semantic.js 921 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040
  1. /*
  2. * # Fomantic UI - 2.8.4
  3. * https://github.com/fomantic/Fomantic-UI
  4. * http://fomantic-ui.com/
  5. *
  6. * Copyright 2014 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. /*!
  12. * # Fomantic-UI - Site
  13. * http://github.com/fomantic/Fomantic-UI/
  14. *
  15. *
  16. * Released under the MIT license
  17. * http://opensource.org/licenses/MIT
  18. *
  19. */
  20. ;(function ($, window, document, undefined) {
  21. $.isFunction = $.isFunction || function(obj) {
  22. return typeof obj === "function" && typeof obj.nodeType !== "number";
  23. };
  24. $.site = $.fn.site = function(parameters) {
  25. var
  26. time = new Date().getTime(),
  27. performance = [],
  28. query = arguments[0],
  29. methodInvoked = (typeof query == 'string'),
  30. queryArguments = [].slice.call(arguments, 1),
  31. settings = ( $.isPlainObject(parameters) )
  32. ? $.extend(true, {}, $.site.settings, parameters)
  33. : $.extend({}, $.site.settings),
  34. namespace = settings.namespace,
  35. error = settings.error,
  36. moduleNamespace = 'module-' + namespace,
  37. $document = $(document),
  38. $module = $document,
  39. element = this,
  40. instance = $module.data(moduleNamespace),
  41. module,
  42. returnedValue
  43. ;
  44. module = {
  45. initialize: function() {
  46. module.instantiate();
  47. },
  48. instantiate: function() {
  49. module.verbose('Storing instance of site', module);
  50. instance = module;
  51. $module
  52. .data(moduleNamespace, module)
  53. ;
  54. },
  55. normalize: function() {
  56. module.fix.console();
  57. module.fix.requestAnimationFrame();
  58. },
  59. fix: {
  60. console: function() {
  61. module.debug('Normalizing window.console');
  62. if (console === undefined || console.log === undefined) {
  63. module.verbose('Console not available, normalizing events');
  64. module.disable.console();
  65. }
  66. if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
  67. module.verbose('Console group not available, normalizing events');
  68. window.console.group = function() {};
  69. window.console.groupEnd = function() {};
  70. window.console.groupCollapsed = function() {};
  71. }
  72. if (typeof console.markTimeline == 'undefined') {
  73. module.verbose('Mark timeline not available, normalizing events');
  74. window.console.markTimeline = function() {};
  75. }
  76. },
  77. consoleClear: function() {
  78. module.debug('Disabling programmatic console clearing');
  79. window.console.clear = function() {};
  80. },
  81. requestAnimationFrame: function() {
  82. module.debug('Normalizing requestAnimationFrame');
  83. if(window.requestAnimationFrame === undefined) {
  84. module.debug('RequestAnimationFrame not available, normalizing event');
  85. window.requestAnimationFrame = window.requestAnimationFrame
  86. || window.mozRequestAnimationFrame
  87. || window.webkitRequestAnimationFrame
  88. || window.msRequestAnimationFrame
  89. || function(callback) { setTimeout(callback, 0); }
  90. ;
  91. }
  92. }
  93. },
  94. moduleExists: function(name) {
  95. return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
  96. },
  97. enabled: {
  98. modules: function(modules) {
  99. var
  100. enabledModules = []
  101. ;
  102. modules = modules || settings.modules;
  103. $.each(modules, function(index, name) {
  104. if(module.moduleExists(name)) {
  105. enabledModules.push(name);
  106. }
  107. });
  108. return enabledModules;
  109. }
  110. },
  111. disabled: {
  112. modules: function(modules) {
  113. var
  114. disabledModules = []
  115. ;
  116. modules = modules || settings.modules;
  117. $.each(modules, function(index, name) {
  118. if(!module.moduleExists(name)) {
  119. disabledModules.push(name);
  120. }
  121. });
  122. return disabledModules;
  123. }
  124. },
  125. change: {
  126. setting: function(setting, value, modules, modifyExisting) {
  127. modules = (typeof modules === 'string')
  128. ? (modules === 'all')
  129. ? settings.modules
  130. : [modules]
  131. : modules || settings.modules
  132. ;
  133. modifyExisting = (modifyExisting !== undefined)
  134. ? modifyExisting
  135. : true
  136. ;
  137. $.each(modules, function(index, name) {
  138. var
  139. namespace = (module.moduleExists(name))
  140. ? $.fn[name].settings.namespace || false
  141. : true,
  142. $existingModules
  143. ;
  144. if(module.moduleExists(name)) {
  145. module.verbose('Changing default setting', setting, value, name);
  146. $.fn[name].settings[setting] = value;
  147. if(modifyExisting && namespace) {
  148. $existingModules = $(':data(module-' + namespace + ')');
  149. if($existingModules.length > 0) {
  150. module.verbose('Modifying existing settings', $existingModules);
  151. $existingModules[name]('setting', setting, value);
  152. }
  153. }
  154. }
  155. });
  156. },
  157. settings: function(newSettings, modules, modifyExisting) {
  158. modules = (typeof modules === 'string')
  159. ? [modules]
  160. : modules || settings.modules
  161. ;
  162. modifyExisting = (modifyExisting !== undefined)
  163. ? modifyExisting
  164. : true
  165. ;
  166. $.each(modules, function(index, name) {
  167. var
  168. $existingModules
  169. ;
  170. if(module.moduleExists(name)) {
  171. module.verbose('Changing default setting', newSettings, name);
  172. $.extend(true, $.fn[name].settings, newSettings);
  173. if(modifyExisting && namespace) {
  174. $existingModules = $(':data(module-' + namespace + ')');
  175. if($existingModules.length > 0) {
  176. module.verbose('Modifying existing settings', $existingModules);
  177. $existingModules[name]('setting', newSettings);
  178. }
  179. }
  180. }
  181. });
  182. }
  183. },
  184. enable: {
  185. console: function() {
  186. module.console(true);
  187. },
  188. debug: function(modules, modifyExisting) {
  189. modules = modules || settings.modules;
  190. module.debug('Enabling debug for modules', modules);
  191. module.change.setting('debug', true, modules, modifyExisting);
  192. },
  193. verbose: function(modules, modifyExisting) {
  194. modules = modules || settings.modules;
  195. module.debug('Enabling verbose debug for modules', modules);
  196. module.change.setting('verbose', true, modules, modifyExisting);
  197. }
  198. },
  199. disable: {
  200. console: function() {
  201. module.console(false);
  202. },
  203. debug: function(modules, modifyExisting) {
  204. modules = modules || settings.modules;
  205. module.debug('Disabling debug for modules', modules);
  206. module.change.setting('debug', false, modules, modifyExisting);
  207. },
  208. verbose: function(modules, modifyExisting) {
  209. modules = modules || settings.modules;
  210. module.debug('Disabling verbose debug for modules', modules);
  211. module.change.setting('verbose', false, modules, modifyExisting);
  212. }
  213. },
  214. console: function(enable) {
  215. if(enable) {
  216. if(instance.cache.console === undefined) {
  217. module.error(error.console);
  218. return;
  219. }
  220. module.debug('Restoring console function');
  221. window.console = instance.cache.console;
  222. }
  223. else {
  224. module.debug('Disabling console function');
  225. instance.cache.console = window.console;
  226. window.console = {
  227. clear : function(){},
  228. error : function(){},
  229. group : function(){},
  230. groupCollapsed : function(){},
  231. groupEnd : function(){},
  232. info : function(){},
  233. log : function(){},
  234. markTimeline : function(){},
  235. warn : function(){}
  236. };
  237. }
  238. },
  239. destroy: function() {
  240. module.verbose('Destroying previous site for', $module);
  241. $module
  242. .removeData(moduleNamespace)
  243. ;
  244. },
  245. cache: {},
  246. setting: function(name, value) {
  247. if( $.isPlainObject(name) ) {
  248. $.extend(true, settings, name);
  249. }
  250. else if(value !== undefined) {
  251. settings[name] = value;
  252. }
  253. else {
  254. return settings[name];
  255. }
  256. },
  257. internal: function(name, value) {
  258. if( $.isPlainObject(name) ) {
  259. $.extend(true, module, name);
  260. }
  261. else if(value !== undefined) {
  262. module[name] = value;
  263. }
  264. else {
  265. return module[name];
  266. }
  267. },
  268. debug: function() {
  269. if(settings.debug) {
  270. if(settings.performance) {
  271. module.performance.log(arguments);
  272. }
  273. else {
  274. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  275. module.debug.apply(console, arguments);
  276. }
  277. }
  278. },
  279. verbose: function() {
  280. if(settings.verbose && settings.debug) {
  281. if(settings.performance) {
  282. module.performance.log(arguments);
  283. }
  284. else {
  285. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  286. module.verbose.apply(console, arguments);
  287. }
  288. }
  289. },
  290. error: function() {
  291. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  292. module.error.apply(console, arguments);
  293. },
  294. performance: {
  295. log: function(message) {
  296. var
  297. currentTime,
  298. executionTime,
  299. previousTime
  300. ;
  301. if(settings.performance) {
  302. currentTime = new Date().getTime();
  303. previousTime = time || currentTime;
  304. executionTime = currentTime - previousTime;
  305. time = currentTime;
  306. performance.push({
  307. 'Element' : element,
  308. 'Name' : message[0],
  309. 'Arguments' : [].slice.call(message, 1) || '',
  310. 'Execution Time' : executionTime
  311. });
  312. }
  313. clearTimeout(module.performance.timer);
  314. module.performance.timer = setTimeout(module.performance.display, 500);
  315. },
  316. display: function() {
  317. var
  318. title = settings.name + ':',
  319. totalTime = 0
  320. ;
  321. time = false;
  322. clearTimeout(module.performance.timer);
  323. $.each(performance, function(index, data) {
  324. totalTime += data['Execution Time'];
  325. });
  326. title += ' ' + totalTime + 'ms';
  327. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  328. console.groupCollapsed(title);
  329. if(console.table) {
  330. console.table(performance);
  331. }
  332. else {
  333. $.each(performance, function(index, data) {
  334. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  335. });
  336. }
  337. console.groupEnd();
  338. }
  339. performance = [];
  340. }
  341. },
  342. invoke: function(query, passedArguments, context) {
  343. var
  344. object = instance,
  345. maxDepth,
  346. found,
  347. response
  348. ;
  349. passedArguments = passedArguments || queryArguments;
  350. context = element || context;
  351. if(typeof query == 'string' && object !== undefined) {
  352. query = query.split(/[\. ]/);
  353. maxDepth = query.length - 1;
  354. $.each(query, function(depth, value) {
  355. var camelCaseValue = (depth != maxDepth)
  356. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  357. : query
  358. ;
  359. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  360. object = object[camelCaseValue];
  361. }
  362. else if( object[camelCaseValue] !== undefined ) {
  363. found = object[camelCaseValue];
  364. return false;
  365. }
  366. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  367. object = object[value];
  368. }
  369. else if( object[value] !== undefined ) {
  370. found = object[value];
  371. return false;
  372. }
  373. else {
  374. module.error(error.method, query);
  375. return false;
  376. }
  377. });
  378. }
  379. if ( $.isFunction( found ) ) {
  380. response = found.apply(context, passedArguments);
  381. }
  382. else if(found !== undefined) {
  383. response = found;
  384. }
  385. if(Array.isArray(returnedValue)) {
  386. returnedValue.push(response);
  387. }
  388. else if(returnedValue !== undefined) {
  389. returnedValue = [returnedValue, response];
  390. }
  391. else if(response !== undefined) {
  392. returnedValue = response;
  393. }
  394. return found;
  395. }
  396. };
  397. if(methodInvoked) {
  398. if(instance === undefined) {
  399. module.initialize();
  400. }
  401. module.invoke(query);
  402. }
  403. else {
  404. if(instance !== undefined) {
  405. module.destroy();
  406. }
  407. module.initialize();
  408. }
  409. return (returnedValue !== undefined)
  410. ? returnedValue
  411. : this
  412. ;
  413. };
  414. $.site.settings = {
  415. name : 'Site',
  416. namespace : 'site',
  417. error : {
  418. console : 'Console cannot be restored, most likely it was overwritten outside of module',
  419. method : 'The method you called is not defined.'
  420. },
  421. debug : false,
  422. verbose : false,
  423. performance : true,
  424. modules: [
  425. 'accordion',
  426. 'api',
  427. 'calendar',
  428. 'checkbox',
  429. 'dimmer',
  430. 'dropdown',
  431. 'embed',
  432. 'form',
  433. 'modal',
  434. 'nag',
  435. 'popup',
  436. 'slider',
  437. 'rating',
  438. 'shape',
  439. 'sidebar',
  440. 'state',
  441. 'sticky',
  442. 'tab',
  443. 'toast',
  444. 'transition',
  445. 'visibility',
  446. 'visit'
  447. ],
  448. siteNamespace : 'site',
  449. namespaceStub : {
  450. cache : {},
  451. config : {},
  452. sections : {},
  453. section : {},
  454. utilities : {}
  455. }
  456. };
  457. // allows for selection of elements with data attributes
  458. $.extend($.expr[ ":" ], {
  459. data: ($.expr.createPseudo)
  460. ? $.expr.createPseudo(function(dataName) {
  461. return function(elem) {
  462. return !!$.data(elem, dataName);
  463. };
  464. })
  465. : function(elem, i, match) {
  466. // support: jQuery < 1.8
  467. return !!$.data(elem, match[ 3 ]);
  468. }
  469. });
  470. })( jQuery, window, document );
  471. /*!
  472. * # Fomantic-UI - Form Validation
  473. * http://github.com/fomantic/Fomantic-UI/
  474. *
  475. *
  476. * Released under the MIT license
  477. * http://opensource.org/licenses/MIT
  478. *
  479. */
  480. ;(function ($, window, document, undefined) {
  481. 'use strict';
  482. $.isFunction = $.isFunction || function(obj) {
  483. return typeof obj === "function" && typeof obj.nodeType !== "number";
  484. };
  485. window = (typeof window != 'undefined' && window.Math == Math)
  486. ? window
  487. : (typeof self != 'undefined' && self.Math == Math)
  488. ? self
  489. : Function('return this')()
  490. ;
  491. $.fn.form = function(parameters) {
  492. var
  493. $allModules = $(this),
  494. moduleSelector = $allModules.selector || '',
  495. time = new Date().getTime(),
  496. performance = [],
  497. query = arguments[0],
  498. legacyParameters = arguments[1],
  499. methodInvoked = (typeof query == 'string'),
  500. queryArguments = [].slice.call(arguments, 1),
  501. returnedValue
  502. ;
  503. $allModules
  504. .each(function() {
  505. var
  506. $module = $(this),
  507. element = this,
  508. formErrors = [],
  509. keyHeldDown = false,
  510. // set at run-time
  511. $field,
  512. $group,
  513. $message,
  514. $prompt,
  515. $submit,
  516. $clear,
  517. $reset,
  518. settings,
  519. validation,
  520. metadata,
  521. selector,
  522. className,
  523. regExp,
  524. error,
  525. namespace,
  526. moduleNamespace,
  527. eventNamespace,
  528. submitting = false,
  529. dirty = false,
  530. history = ['clean', 'clean'],
  531. instance,
  532. module
  533. ;
  534. module = {
  535. initialize: function() {
  536. // settings grabbed at run time
  537. module.get.settings();
  538. if(methodInvoked) {
  539. if(instance === undefined) {
  540. module.instantiate();
  541. }
  542. module.invoke(query);
  543. }
  544. else {
  545. if(instance !== undefined) {
  546. instance.invoke('destroy');
  547. }
  548. module.verbose('Initializing form validation', $module, settings);
  549. module.bindEvents();
  550. module.set.defaults();
  551. if (settings.autoCheckRequired) {
  552. module.set.autoCheck();
  553. }
  554. module.instantiate();
  555. }
  556. },
  557. instantiate: function() {
  558. module.verbose('Storing instance of module', module);
  559. instance = module;
  560. $module
  561. .data(moduleNamespace, module)
  562. ;
  563. },
  564. destroy: function() {
  565. module.verbose('Destroying previous module', instance);
  566. module.removeEvents();
  567. $module
  568. .removeData(moduleNamespace)
  569. ;
  570. },
  571. refresh: function() {
  572. module.verbose('Refreshing selector cache');
  573. $field = $module.find(selector.field);
  574. $group = $module.find(selector.group);
  575. $message = $module.find(selector.message);
  576. $prompt = $module.find(selector.prompt);
  577. $submit = $module.find(selector.submit);
  578. $clear = $module.find(selector.clear);
  579. $reset = $module.find(selector.reset);
  580. },
  581. submit: function() {
  582. module.verbose('Submitting form', $module);
  583. submitting = true;
  584. $module.submit();
  585. },
  586. attachEvents: function(selector, action) {
  587. action = action || 'submit';
  588. $(selector).on('click' + eventNamespace, function(event) {
  589. module[action]();
  590. event.preventDefault();
  591. });
  592. },
  593. bindEvents: function() {
  594. module.verbose('Attaching form events');
  595. $module
  596. .on('submit' + eventNamespace, module.validate.form)
  597. .on('blur' + eventNamespace, selector.field, module.event.field.blur)
  598. .on('click' + eventNamespace, selector.submit, module.submit)
  599. .on('click' + eventNamespace, selector.reset, module.reset)
  600. .on('click' + eventNamespace, selector.clear, module.clear)
  601. ;
  602. if(settings.keyboardShortcuts) {
  603. $module.on('keydown' + eventNamespace, selector.field, module.event.field.keydown);
  604. }
  605. $field.each(function(index, el) {
  606. var
  607. $input = $(el),
  608. type = $input.prop('type'),
  609. inputEvent = module.get.changeEvent(type, $input)
  610. ;
  611. $input.on(inputEvent + eventNamespace, module.event.field.change);
  612. });
  613. // Dirty events
  614. if (settings.preventLeaving) {
  615. $(window).on('beforeunload' + eventNamespace, module.event.beforeUnload);
  616. }
  617. $field.on('change click keyup keydown blur', function(e) {
  618. $(this).triggerHandler(e.type + ".dirty");
  619. });
  620. $field.on('change.dirty click.dirty keyup.dirty keydown.dirty blur.dirty', module.determine.isDirty);
  621. $module.on('dirty' + eventNamespace, function(e) {
  622. settings.onDirty.call();
  623. });
  624. $module.on('clean' + eventNamespace, function(e) {
  625. settings.onClean.call();
  626. })
  627. },
  628. clear: function() {
  629. $field.each(function (index, el) {
  630. var
  631. $field = $(el),
  632. $element = $field.parent(),
  633. $fieldGroup = $field.closest($group),
  634. $prompt = $fieldGroup.find(selector.prompt),
  635. $calendar = $field.closest(selector.uiCalendar),
  636. defaultValue = $field.data(metadata.defaultValue) || '',
  637. isCheckbox = $element.is(selector.uiCheckbox),
  638. isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
  639. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  640. isErrored = $fieldGroup.hasClass(className.error)
  641. ;
  642. if(isErrored) {
  643. module.verbose('Resetting error on field', $fieldGroup);
  644. $fieldGroup.removeClass(className.error);
  645. $prompt.remove();
  646. }
  647. if(isDropdown) {
  648. module.verbose('Resetting dropdown value', $element, defaultValue);
  649. $element.dropdown('clear', true);
  650. }
  651. else if(isCheckbox) {
  652. $field.prop('checked', false);
  653. }
  654. else if (isCalendar) {
  655. $calendar.calendar('clear');
  656. }
  657. else {
  658. module.verbose('Resetting field value', $field, defaultValue);
  659. $field.val('');
  660. }
  661. });
  662. },
  663. reset: function() {
  664. $field.each(function (index, el) {
  665. var
  666. $field = $(el),
  667. $element = $field.parent(),
  668. $fieldGroup = $field.closest($group),
  669. $calendar = $field.closest(selector.uiCalendar),
  670. $prompt = $fieldGroup.find(selector.prompt),
  671. defaultValue = $field.data(metadata.defaultValue),
  672. isCheckbox = $element.is(selector.uiCheckbox),
  673. isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
  674. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  675. isErrored = $fieldGroup.hasClass(className.error)
  676. ;
  677. if(defaultValue === undefined) {
  678. return;
  679. }
  680. if(isErrored) {
  681. module.verbose('Resetting error on field', $fieldGroup);
  682. $fieldGroup.removeClass(className.error);
  683. $prompt.remove();
  684. }
  685. if(isDropdown) {
  686. module.verbose('Resetting dropdown value', $element, defaultValue);
  687. $element.dropdown('restore defaults', true);
  688. }
  689. else if(isCheckbox) {
  690. module.verbose('Resetting checkbox value', $element, defaultValue);
  691. $field.prop('checked', defaultValue);
  692. }
  693. else if (isCalendar) {
  694. $calendar.calendar('set date', defaultValue);
  695. }
  696. else {
  697. module.verbose('Resetting field value', $field, defaultValue);
  698. $field.val(defaultValue);
  699. }
  700. });
  701. module.determine.isDirty();
  702. },
  703. determine: {
  704. isValid: function() {
  705. var
  706. allValid = true
  707. ;
  708. $.each(validation, function(fieldName, field) {
  709. if( !( module.validate.field(field, fieldName, true) ) ) {
  710. allValid = false;
  711. }
  712. });
  713. return allValid;
  714. },
  715. isDirty: function(e) {
  716. var formIsDirty = false;
  717. $field.each(function(index, el) {
  718. var
  719. $el = $(el),
  720. isCheckbox = ($el.filter(selector.checkbox).length > 0),
  721. isDirty
  722. ;
  723. if (isCheckbox) {
  724. isDirty = module.is.checkboxDirty($el);
  725. } else {
  726. isDirty = module.is.fieldDirty($el);
  727. }
  728. $el.data(settings.metadata.isDirty, isDirty);
  729. formIsDirty |= isDirty;
  730. });
  731. if (formIsDirty) {
  732. module.set.dirty();
  733. } else {
  734. module.set.clean();
  735. }
  736. if (e && e.namespace === 'dirty') {
  737. e.stopImmediatePropagation();
  738. e.preventDefault();
  739. }
  740. }
  741. },
  742. is: {
  743. bracketedRule: function(rule) {
  744. return (rule.type && rule.type.match(settings.regExp.bracket));
  745. },
  746. shorthandFields: function(fields) {
  747. var
  748. fieldKeys = Object.keys(fields),
  749. firstRule = fields[fieldKeys[0]]
  750. ;
  751. return module.is.shorthandRules(firstRule);
  752. },
  753. // duck type rule test
  754. shorthandRules: function(rules) {
  755. return (typeof rules == 'string' || Array.isArray(rules));
  756. },
  757. empty: function($field) {
  758. if(!$field || $field.length === 0) {
  759. return true;
  760. }
  761. else if($field.is(selector.checkbox)) {
  762. return !$field.is(':checked');
  763. }
  764. else {
  765. return module.is.blank($field);
  766. }
  767. },
  768. blank: function($field) {
  769. return $.trim($field.val()) === '';
  770. },
  771. valid: function(field) {
  772. var
  773. allValid = true
  774. ;
  775. if(field) {
  776. module.verbose('Checking if field is valid', field);
  777. return module.validate.field(validation[field], field, false);
  778. }
  779. else {
  780. module.verbose('Checking if form is valid');
  781. $.each(validation, function(fieldName, field) {
  782. if( !module.is.valid(fieldName) ) {
  783. allValid = false;
  784. }
  785. });
  786. return allValid;
  787. }
  788. },
  789. dirty: function() {
  790. return dirty;
  791. },
  792. clean: function() {
  793. return !dirty;
  794. },
  795. fieldDirty: function($el) {
  796. var initialValue = $el.data(metadata.defaultValue);
  797. // Explicitly check for null/undefined here as value may be `false`, so ($el.data(dataInitialValue) || '') would not work
  798. if (initialValue == null) { initialValue = ''; }
  799. var currentValue = $el.val();
  800. if (currentValue == null) { currentValue = ''; }
  801. // Boolean values can be encoded as "true/false" or "True/False" depending on underlying frameworks so we need a case insensitive comparison
  802. var boolRegex = /^(true|false)$/i;
  803. var isBoolValue = boolRegex.test(initialValue) && boolRegex.test(currentValue);
  804. if (isBoolValue) {
  805. var regex = new RegExp("^" + initialValue + "$", "i");
  806. return !regex.test(currentValue);
  807. }
  808. return currentValue !== initialValue;
  809. },
  810. checkboxDirty: function($el) {
  811. var initialValue = $el.data(metadata.defaultValue);
  812. var currentValue = $el.is(":checked");
  813. return initialValue !== currentValue;
  814. },
  815. justDirty: function() {
  816. return (history[0] === 'dirty');
  817. },
  818. justClean: function() {
  819. return (history[0] === 'clean');
  820. }
  821. },
  822. removeEvents: function() {
  823. $module.off(eventNamespace);
  824. $field.off(eventNamespace);
  825. $submit.off(eventNamespace);
  826. $field.off(eventNamespace);
  827. },
  828. event: {
  829. field: {
  830. keydown: function(event) {
  831. var
  832. $field = $(this),
  833. key = event.which,
  834. isInput = $field.is(selector.input),
  835. isCheckbox = $field.is(selector.checkbox),
  836. isInDropdown = ($field.closest(selector.uiDropdown).length > 0),
  837. keyCode = {
  838. enter : 13,
  839. escape : 27
  840. }
  841. ;
  842. if( key == keyCode.escape) {
  843. module.verbose('Escape key pressed blurring field');
  844. $field
  845. .blur()
  846. ;
  847. }
  848. if(!event.ctrlKey && key == keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
  849. if(!keyHeldDown) {
  850. $field.one('keyup' + eventNamespace, module.event.field.keyup);
  851. module.submit();
  852. module.debug('Enter pressed on input submitting form');
  853. }
  854. keyHeldDown = true;
  855. }
  856. },
  857. keyup: function() {
  858. keyHeldDown = false;
  859. },
  860. blur: function(event) {
  861. var
  862. $field = $(this),
  863. $fieldGroup = $field.closest($group),
  864. validationRules = module.get.validation($field)
  865. ;
  866. if( $fieldGroup.hasClass(className.error) ) {
  867. module.debug('Revalidating field', $field, validationRules);
  868. if(validationRules) {
  869. module.validate.field( validationRules );
  870. }
  871. }
  872. else if(settings.on == 'blur') {
  873. if(validationRules) {
  874. module.validate.field( validationRules );
  875. }
  876. }
  877. },
  878. change: function(event) {
  879. var
  880. $field = $(this),
  881. $fieldGroup = $field.closest($group),
  882. validationRules = module.get.validation($field)
  883. ;
  884. if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
  885. clearTimeout(module.timer);
  886. module.timer = setTimeout(function() {
  887. module.debug('Revalidating field', $field, module.get.validation($field));
  888. module.validate.field( validationRules );
  889. }, settings.delay);
  890. }
  891. }
  892. },
  893. beforeUnload: function(event) {
  894. if (module.is.dirty() && !submitting) {
  895. var event = event || window.event;
  896. // For modern browsers
  897. if (event) {
  898. event.returnValue = settings.text.leavingMessage;
  899. }
  900. // For olders...
  901. return settings.text.leavingMessage;
  902. }
  903. }
  904. },
  905. get: {
  906. ancillaryValue: function(rule) {
  907. if(!rule.type || (!rule.value && !module.is.bracketedRule(rule))) {
  908. return false;
  909. }
  910. return (rule.value !== undefined)
  911. ? rule.value
  912. : rule.type.match(settings.regExp.bracket)[1] + ''
  913. ;
  914. },
  915. ruleName: function(rule) {
  916. if( module.is.bracketedRule(rule) ) {
  917. return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
  918. }
  919. return rule.type;
  920. },
  921. changeEvent: function(type, $input) {
  922. if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
  923. return 'change';
  924. }
  925. else {
  926. return module.get.inputEvent();
  927. }
  928. },
  929. inputEvent: function() {
  930. return (document.createElement('input').oninput !== undefined)
  931. ? 'input'
  932. : (document.createElement('input').onpropertychange !== undefined)
  933. ? 'propertychange'
  934. : 'keyup'
  935. ;
  936. },
  937. fieldsFromShorthand: function(fields) {
  938. var
  939. fullFields = {}
  940. ;
  941. $.each(fields, function(name, rules) {
  942. if(typeof rules == 'string') {
  943. rules = [rules];
  944. }
  945. fullFields[name] = {
  946. rules: []
  947. };
  948. $.each(rules, function(index, rule) {
  949. fullFields[name].rules.push({ type: rule });
  950. });
  951. });
  952. return fullFields;
  953. },
  954. prompt: function(rule, field) {
  955. var
  956. ruleName = module.get.ruleName(rule),
  957. ancillary = module.get.ancillaryValue(rule),
  958. $field = module.get.field(field.identifier),
  959. value = $field.val(),
  960. prompt = $.isFunction(rule.prompt)
  961. ? rule.prompt(value)
  962. : rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
  963. requiresValue = (prompt.search('{value}') !== -1),
  964. requiresName = (prompt.search('{name}') !== -1),
  965. $label,
  966. name
  967. ;
  968. if(requiresValue) {
  969. prompt = prompt.replace(/\{value\}/g, $field.val());
  970. }
  971. if(requiresName) {
  972. $label = $field.closest(selector.group).find('label').eq(0);
  973. name = ($label.length == 1)
  974. ? $label.text()
  975. : $field.prop('placeholder') || settings.text.unspecifiedField
  976. ;
  977. prompt = prompt.replace(/\{name\}/g, name);
  978. }
  979. prompt = prompt.replace(/\{identifier\}/g, field.identifier);
  980. prompt = prompt.replace(/\{ruleValue\}/g, ancillary);
  981. if(!rule.prompt) {
  982. module.verbose('Using default validation prompt for type', prompt, ruleName);
  983. }
  984. return prompt;
  985. },
  986. settings: function() {
  987. if($.isPlainObject(parameters)) {
  988. var
  989. keys = Object.keys(parameters),
  990. isLegacySettings = (keys.length > 0)
  991. ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
  992. : false
  993. ;
  994. if(isLegacySettings) {
  995. // 1.x (ducktyped)
  996. settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
  997. validation = $.extend({}, $.fn.form.settings.defaults, parameters);
  998. module.error(settings.error.oldSyntax, element);
  999. module.verbose('Extending settings from legacy parameters', validation, settings);
  1000. }
  1001. else {
  1002. // 2.x
  1003. if(parameters.fields && module.is.shorthandFields(parameters.fields)) {
  1004. parameters.fields = module.get.fieldsFromShorthand(parameters.fields);
  1005. }
  1006. settings = $.extend(true, {}, $.fn.form.settings, parameters);
  1007. validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
  1008. module.verbose('Extending settings', validation, settings);
  1009. }
  1010. }
  1011. else {
  1012. settings = $.fn.form.settings;
  1013. validation = $.fn.form.settings.defaults;
  1014. module.verbose('Using default form validation', validation, settings);
  1015. }
  1016. // shorthand
  1017. namespace = settings.namespace;
  1018. metadata = settings.metadata;
  1019. selector = settings.selector;
  1020. className = settings.className;
  1021. regExp = settings.regExp;
  1022. error = settings.error;
  1023. moduleNamespace = 'module-' + namespace;
  1024. eventNamespace = '.' + namespace;
  1025. // grab instance
  1026. instance = $module.data(moduleNamespace);
  1027. // refresh selector cache
  1028. module.refresh();
  1029. },
  1030. field: function(identifier) {
  1031. module.verbose('Finding field with identifier', identifier);
  1032. identifier = module.escape.string(identifier);
  1033. var t;
  1034. if((t=$field.filter('#' + identifier)).length > 0 ) {
  1035. return t;
  1036. }
  1037. if((t=$field.filter('[name="' + identifier +'"]')).length > 0 ) {
  1038. return t;
  1039. }
  1040. if((t=$field.filter('[name="' + identifier +'[]"]')).length > 0 ) {
  1041. return t;
  1042. }
  1043. if((t=$field.filter('[data-' + metadata.validate + '="'+ identifier +'"]')).length > 0 ) {
  1044. return t;
  1045. }
  1046. return $('<input/>');
  1047. },
  1048. fields: function(fields) {
  1049. var
  1050. $fields = $()
  1051. ;
  1052. $.each(fields, function(index, name) {
  1053. $fields = $fields.add( module.get.field(name) );
  1054. });
  1055. return $fields;
  1056. },
  1057. validation: function($field) {
  1058. var
  1059. fieldValidation,
  1060. identifier
  1061. ;
  1062. if(!validation) {
  1063. return false;
  1064. }
  1065. $.each(validation, function(fieldName, field) {
  1066. identifier = field.identifier || fieldName;
  1067. $.each(module.get.field(identifier), function(index, groupField) {
  1068. if(groupField == $field[0]) {
  1069. field.identifier = identifier;
  1070. fieldValidation = field;
  1071. return false;
  1072. }
  1073. });
  1074. });
  1075. return fieldValidation || false;
  1076. },
  1077. value: function (field) {
  1078. var
  1079. fields = [],
  1080. results
  1081. ;
  1082. fields.push(field);
  1083. results = module.get.values.call(element, fields);
  1084. return results[field];
  1085. },
  1086. values: function (fields) {
  1087. var
  1088. $fields = Array.isArray(fields)
  1089. ? module.get.fields(fields)
  1090. : $field,
  1091. values = {}
  1092. ;
  1093. $fields.each(function(index, field) {
  1094. var
  1095. $field = $(field),
  1096. $calendar = $field.closest(selector.uiCalendar),
  1097. name = $field.prop('name'),
  1098. value = $field.val(),
  1099. isCheckbox = $field.is(selector.checkbox),
  1100. isRadio = $field.is(selector.radio),
  1101. isMultiple = (name.indexOf('[]') !== -1),
  1102. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  1103. isChecked = (isCheckbox)
  1104. ? $field.is(':checked')
  1105. : false
  1106. ;
  1107. if(name) {
  1108. if(isMultiple) {
  1109. name = name.replace('[]', '');
  1110. if(!values[name]) {
  1111. values[name] = [];
  1112. }
  1113. if(isCheckbox) {
  1114. if(isChecked) {
  1115. values[name].push(value || true);
  1116. }
  1117. else {
  1118. values[name].push(false);
  1119. }
  1120. }
  1121. else {
  1122. values[name].push(value);
  1123. }
  1124. }
  1125. else {
  1126. if(isRadio) {
  1127. if(values[name] === undefined || values[name] === false) {
  1128. values[name] = (isChecked)
  1129. ? value || true
  1130. : false
  1131. ;
  1132. }
  1133. }
  1134. else if(isCheckbox) {
  1135. if(isChecked) {
  1136. values[name] = value || true;
  1137. }
  1138. else {
  1139. values[name] = false;
  1140. }
  1141. }
  1142. else if(isCalendar) {
  1143. var date = $calendar.calendar('get date');
  1144. if (date !== null) {
  1145. if (settings.dateHandling == 'date') {
  1146. values[name] = date;
  1147. } else if(settings.dateHandling == 'input') {
  1148. values[name] = $calendar.calendar('get input date')
  1149. } else if (settings.dateHandling == 'formatter') {
  1150. var type = $calendar.calendar('setting', 'type');
  1151. switch(type) {
  1152. case 'date':
  1153. values[name] = settings.formatter.date(date);
  1154. break;
  1155. case 'datetime':
  1156. values[name] = settings.formatter.datetime(date);
  1157. break;
  1158. case 'time':
  1159. values[name] = settings.formatter.time(date);
  1160. break;
  1161. case 'month':
  1162. values[name] = settings.formatter.month(date);
  1163. break;
  1164. case 'year':
  1165. values[name] = settings.formatter.year(date);
  1166. break;
  1167. default:
  1168. module.debug('Wrong calendar mode', $calendar, type);
  1169. values[name] = '';
  1170. }
  1171. }
  1172. } else {
  1173. values[name] = '';
  1174. }
  1175. } else {
  1176. values[name] = value;
  1177. }
  1178. }
  1179. }
  1180. });
  1181. return values;
  1182. },
  1183. dirtyFields: function() {
  1184. return $field.filter(function(index, e) {
  1185. return $(e).data(metadata.isDirty);
  1186. });
  1187. }
  1188. },
  1189. has: {
  1190. field: function(identifier) {
  1191. module.verbose('Checking for existence of a field with identifier', identifier);
  1192. identifier = module.escape.string(identifier);
  1193. if(typeof identifier !== 'string') {
  1194. module.error(error.identifier, identifier);
  1195. }
  1196. if($field.filter('#' + identifier).length > 0 ) {
  1197. return true;
  1198. }
  1199. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  1200. return true;
  1201. }
  1202. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  1203. return true;
  1204. }
  1205. return false;
  1206. }
  1207. },
  1208. can: {
  1209. useElement: function(element){
  1210. if ($.fn[element] !== undefined) {
  1211. return true;
  1212. }
  1213. module.error(error.noElement.replace('{element}',element));
  1214. return false;
  1215. }
  1216. },
  1217. escape: {
  1218. string: function(text) {
  1219. text = String(text);
  1220. return text.replace(regExp.escape, '\\$&');
  1221. }
  1222. },
  1223. add: {
  1224. // alias
  1225. rule: function(name, rules) {
  1226. module.add.field(name, rules);
  1227. },
  1228. field: function(name, rules) {
  1229. // Validation should have at least a standard format
  1230. if(validation[name] === undefined || validation[name].rules === undefined) {
  1231. validation[name] = {
  1232. rules: []
  1233. };
  1234. }
  1235. var
  1236. newValidation = {
  1237. rules: []
  1238. }
  1239. ;
  1240. if(module.is.shorthandRules(rules)) {
  1241. rules = Array.isArray(rules)
  1242. ? rules
  1243. : [rules]
  1244. ;
  1245. $.each(rules, function(_index, rule) {
  1246. newValidation.rules.push({ type: rule });
  1247. });
  1248. }
  1249. else {
  1250. newValidation.rules = rules.rules;
  1251. }
  1252. // For each new rule, check if there's not already one with the same type
  1253. $.each(newValidation.rules, function (_index, rule) {
  1254. if ($.grep(validation[name].rules, function(item){ return item.type == rule.type; }).length == 0) {
  1255. validation[name].rules.push(rule);
  1256. }
  1257. });
  1258. module.debug('Adding rules', newValidation.rules, validation);
  1259. },
  1260. fields: function(fields) {
  1261. var
  1262. newValidation
  1263. ;
  1264. if(fields && module.is.shorthandFields(fields)) {
  1265. newValidation = module.get.fieldsFromShorthand(fields);
  1266. }
  1267. else {
  1268. newValidation = fields;
  1269. }
  1270. validation = $.extend({}, validation, newValidation);
  1271. },
  1272. prompt: function(identifier, errors, internal) {
  1273. var
  1274. $field = module.get.field(identifier),
  1275. $fieldGroup = $field.closest($group),
  1276. $prompt = $fieldGroup.children(selector.prompt),
  1277. promptExists = ($prompt.length !== 0)
  1278. ;
  1279. errors = (typeof errors == 'string')
  1280. ? [errors]
  1281. : errors
  1282. ;
  1283. module.verbose('Adding field error state', identifier);
  1284. if(!internal) {
  1285. $fieldGroup
  1286. .addClass(className.error)
  1287. ;
  1288. }
  1289. if(settings.inline) {
  1290. if(!promptExists) {
  1291. $prompt = settings.templates.prompt(errors, className.label);
  1292. $prompt
  1293. .appendTo($fieldGroup)
  1294. ;
  1295. }
  1296. $prompt
  1297. .html(errors[0])
  1298. ;
  1299. if(!promptExists) {
  1300. if(settings.transition && module.can.useElement('transition') && $module.transition('is supported')) {
  1301. module.verbose('Displaying error with css transition', settings.transition);
  1302. $prompt.transition(settings.transition + ' in', settings.duration);
  1303. }
  1304. else {
  1305. module.verbose('Displaying error with fallback javascript animation');
  1306. $prompt
  1307. .fadeIn(settings.duration)
  1308. ;
  1309. }
  1310. }
  1311. else {
  1312. module.verbose('Inline errors are disabled, no inline error added', identifier);
  1313. }
  1314. }
  1315. },
  1316. errors: function(errors) {
  1317. module.debug('Adding form error messages', errors);
  1318. module.set.error();
  1319. $message
  1320. .html( settings.templates.error(errors) )
  1321. ;
  1322. }
  1323. },
  1324. remove: {
  1325. rule: function(field, rule) {
  1326. var
  1327. rules = Array.isArray(rule)
  1328. ? rule
  1329. : [rule]
  1330. ;
  1331. if(validation[field] === undefined || !Array.isArray(validation[field].rules)) {
  1332. return;
  1333. }
  1334. if(rule === undefined) {
  1335. module.debug('Removed all rules');
  1336. validation[field].rules = [];
  1337. return;
  1338. }
  1339. $.each(validation[field].rules, function(index, rule) {
  1340. if(rule && rules.indexOf(rule.type) !== -1) {
  1341. module.debug('Removed rule', rule.type);
  1342. validation[field].rules.splice(index, 1);
  1343. }
  1344. });
  1345. },
  1346. field: function(field) {
  1347. var
  1348. fields = Array.isArray(field)
  1349. ? field
  1350. : [field]
  1351. ;
  1352. $.each(fields, function(index, field) {
  1353. module.remove.rule(field);
  1354. });
  1355. },
  1356. // alias
  1357. rules: function(field, rules) {
  1358. if(Array.isArray(field)) {
  1359. $.each(field, function(index, field) {
  1360. module.remove.rule(field, rules);
  1361. });
  1362. }
  1363. else {
  1364. module.remove.rule(field, rules);
  1365. }
  1366. },
  1367. fields: function(fields) {
  1368. module.remove.field(fields);
  1369. },
  1370. prompt: function(identifier) {
  1371. var
  1372. $field = module.get.field(identifier),
  1373. $fieldGroup = $field.closest($group),
  1374. $prompt = $fieldGroup.children(selector.prompt)
  1375. ;
  1376. $fieldGroup
  1377. .removeClass(className.error)
  1378. ;
  1379. if(settings.inline && $prompt.is(':visible')) {
  1380. module.verbose('Removing prompt for field', identifier);
  1381. if(settings.transition && module.can.useElement('transition') && $module.transition('is supported')) {
  1382. $prompt.transition(settings.transition + ' out', settings.duration, function() {
  1383. $prompt.remove();
  1384. });
  1385. }
  1386. else {
  1387. $prompt
  1388. .fadeOut(settings.duration, function(){
  1389. $prompt.remove();
  1390. })
  1391. ;
  1392. }
  1393. }
  1394. }
  1395. },
  1396. set: {
  1397. success: function() {
  1398. $module
  1399. .removeClass(className.error)
  1400. .addClass(className.success)
  1401. ;
  1402. },
  1403. defaults: function () {
  1404. $field.each(function (index, el) {
  1405. var
  1406. $el = $(el),
  1407. $parent = $el.parent(),
  1408. isCheckbox = ($el.filter(selector.checkbox).length > 0),
  1409. isDropdown = $parent.is(selector.uiDropdown) && module.can.useElement('dropdown'),
  1410. $calendar = $el.closest(selector.uiCalendar),
  1411. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  1412. value = (isCheckbox)
  1413. ? $el.is(':checked')
  1414. : $el.val()
  1415. ;
  1416. if (isDropdown) {
  1417. $parent.dropdown('save defaults');
  1418. }
  1419. else if (isCalendar) {
  1420. $calendar.calendar('refresh');
  1421. }
  1422. $el.data(metadata.defaultValue, value);
  1423. $el.data(metadata.isDirty, false);
  1424. });
  1425. },
  1426. error: function() {
  1427. $module
  1428. .removeClass(className.success)
  1429. .addClass(className.error)
  1430. ;
  1431. },
  1432. value: function (field, value) {
  1433. var
  1434. fields = {}
  1435. ;
  1436. fields[field] = value;
  1437. return module.set.values.call(element, fields);
  1438. },
  1439. values: function (fields) {
  1440. if($.isEmptyObject(fields)) {
  1441. return;
  1442. }
  1443. $.each(fields, function(key, value) {
  1444. var
  1445. $field = module.get.field(key),
  1446. $element = $field.parent(),
  1447. $calendar = $field.closest(selector.uiCalendar),
  1448. isMultiple = Array.isArray(value),
  1449. isCheckbox = $element.is(selector.uiCheckbox) && module.can.useElement('checkbox'),
  1450. isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
  1451. isRadio = ($field.is(selector.radio) && isCheckbox),
  1452. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  1453. fieldExists = ($field.length > 0),
  1454. $multipleField
  1455. ;
  1456. if(fieldExists) {
  1457. if(isMultiple && isCheckbox) {
  1458. module.verbose('Selecting multiple', value, $field);
  1459. $element.checkbox('uncheck');
  1460. $.each(value, function(index, value) {
  1461. $multipleField = $field.filter('[value="' + value + '"]');
  1462. $element = $multipleField.parent();
  1463. if($multipleField.length > 0) {
  1464. $element.checkbox('check');
  1465. }
  1466. });
  1467. }
  1468. else if(isRadio) {
  1469. module.verbose('Selecting radio value', value, $field);
  1470. $field.filter('[value="' + value + '"]')
  1471. .parent(selector.uiCheckbox)
  1472. .checkbox('check')
  1473. ;
  1474. }
  1475. else if(isCheckbox) {
  1476. module.verbose('Setting checkbox value', value, $element);
  1477. if(value === true || value === 1) {
  1478. $element.checkbox('check');
  1479. }
  1480. else {
  1481. $element.checkbox('uncheck');
  1482. }
  1483. }
  1484. else if(isDropdown) {
  1485. module.verbose('Setting dropdown value', value, $element);
  1486. $element.dropdown('set selected', value);
  1487. }
  1488. else if (isCalendar) {
  1489. $calendar.calendar('set date',value);
  1490. }
  1491. else {
  1492. module.verbose('Setting field value', value, $field);
  1493. $field.val(value);
  1494. }
  1495. }
  1496. });
  1497. },
  1498. dirty: function() {
  1499. module.verbose('Setting state dirty');
  1500. dirty = true;
  1501. history[0] = history[1];
  1502. history[1] = 'dirty';
  1503. if (module.is.justClean()) {
  1504. $module.trigger('dirty');
  1505. }
  1506. },
  1507. clean: function() {
  1508. module.verbose('Setting state clean');
  1509. dirty = false;
  1510. history[0] = history[1];
  1511. history[1] = 'clean';
  1512. if (module.is.justDirty()) {
  1513. $module.trigger('clean');
  1514. }
  1515. },
  1516. asClean: function() {
  1517. module.set.defaults();
  1518. module.set.clean();
  1519. },
  1520. asDirty: function() {
  1521. module.set.defaults();
  1522. module.set.dirty();
  1523. },
  1524. autoCheck: function() {
  1525. module.debug('Enabling auto check on required fields');
  1526. $field.each(function (_index, el) {
  1527. var
  1528. $el = $(el),
  1529. $elGroup = $(el).closest($group),
  1530. isCheckbox = ($el.filter(selector.checkbox).length > 0),
  1531. isRequired = $el.prop('required') || $elGroup.hasClass(className.required) || $elGroup.parent().hasClass(className.required),
  1532. isDisabled = $el.prop('disabled') || $elGroup.hasClass(className.disabled) || $elGroup.parent().hasClass(className.disabled),
  1533. validation = module.get.validation($el),
  1534. hasEmptyRule = validation
  1535. ? $.grep(validation.rules, function(rule) { return rule.type == "empty" }) !== 0
  1536. : false,
  1537. identifier = validation.identifier || $el.attr('id') || $el.attr('name') || $el.data(metadata.validate)
  1538. ;
  1539. if (isRequired && !isDisabled && !hasEmptyRule && identifier !== undefined) {
  1540. if (isCheckbox) {
  1541. module.verbose("Adding 'checked' rule on field", identifier);
  1542. module.add.rule(identifier, "checked");
  1543. } else {
  1544. module.verbose("Adding 'empty' rule on field", identifier);
  1545. module.add.rule(identifier, "empty");
  1546. }
  1547. }
  1548. });
  1549. }
  1550. },
  1551. validate: {
  1552. form: function(event, ignoreCallbacks) {
  1553. var values = module.get.values();
  1554. // input keydown event will fire submit repeatedly by browser default
  1555. if(keyHeldDown) {
  1556. return false;
  1557. }
  1558. // reset errors
  1559. formErrors = [];
  1560. if( module.determine.isValid() ) {
  1561. module.debug('Form has no validation errors, submitting');
  1562. module.set.success();
  1563. if(ignoreCallbacks !== true) {
  1564. return settings.onSuccess.call(element, event, values);
  1565. }
  1566. }
  1567. else {
  1568. module.debug('Form has errors');
  1569. module.set.error();
  1570. if(!settings.inline) {
  1571. module.add.errors(formErrors);
  1572. }
  1573. // prevent ajax submit
  1574. if(event && $module.data('moduleApi') !== undefined) {
  1575. event.stopImmediatePropagation();
  1576. }
  1577. if(ignoreCallbacks !== true) {
  1578. return settings.onFailure.call(element, formErrors, values);
  1579. }
  1580. }
  1581. },
  1582. // takes a validation object and returns whether field passes validation
  1583. field: function(field, fieldName, showErrors) {
  1584. showErrors = (showErrors !== undefined)
  1585. ? showErrors
  1586. : true
  1587. ;
  1588. if(typeof field == 'string') {
  1589. module.verbose('Validating field', field);
  1590. fieldName = field;
  1591. field = validation[field];
  1592. }
  1593. var
  1594. identifier = field.identifier || fieldName,
  1595. $field = module.get.field(identifier),
  1596. $dependsField = (field.depends)
  1597. ? module.get.field(field.depends)
  1598. : false,
  1599. fieldValid = true,
  1600. fieldErrors = []
  1601. ;
  1602. if(!field.identifier) {
  1603. module.debug('Using field name as identifier', identifier);
  1604. field.identifier = identifier;
  1605. }
  1606. var isDisabled = true;
  1607. $.each($field, function(){
  1608. if(!$(this).prop('disabled')) {
  1609. isDisabled = false;
  1610. return false;
  1611. }
  1612. });
  1613. if(isDisabled) {
  1614. module.debug('Field is disabled. Skipping', identifier);
  1615. }
  1616. else if(field.optional && module.is.blank($field)){
  1617. module.debug('Field is optional and blank. Skipping', identifier);
  1618. }
  1619. else if(field.depends && module.is.empty($dependsField)) {
  1620. module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
  1621. }
  1622. else if(field.rules !== undefined) {
  1623. $field.closest($group).removeClass(className.error);
  1624. $.each(field.rules, function(index, rule) {
  1625. if( module.has.field(identifier)) {
  1626. var invalidFields = module.validate.rule(field, rule,true) || [];
  1627. if (invalidFields.length>0){
  1628. module.debug('Field is invalid', identifier, rule.type);
  1629. fieldErrors.push(module.get.prompt(rule, field));
  1630. fieldValid = false;
  1631. if(showErrors){
  1632. $(invalidFields).closest($group).addClass(className.error);
  1633. }
  1634. }
  1635. }
  1636. });
  1637. }
  1638. if(fieldValid) {
  1639. if(showErrors) {
  1640. module.remove.prompt(identifier, fieldErrors);
  1641. settings.onValid.call($field);
  1642. }
  1643. }
  1644. else {
  1645. if(showErrors) {
  1646. formErrors = formErrors.concat(fieldErrors);
  1647. module.add.prompt(identifier, fieldErrors, true);
  1648. settings.onInvalid.call($field, fieldErrors);
  1649. }
  1650. return false;
  1651. }
  1652. return true;
  1653. },
  1654. // takes validation rule and returns whether field passes rule
  1655. rule: function(field, rule, internal) {
  1656. var
  1657. $field = module.get.field(field.identifier),
  1658. ancillary = module.get.ancillaryValue(rule),
  1659. ruleName = module.get.ruleName(rule),
  1660. ruleFunction = settings.rules[ruleName],
  1661. invalidFields = [],
  1662. isCheckbox = $field.is(selector.checkbox),
  1663. isValid = function(field){
  1664. var value = (isCheckbox ? $(field).filter(':checked').val() : $(field).val());
  1665. // cast to string avoiding encoding special values
  1666. value = (value === undefined || value === '' || value === null)
  1667. ? ''
  1668. : (settings.shouldTrim) ? $.trim(value + '') : String(value + '')
  1669. ;
  1670. return ruleFunction.call(field, value, ancillary, $module);
  1671. }
  1672. ;
  1673. if( !$.isFunction(ruleFunction) ) {
  1674. module.error(error.noRule, ruleName);
  1675. return;
  1676. }
  1677. if(isCheckbox) {
  1678. if (!isValid($field)) {
  1679. invalidFields = $field;
  1680. }
  1681. } else {
  1682. $.each($field, function (index, field) {
  1683. if (!isValid(field)) {
  1684. invalidFields.push(field);
  1685. }
  1686. });
  1687. }
  1688. return internal ? invalidFields : !(invalidFields.length>0);
  1689. }
  1690. },
  1691. setting: function(name, value) {
  1692. if( $.isPlainObject(name) ) {
  1693. $.extend(true, settings, name);
  1694. }
  1695. else if(value !== undefined) {
  1696. settings[name] = value;
  1697. }
  1698. else {
  1699. return settings[name];
  1700. }
  1701. },
  1702. internal: function(name, value) {
  1703. if( $.isPlainObject(name) ) {
  1704. $.extend(true, module, name);
  1705. }
  1706. else if(value !== undefined) {
  1707. module[name] = value;
  1708. }
  1709. else {
  1710. return module[name];
  1711. }
  1712. },
  1713. debug: function() {
  1714. if(!settings.silent && settings.debug) {
  1715. if(settings.performance) {
  1716. module.performance.log(arguments);
  1717. }
  1718. else {
  1719. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1720. module.debug.apply(console, arguments);
  1721. }
  1722. }
  1723. },
  1724. verbose: function() {
  1725. if(!settings.silent && settings.verbose && settings.debug) {
  1726. if(settings.performance) {
  1727. module.performance.log(arguments);
  1728. }
  1729. else {
  1730. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1731. module.verbose.apply(console, arguments);
  1732. }
  1733. }
  1734. },
  1735. error: function() {
  1736. if(!settings.silent) {
  1737. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  1738. module.error.apply(console, arguments);
  1739. }
  1740. },
  1741. performance: {
  1742. log: function(message) {
  1743. var
  1744. currentTime,
  1745. executionTime,
  1746. previousTime
  1747. ;
  1748. if(settings.performance) {
  1749. currentTime = new Date().getTime();
  1750. previousTime = time || currentTime;
  1751. executionTime = currentTime - previousTime;
  1752. time = currentTime;
  1753. performance.push({
  1754. 'Name' : message[0],
  1755. 'Arguments' : [].slice.call(message, 1) || '',
  1756. 'Element' : element,
  1757. 'Execution Time' : executionTime
  1758. });
  1759. }
  1760. clearTimeout(module.performance.timer);
  1761. module.performance.timer = setTimeout(module.performance.display, 500);
  1762. },
  1763. display: function() {
  1764. var
  1765. title = settings.name + ':',
  1766. totalTime = 0
  1767. ;
  1768. time = false;
  1769. clearTimeout(module.performance.timer);
  1770. $.each(performance, function(index, data) {
  1771. totalTime += data['Execution Time'];
  1772. });
  1773. title += ' ' + totalTime + 'ms';
  1774. if(moduleSelector) {
  1775. title += ' \'' + moduleSelector + '\'';
  1776. }
  1777. if($allModules.length > 1) {
  1778. title += ' ' + '(' + $allModules.length + ')';
  1779. }
  1780. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  1781. console.groupCollapsed(title);
  1782. if(console.table) {
  1783. console.table(performance);
  1784. }
  1785. else {
  1786. $.each(performance, function(index, data) {
  1787. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  1788. });
  1789. }
  1790. console.groupEnd();
  1791. }
  1792. performance = [];
  1793. }
  1794. },
  1795. invoke: function(query, passedArguments, context) {
  1796. var
  1797. object = instance,
  1798. maxDepth,
  1799. found,
  1800. response
  1801. ;
  1802. passedArguments = passedArguments || queryArguments;
  1803. context = element || context;
  1804. if(typeof query == 'string' && object !== undefined) {
  1805. query = query.split(/[\. ]/);
  1806. maxDepth = query.length - 1;
  1807. $.each(query, function(depth, value) {
  1808. var camelCaseValue = (depth != maxDepth)
  1809. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  1810. : query
  1811. ;
  1812. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  1813. object = object[camelCaseValue];
  1814. }
  1815. else if( object[camelCaseValue] !== undefined ) {
  1816. found = object[camelCaseValue];
  1817. return false;
  1818. }
  1819. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  1820. object = object[value];
  1821. }
  1822. else if( object[value] !== undefined ) {
  1823. found = object[value];
  1824. return false;
  1825. }
  1826. else {
  1827. return false;
  1828. }
  1829. });
  1830. }
  1831. if( $.isFunction( found ) ) {
  1832. response = found.apply(context, passedArguments);
  1833. }
  1834. else if(found !== undefined) {
  1835. response = found;
  1836. }
  1837. if(Array.isArray(returnedValue)) {
  1838. returnedValue.push(response);
  1839. }
  1840. else if(returnedValue !== undefined) {
  1841. returnedValue = [returnedValue, response];
  1842. }
  1843. else if(response !== undefined) {
  1844. returnedValue = response;
  1845. }
  1846. return found;
  1847. }
  1848. };
  1849. module.initialize();
  1850. })
  1851. ;
  1852. return (returnedValue !== undefined)
  1853. ? returnedValue
  1854. : this
  1855. ;
  1856. };
  1857. $.fn.form.settings = {
  1858. name : 'Form',
  1859. namespace : 'form',
  1860. debug : false,
  1861. verbose : false,
  1862. performance : true,
  1863. fields : false,
  1864. keyboardShortcuts : true,
  1865. on : 'submit',
  1866. inline : false,
  1867. delay : 200,
  1868. revalidate : true,
  1869. shouldTrim : true,
  1870. transition : 'scale',
  1871. duration : 200,
  1872. autoCheckRequired : false,
  1873. preventLeaving : false,
  1874. dateHandling : 'date', // 'date', 'input', 'formatter'
  1875. onValid : function() {},
  1876. onInvalid : function() {},
  1877. onSuccess : function() { return true; },
  1878. onFailure : function() { return false; },
  1879. onDirty : function() {},
  1880. onClean : function() {},
  1881. metadata : {
  1882. defaultValue : 'default',
  1883. validate : 'validate',
  1884. isDirty : 'isDirty'
  1885. },
  1886. regExp: {
  1887. htmlID : /^[a-zA-Z][\w:.-]*$/g,
  1888. bracket : /\[(.*)\]/i,
  1889. decimal : /^\d+\.?\d*$/,
  1890. email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
  1891. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|:,=@]/g,
  1892. flags : /^\/(.*)\/(.*)?/,
  1893. integer : /^\-?\d+$/,
  1894. number : /^\-?\d*(\.\d+)?$/,
  1895. url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
  1896. },
  1897. text: {
  1898. unspecifiedRule : 'Please enter a valid value',
  1899. unspecifiedField : 'This field',
  1900. leavingMessage : 'There are unsaved changes on this page which will be discarded if you continue.'
  1901. },
  1902. prompt: {
  1903. empty : '{name} must have a value',
  1904. checked : '{name} must be checked',
  1905. email : '{name} must be a valid e-mail',
  1906. url : '{name} must be a valid url',
  1907. regExp : '{name} is not formatted correctly',
  1908. integer : '{name} must be an integer',
  1909. decimal : '{name} must be a decimal number',
  1910. number : '{name} must be set to a number',
  1911. is : '{name} must be "{ruleValue}"',
  1912. isExactly : '{name} must be exactly "{ruleValue}"',
  1913. not : '{name} cannot be set to "{ruleValue}"',
  1914. notExactly : '{name} cannot be set to exactly "{ruleValue}"',
  1915. contain : '{name} must contain "{ruleValue}"',
  1916. containExactly : '{name} must contain exactly "{ruleValue}"',
  1917. doesntContain : '{name} cannot contain "{ruleValue}"',
  1918. doesntContainExactly : '{name} cannot contain exactly "{ruleValue}"',
  1919. minLength : '{name} must be at least {ruleValue} characters',
  1920. length : '{name} must be at least {ruleValue} characters',
  1921. exactLength : '{name} must be exactly {ruleValue} characters',
  1922. maxLength : '{name} cannot be longer than {ruleValue} characters',
  1923. match : '{name} must match {ruleValue} field',
  1924. different : '{name} must have a different value than {ruleValue} field',
  1925. creditCard : '{name} must be a valid credit card number',
  1926. minCount : '{name} must have at least {ruleValue} choices',
  1927. exactCount : '{name} must have exactly {ruleValue} choices',
  1928. maxCount : '{name} must have {ruleValue} or less choices'
  1929. },
  1930. selector : {
  1931. checkbox : 'input[type="checkbox"], input[type="radio"]',
  1932. clear : '.clear',
  1933. field : 'input, textarea, select',
  1934. group : '.field',
  1935. input : 'input',
  1936. message : '.error.message',
  1937. prompt : '.prompt.label',
  1938. radio : 'input[type="radio"]',
  1939. reset : '.reset:not([type="reset"])',
  1940. submit : '.submit:not([type="submit"])',
  1941. uiCheckbox : '.ui.checkbox',
  1942. uiDropdown : '.ui.dropdown',
  1943. uiCalendar : '.ui.calendar'
  1944. },
  1945. className : {
  1946. error : 'error',
  1947. label : 'ui basic red pointing prompt label',
  1948. pressed : 'down',
  1949. success : 'success',
  1950. required : 'required',
  1951. disabled : 'disabled'
  1952. },
  1953. error: {
  1954. identifier : 'You must specify a string identifier for each field',
  1955. method : 'The method you called is not defined.',
  1956. noRule : 'There is no rule matching the one you specified',
  1957. oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.',
  1958. noElement : 'This module requires ui {element}'
  1959. },
  1960. templates: {
  1961. // template that produces error message
  1962. error: function(errors) {
  1963. var
  1964. html = '<ul class="list">'
  1965. ;
  1966. $.each(errors, function(index, value) {
  1967. html += '<li>' + value + '</li>';
  1968. });
  1969. html += '</ul>';
  1970. return $(html);
  1971. },
  1972. // template that produces label
  1973. prompt: function(errors, labelClasses) {
  1974. return $('<div/>')
  1975. .addClass(labelClasses)
  1976. .html(errors[0])
  1977. ;
  1978. }
  1979. },
  1980. formatter: {
  1981. date: function(date) {
  1982. return Intl.DateTimeFormat('en-GB').format(date);
  1983. },
  1984. datetime: function(date) {
  1985. return Intl.DateTimeFormat('en-GB', {
  1986. year: "numeric",
  1987. month: "2-digit",
  1988. day: "2-digit",
  1989. hour: '2-digit',
  1990. minute: '2-digit',
  1991. second: '2-digit'
  1992. }).format(date);
  1993. },
  1994. time: function(date) {
  1995. return Intl.DateTimeFormat('en-GB', {
  1996. hour: '2-digit',
  1997. minute: '2-digit',
  1998. second: '2-digit'
  1999. }).format(date);
  2000. },
  2001. month: function(date) {
  2002. return Intl.DateTimeFormat('en-GB', {
  2003. month: '2-digit',
  2004. year: 'numeric'
  2005. }).format(date);
  2006. },
  2007. year: function(date) {
  2008. return Intl.DateTimeFormat('en-GB', {
  2009. year: 'numeric'
  2010. }).format(date);
  2011. }
  2012. },
  2013. rules: {
  2014. // is not empty or blank string
  2015. empty: function(value) {
  2016. return !(value === undefined || '' === value || Array.isArray(value) && value.length === 0);
  2017. },
  2018. // checkbox checked
  2019. checked: function() {
  2020. return ($(this).filter(':checked').length > 0);
  2021. },
  2022. // is most likely an email
  2023. email: function(value){
  2024. return $.fn.form.settings.regExp.email.test(value);
  2025. },
  2026. // value is most likely url
  2027. url: function(value) {
  2028. return $.fn.form.settings.regExp.url.test(value);
  2029. },
  2030. // matches specified regExp
  2031. regExp: function(value, regExp) {
  2032. if(regExp instanceof RegExp) {
  2033. return value.match(regExp);
  2034. }
  2035. var
  2036. regExpParts = regExp.match($.fn.form.settings.regExp.flags),
  2037. flags
  2038. ;
  2039. // regular expression specified as /baz/gi (flags)
  2040. if(regExpParts) {
  2041. regExp = (regExpParts.length >= 2)
  2042. ? regExpParts[1]
  2043. : regExp
  2044. ;
  2045. flags = (regExpParts.length >= 3)
  2046. ? regExpParts[2]
  2047. : ''
  2048. ;
  2049. }
  2050. return value.match( new RegExp(regExp, flags) );
  2051. },
  2052. // is valid integer or matches range
  2053. integer: function(value, range) {
  2054. var
  2055. intRegExp = $.fn.form.settings.regExp.integer,
  2056. min,
  2057. max,
  2058. parts
  2059. ;
  2060. if( !range || ['', '..'].indexOf(range) !== -1) {
  2061. // do nothing
  2062. }
  2063. else if(range.indexOf('..') == -1) {
  2064. if(intRegExp.test(range)) {
  2065. min = max = range - 0;
  2066. }
  2067. }
  2068. else {
  2069. parts = range.split('..', 2);
  2070. if(intRegExp.test(parts[0])) {
  2071. min = parts[0] - 0;
  2072. }
  2073. if(intRegExp.test(parts[1])) {
  2074. max = parts[1] - 0;
  2075. }
  2076. }
  2077. return (
  2078. intRegExp.test(value) &&
  2079. (min === undefined || value >= min) &&
  2080. (max === undefined || value <= max)
  2081. );
  2082. },
  2083. // is valid number (with decimal)
  2084. decimal: function(value) {
  2085. return $.fn.form.settings.regExp.decimal.test(value);
  2086. },
  2087. // is valid number
  2088. number: function(value) {
  2089. return $.fn.form.settings.regExp.number.test(value);
  2090. },
  2091. // is value (case insensitive)
  2092. is: function(value, text) {
  2093. text = (typeof text == 'string')
  2094. ? text.toLowerCase()
  2095. : text
  2096. ;
  2097. value = (typeof value == 'string')
  2098. ? value.toLowerCase()
  2099. : value
  2100. ;
  2101. return (value == text);
  2102. },
  2103. // is value
  2104. isExactly: function(value, text) {
  2105. return (value == text);
  2106. },
  2107. // value is not another value (case insensitive)
  2108. not: function(value, notValue) {
  2109. value = (typeof value == 'string')
  2110. ? value.toLowerCase()
  2111. : value
  2112. ;
  2113. notValue = (typeof notValue == 'string')
  2114. ? notValue.toLowerCase()
  2115. : notValue
  2116. ;
  2117. return (value != notValue);
  2118. },
  2119. // value is not another value (case sensitive)
  2120. notExactly: function(value, notValue) {
  2121. return (value != notValue);
  2122. },
  2123. // value contains text (insensitive)
  2124. contains: function(value, text) {
  2125. // escape regex characters
  2126. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  2127. return (value.search( new RegExp(text, 'i') ) !== -1);
  2128. },
  2129. // value contains text (case sensitive)
  2130. containsExactly: function(value, text) {
  2131. // escape regex characters
  2132. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  2133. return (value.search( new RegExp(text) ) !== -1);
  2134. },
  2135. // value contains text (insensitive)
  2136. doesntContain: function(value, text) {
  2137. // escape regex characters
  2138. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  2139. return (value.search( new RegExp(text, 'i') ) === -1);
  2140. },
  2141. // value contains text (case sensitive)
  2142. doesntContainExactly: function(value, text) {
  2143. // escape regex characters
  2144. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  2145. return (value.search( new RegExp(text) ) === -1);
  2146. },
  2147. // is at least string length
  2148. minLength: function(value, requiredLength) {
  2149. return (value !== undefined)
  2150. ? (value.length >= requiredLength)
  2151. : false
  2152. ;
  2153. },
  2154. // see rls notes for 2.0.6 (this is a duplicate of minLength)
  2155. length: function(value, requiredLength) {
  2156. return (value !== undefined)
  2157. ? (value.length >= requiredLength)
  2158. : false
  2159. ;
  2160. },
  2161. // is exactly length
  2162. exactLength: function(value, requiredLength) {
  2163. return (value !== undefined)
  2164. ? (value.length == requiredLength)
  2165. : false
  2166. ;
  2167. },
  2168. // is less than length
  2169. maxLength: function(value, maxLength) {
  2170. return (value !== undefined)
  2171. ? (value.length <= maxLength)
  2172. : false
  2173. ;
  2174. },
  2175. // matches another field
  2176. match: function(value, identifier, $module) {
  2177. var
  2178. matchingValue,
  2179. matchingElement
  2180. ;
  2181. if((matchingElement = $module.find('[data-validate="'+ identifier +'"]')).length > 0 ) {
  2182. matchingValue = matchingElement.val();
  2183. }
  2184. else if((matchingElement = $module.find('#' + identifier)).length > 0) {
  2185. matchingValue = matchingElement.val();
  2186. }
  2187. else if((matchingElement = $module.find('[name="' + identifier +'"]')).length > 0) {
  2188. matchingValue = matchingElement.val();
  2189. }
  2190. else if((matchingElement = $module.find('[name="' + identifier +'[]"]')).length > 0 ) {
  2191. matchingValue = matchingElement;
  2192. }
  2193. return (matchingValue !== undefined)
  2194. ? ( value.toString() == matchingValue.toString() )
  2195. : false
  2196. ;
  2197. },
  2198. // different than another field
  2199. different: function(value, identifier, $module) {
  2200. // use either id or name of field
  2201. var
  2202. matchingValue,
  2203. matchingElement
  2204. ;
  2205. if((matchingElement = $module.find('[data-validate="'+ identifier +'"]')).length > 0 ) {
  2206. matchingValue = matchingElement.val();
  2207. }
  2208. else if((matchingElement = $module.find('#' + identifier)).length > 0) {
  2209. matchingValue = matchingElement.val();
  2210. }
  2211. else if((matchingElement = $module.find('[name="' + identifier +'"]')).length > 0) {
  2212. matchingValue = matchingElement.val();
  2213. }
  2214. else if((matchingElement = $module.find('[name="' + identifier +'[]"]')).length > 0 ) {
  2215. matchingValue = matchingElement;
  2216. }
  2217. return (matchingValue !== undefined)
  2218. ? ( value.toString() !== matchingValue.toString() )
  2219. : false
  2220. ;
  2221. },
  2222. creditCard: function(cardNumber, cardTypes) {
  2223. var
  2224. cards = {
  2225. visa: {
  2226. pattern : /^4/,
  2227. length : [16]
  2228. },
  2229. amex: {
  2230. pattern : /^3[47]/,
  2231. length : [15]
  2232. },
  2233. mastercard: {
  2234. pattern : /^5[1-5]/,
  2235. length : [16]
  2236. },
  2237. discover: {
  2238. pattern : /^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/,
  2239. length : [16]
  2240. },
  2241. unionPay: {
  2242. pattern : /^(62|88)/,
  2243. length : [16, 17, 18, 19]
  2244. },
  2245. jcb: {
  2246. pattern : /^35(2[89]|[3-8][0-9])/,
  2247. length : [16]
  2248. },
  2249. maestro: {
  2250. pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
  2251. length : [12, 13, 14, 15, 16, 17, 18, 19]
  2252. },
  2253. dinersClub: {
  2254. pattern : /^(30[0-5]|^36)/,
  2255. length : [14]
  2256. },
  2257. laser: {
  2258. pattern : /^(6304|670[69]|6771)/,
  2259. length : [16, 17, 18, 19]
  2260. },
  2261. visaElectron: {
  2262. pattern : /^(4026|417500|4508|4844|491(3|7))/,
  2263. length : [16]
  2264. }
  2265. },
  2266. valid = {},
  2267. validCard = false,
  2268. requiredTypes = (typeof cardTypes == 'string')
  2269. ? cardTypes.split(',')
  2270. : false,
  2271. unionPay,
  2272. validation
  2273. ;
  2274. if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
  2275. return;
  2276. }
  2277. // allow dashes in card
  2278. cardNumber = cardNumber.replace(/[\-]/g, '');
  2279. // verify card types
  2280. if(requiredTypes) {
  2281. $.each(requiredTypes, function(index, type){
  2282. // verify each card type
  2283. validation = cards[type];
  2284. if(validation) {
  2285. valid = {
  2286. length : ($.inArray(cardNumber.length, validation.length) !== -1),
  2287. pattern : (cardNumber.search(validation.pattern) !== -1)
  2288. };
  2289. if(valid.length && valid.pattern) {
  2290. validCard = true;
  2291. }
  2292. }
  2293. });
  2294. if(!validCard) {
  2295. return false;
  2296. }
  2297. }
  2298. // skip luhn for UnionPay
  2299. unionPay = {
  2300. number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
  2301. pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
  2302. };
  2303. if(unionPay.number && unionPay.pattern) {
  2304. return true;
  2305. }
  2306. // verify luhn, adapted from <https://gist.github.com/2134376>
  2307. var
  2308. length = cardNumber.length,
  2309. multiple = 0,
  2310. producedValue = [
  2311. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
  2312. [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
  2313. ],
  2314. sum = 0
  2315. ;
  2316. while (length--) {
  2317. sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
  2318. multiple ^= 1;
  2319. }
  2320. return (sum % 10 === 0 && sum > 0);
  2321. },
  2322. minCount: function(value, minCount) {
  2323. if(minCount == 0) {
  2324. return true;
  2325. }
  2326. if(minCount == 1) {
  2327. return (value !== '');
  2328. }
  2329. return (value.split(',').length >= minCount);
  2330. },
  2331. exactCount: function(value, exactCount) {
  2332. if(exactCount == 0) {
  2333. return (value === '');
  2334. }
  2335. if(exactCount == 1) {
  2336. return (value !== '' && value.search(',') === -1);
  2337. }
  2338. return (value.split(',').length == exactCount);
  2339. },
  2340. maxCount: function(value, maxCount) {
  2341. if(maxCount == 0) {
  2342. return false;
  2343. }
  2344. if(maxCount == 1) {
  2345. return (value.search(',') === -1);
  2346. }
  2347. return (value.split(',').length <= maxCount);
  2348. }
  2349. }
  2350. };
  2351. })( jQuery, window, document );
  2352. /*!
  2353. * # Fomantic-UI - Accordion
  2354. * http://github.com/fomantic/Fomantic-UI/
  2355. *
  2356. *
  2357. * Released under the MIT license
  2358. * http://opensource.org/licenses/MIT
  2359. *
  2360. */
  2361. ;(function ($, window, document, undefined) {
  2362. 'use strict';
  2363. $.isFunction = $.isFunction || function(obj) {
  2364. return typeof obj === "function" && typeof obj.nodeType !== "number";
  2365. };
  2366. window = (typeof window != 'undefined' && window.Math == Math)
  2367. ? window
  2368. : (typeof self != 'undefined' && self.Math == Math)
  2369. ? self
  2370. : Function('return this')()
  2371. ;
  2372. $.fn.accordion = function(parameters) {
  2373. var
  2374. $allModules = $(this),
  2375. time = new Date().getTime(),
  2376. performance = [],
  2377. query = arguments[0],
  2378. methodInvoked = (typeof query == 'string'),
  2379. queryArguments = [].slice.call(arguments, 1),
  2380. returnedValue
  2381. ;
  2382. $allModules
  2383. .each(function() {
  2384. var
  2385. settings = ( $.isPlainObject(parameters) )
  2386. ? $.extend(true, {}, $.fn.accordion.settings, parameters)
  2387. : $.extend({}, $.fn.accordion.settings),
  2388. className = settings.className,
  2389. namespace = settings.namespace,
  2390. selector = settings.selector,
  2391. error = settings.error,
  2392. eventNamespace = '.' + namespace,
  2393. moduleNamespace = 'module-' + namespace,
  2394. moduleSelector = $allModules.selector || '',
  2395. $module = $(this),
  2396. $title = $module.find(selector.title),
  2397. $content = $module.find(selector.content),
  2398. element = this,
  2399. instance = $module.data(moduleNamespace),
  2400. observer,
  2401. module
  2402. ;
  2403. module = {
  2404. initialize: function() {
  2405. module.debug('Initializing', $module);
  2406. module.bind.events();
  2407. if(settings.observeChanges) {
  2408. module.observeChanges();
  2409. }
  2410. module.instantiate();
  2411. },
  2412. instantiate: function() {
  2413. instance = module;
  2414. $module
  2415. .data(moduleNamespace, module)
  2416. ;
  2417. },
  2418. destroy: function() {
  2419. module.debug('Destroying previous instance', $module);
  2420. $module
  2421. .off(eventNamespace)
  2422. .removeData(moduleNamespace)
  2423. ;
  2424. },
  2425. refresh: function() {
  2426. $title = $module.find(selector.title);
  2427. $content = $module.find(selector.content);
  2428. },
  2429. observeChanges: function() {
  2430. if('MutationObserver' in window) {
  2431. observer = new MutationObserver(function(mutations) {
  2432. module.debug('DOM tree modified, updating selector cache');
  2433. module.refresh();
  2434. });
  2435. observer.observe(element, {
  2436. childList : true,
  2437. subtree : true
  2438. });
  2439. module.debug('Setting up mutation observer', observer);
  2440. }
  2441. },
  2442. bind: {
  2443. events: function() {
  2444. module.debug('Binding delegated events');
  2445. $module
  2446. .on(settings.on + eventNamespace, selector.trigger, module.event.click)
  2447. ;
  2448. }
  2449. },
  2450. event: {
  2451. click: function() {
  2452. module.toggle.call(this);
  2453. }
  2454. },
  2455. toggle: function(query) {
  2456. var
  2457. $activeTitle = (query !== undefined)
  2458. ? (typeof query === 'number')
  2459. ? $title.eq(query)
  2460. : $(query).closest(selector.title)
  2461. : $(this).closest(selector.title),
  2462. $activeContent = $activeTitle.next($content),
  2463. isAnimating = $activeContent.hasClass(className.animating),
  2464. isActive = $activeContent.hasClass(className.active),
  2465. isOpen = (isActive && !isAnimating),
  2466. isOpening = (!isActive && isAnimating)
  2467. ;
  2468. module.debug('Toggling visibility of content', $activeTitle);
  2469. if(isOpen || isOpening) {
  2470. if(settings.collapsible) {
  2471. module.close.call($activeTitle);
  2472. }
  2473. else {
  2474. module.debug('Cannot close accordion content collapsing is disabled');
  2475. }
  2476. }
  2477. else {
  2478. module.open.call($activeTitle);
  2479. }
  2480. },
  2481. open: function(query) {
  2482. var
  2483. $activeTitle = (query !== undefined)
  2484. ? (typeof query === 'number')
  2485. ? $title.eq(query)
  2486. : $(query).closest(selector.title)
  2487. : $(this).closest(selector.title),
  2488. $activeContent = $activeTitle.next($content),
  2489. isAnimating = $activeContent.hasClass(className.animating),
  2490. isActive = $activeContent.hasClass(className.active),
  2491. isOpen = (isActive || isAnimating)
  2492. ;
  2493. if(isOpen) {
  2494. module.debug('Accordion already open, skipping', $activeContent);
  2495. return;
  2496. }
  2497. module.debug('Opening accordion content', $activeTitle);
  2498. settings.onOpening.call($activeContent);
  2499. settings.onChanging.call($activeContent);
  2500. if(settings.exclusive) {
  2501. module.closeOthers.call($activeTitle);
  2502. }
  2503. $activeTitle
  2504. .addClass(className.active)
  2505. ;
  2506. $activeContent
  2507. .stop(true, true)
  2508. .addClass(className.animating)
  2509. ;
  2510. if(settings.animateChildren) {
  2511. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2512. $activeContent
  2513. .children()
  2514. .transition({
  2515. animation : 'fade in',
  2516. queue : false,
  2517. useFailSafe : true,
  2518. debug : settings.debug,
  2519. verbose : settings.verbose,
  2520. duration : settings.duration,
  2521. skipInlineHidden : true,
  2522. onComplete: function() {
  2523. $activeContent.children().removeClass(className.transition);
  2524. }
  2525. })
  2526. ;
  2527. }
  2528. else {
  2529. $activeContent
  2530. .children()
  2531. .stop(true, true)
  2532. .animate({
  2533. opacity: 1
  2534. }, settings.duration, module.resetOpacity)
  2535. ;
  2536. }
  2537. }
  2538. $activeContent
  2539. .slideDown(settings.duration, settings.easing, function() {
  2540. $activeContent
  2541. .removeClass(className.animating)
  2542. .addClass(className.active)
  2543. ;
  2544. module.reset.display.call(this);
  2545. settings.onOpen.call(this);
  2546. settings.onChange.call(this);
  2547. })
  2548. ;
  2549. },
  2550. close: function(query) {
  2551. var
  2552. $activeTitle = (query !== undefined)
  2553. ? (typeof query === 'number')
  2554. ? $title.eq(query)
  2555. : $(query).closest(selector.title)
  2556. : $(this).closest(selector.title),
  2557. $activeContent = $activeTitle.next($content),
  2558. isAnimating = $activeContent.hasClass(className.animating),
  2559. isActive = $activeContent.hasClass(className.active),
  2560. isOpening = (!isActive && isAnimating),
  2561. isClosing = (isActive && isAnimating)
  2562. ;
  2563. if((isActive || isOpening) && !isClosing) {
  2564. module.debug('Closing accordion content', $activeContent);
  2565. settings.onClosing.call($activeContent);
  2566. settings.onChanging.call($activeContent);
  2567. $activeTitle
  2568. .removeClass(className.active)
  2569. ;
  2570. $activeContent
  2571. .stop(true, true)
  2572. .addClass(className.animating)
  2573. ;
  2574. if(settings.animateChildren) {
  2575. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2576. $activeContent
  2577. .children()
  2578. .transition({
  2579. animation : 'fade out',
  2580. queue : false,
  2581. useFailSafe : true,
  2582. debug : settings.debug,
  2583. verbose : settings.verbose,
  2584. duration : settings.duration,
  2585. skipInlineHidden : true
  2586. })
  2587. ;
  2588. }
  2589. else {
  2590. $activeContent
  2591. .children()
  2592. .stop(true, true)
  2593. .animate({
  2594. opacity: 0
  2595. }, settings.duration, module.resetOpacity)
  2596. ;
  2597. }
  2598. }
  2599. $activeContent
  2600. .slideUp(settings.duration, settings.easing, function() {
  2601. $activeContent
  2602. .removeClass(className.animating)
  2603. .removeClass(className.active)
  2604. ;
  2605. module.reset.display.call(this);
  2606. settings.onClose.call(this);
  2607. settings.onChange.call(this);
  2608. })
  2609. ;
  2610. }
  2611. },
  2612. closeOthers: function(index) {
  2613. var
  2614. $activeTitle = (index !== undefined)
  2615. ? $title.eq(index)
  2616. : $(this).closest(selector.title),
  2617. $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
  2618. $activeAccordion = $activeTitle.closest(selector.accordion),
  2619. activeSelector = selector.title + '.' + className.active + ':visible',
  2620. activeContent = selector.content + '.' + className.active + ':visible',
  2621. $openTitles,
  2622. $nestedTitles,
  2623. $openContents
  2624. ;
  2625. if(settings.closeNested) {
  2626. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2627. $openContents = $openTitles.next($content);
  2628. }
  2629. else {
  2630. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2631. $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
  2632. $openTitles = $openTitles.not($nestedTitles);
  2633. $openContents = $openTitles.next($content);
  2634. }
  2635. if( ($openTitles.length > 0) ) {
  2636. module.debug('Exclusive enabled, closing other content', $openTitles);
  2637. $openTitles
  2638. .removeClass(className.active)
  2639. ;
  2640. $openContents
  2641. .removeClass(className.animating)
  2642. .stop(true, true)
  2643. ;
  2644. if(settings.animateChildren) {
  2645. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2646. $openContents
  2647. .children()
  2648. .transition({
  2649. animation : 'fade out',
  2650. useFailSafe : true,
  2651. debug : settings.debug,
  2652. verbose : settings.verbose,
  2653. duration : settings.duration,
  2654. skipInlineHidden : true
  2655. })
  2656. ;
  2657. }
  2658. else {
  2659. $openContents
  2660. .children()
  2661. .stop(true, true)
  2662. .animate({
  2663. opacity: 0
  2664. }, settings.duration, module.resetOpacity)
  2665. ;
  2666. }
  2667. }
  2668. $openContents
  2669. .slideUp(settings.duration , settings.easing, function() {
  2670. $(this).removeClass(className.active);
  2671. module.reset.display.call(this);
  2672. })
  2673. ;
  2674. }
  2675. },
  2676. reset: {
  2677. display: function() {
  2678. module.verbose('Removing inline display from element', this);
  2679. $(this).css('display', '');
  2680. if( $(this).attr('style') === '') {
  2681. $(this)
  2682. .attr('style', '')
  2683. .removeAttr('style')
  2684. ;
  2685. }
  2686. },
  2687. opacity: function() {
  2688. module.verbose('Removing inline opacity from element', this);
  2689. $(this).css('opacity', '');
  2690. if( $(this).attr('style') === '') {
  2691. $(this)
  2692. .attr('style', '')
  2693. .removeAttr('style')
  2694. ;
  2695. }
  2696. },
  2697. },
  2698. setting: function(name, value) {
  2699. module.debug('Changing setting', name, value);
  2700. if( $.isPlainObject(name) ) {
  2701. $.extend(true, settings, name);
  2702. }
  2703. else if(value !== undefined) {
  2704. if($.isPlainObject(settings[name])) {
  2705. $.extend(true, settings[name], value);
  2706. }
  2707. else {
  2708. settings[name] = value;
  2709. }
  2710. }
  2711. else {
  2712. return settings[name];
  2713. }
  2714. },
  2715. internal: function(name, value) {
  2716. module.debug('Changing internal', name, value);
  2717. if(value !== undefined) {
  2718. if( $.isPlainObject(name) ) {
  2719. $.extend(true, module, name);
  2720. }
  2721. else {
  2722. module[name] = value;
  2723. }
  2724. }
  2725. else {
  2726. return module[name];
  2727. }
  2728. },
  2729. debug: function() {
  2730. if(!settings.silent && settings.debug) {
  2731. if(settings.performance) {
  2732. module.performance.log(arguments);
  2733. }
  2734. else {
  2735. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2736. module.debug.apply(console, arguments);
  2737. }
  2738. }
  2739. },
  2740. verbose: function() {
  2741. if(!settings.silent && settings.verbose && settings.debug) {
  2742. if(settings.performance) {
  2743. module.performance.log(arguments);
  2744. }
  2745. else {
  2746. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2747. module.verbose.apply(console, arguments);
  2748. }
  2749. }
  2750. },
  2751. error: function() {
  2752. if(!settings.silent) {
  2753. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  2754. module.error.apply(console, arguments);
  2755. }
  2756. },
  2757. performance: {
  2758. log: function(message) {
  2759. var
  2760. currentTime,
  2761. executionTime,
  2762. previousTime
  2763. ;
  2764. if(settings.performance) {
  2765. currentTime = new Date().getTime();
  2766. previousTime = time || currentTime;
  2767. executionTime = currentTime - previousTime;
  2768. time = currentTime;
  2769. performance.push({
  2770. 'Name' : message[0],
  2771. 'Arguments' : [].slice.call(message, 1) || '',
  2772. 'Element' : element,
  2773. 'Execution Time' : executionTime
  2774. });
  2775. }
  2776. clearTimeout(module.performance.timer);
  2777. module.performance.timer = setTimeout(module.performance.display, 500);
  2778. },
  2779. display: function() {
  2780. var
  2781. title = settings.name + ':',
  2782. totalTime = 0
  2783. ;
  2784. time = false;
  2785. clearTimeout(module.performance.timer);
  2786. $.each(performance, function(index, data) {
  2787. totalTime += data['Execution Time'];
  2788. });
  2789. title += ' ' + totalTime + 'ms';
  2790. if(moduleSelector) {
  2791. title += ' \'' + moduleSelector + '\'';
  2792. }
  2793. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  2794. console.groupCollapsed(title);
  2795. if(console.table) {
  2796. console.table(performance);
  2797. }
  2798. else {
  2799. $.each(performance, function(index, data) {
  2800. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  2801. });
  2802. }
  2803. console.groupEnd();
  2804. }
  2805. performance = [];
  2806. }
  2807. },
  2808. invoke: function(query, passedArguments, context) {
  2809. var
  2810. object = instance,
  2811. maxDepth,
  2812. found,
  2813. response
  2814. ;
  2815. passedArguments = passedArguments || queryArguments;
  2816. context = element || context;
  2817. if(typeof query == 'string' && object !== undefined) {
  2818. query = query.split(/[\. ]/);
  2819. maxDepth = query.length - 1;
  2820. $.each(query, function(depth, value) {
  2821. var camelCaseValue = (depth != maxDepth)
  2822. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  2823. : query
  2824. ;
  2825. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  2826. object = object[camelCaseValue];
  2827. }
  2828. else if( object[camelCaseValue] !== undefined ) {
  2829. found = object[camelCaseValue];
  2830. return false;
  2831. }
  2832. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  2833. object = object[value];
  2834. }
  2835. else if( object[value] !== undefined ) {
  2836. found = object[value];
  2837. return false;
  2838. }
  2839. else {
  2840. module.error(error.method, query);
  2841. return false;
  2842. }
  2843. });
  2844. }
  2845. if ( $.isFunction( found ) ) {
  2846. response = found.apply(context, passedArguments);
  2847. }
  2848. else if(found !== undefined) {
  2849. response = found;
  2850. }
  2851. if(Array.isArray(returnedValue)) {
  2852. returnedValue.push(response);
  2853. }
  2854. else if(returnedValue !== undefined) {
  2855. returnedValue = [returnedValue, response];
  2856. }
  2857. else if(response !== undefined) {
  2858. returnedValue = response;
  2859. }
  2860. return found;
  2861. }
  2862. };
  2863. if(methodInvoked) {
  2864. if(instance === undefined) {
  2865. module.initialize();
  2866. }
  2867. module.invoke(query);
  2868. }
  2869. else {
  2870. if(instance !== undefined) {
  2871. instance.invoke('destroy');
  2872. }
  2873. module.initialize();
  2874. }
  2875. })
  2876. ;
  2877. return (returnedValue !== undefined)
  2878. ? returnedValue
  2879. : this
  2880. ;
  2881. };
  2882. $.fn.accordion.settings = {
  2883. name : 'Accordion',
  2884. namespace : 'accordion',
  2885. silent : false,
  2886. debug : false,
  2887. verbose : false,
  2888. performance : true,
  2889. on : 'click', // event on title that opens accordion
  2890. observeChanges : true, // whether accordion should automatically refresh on DOM insertion
  2891. exclusive : true, // whether a single accordion content panel should be open at once
  2892. collapsible : true, // whether accordion content can be closed
  2893. closeNested : false, // whether nested content should be closed when a panel is closed
  2894. animateChildren : true, // whether children opacity should be animated
  2895. duration : 350, // duration of animation
  2896. easing : 'easeOutQuad', // easing equation for animation
  2897. onOpening : function(){}, // callback before open animation
  2898. onClosing : function(){}, // callback before closing animation
  2899. onChanging : function(){}, // callback before closing or opening animation
  2900. onOpen : function(){}, // callback after open animation
  2901. onClose : function(){}, // callback after closing animation
  2902. onChange : function(){}, // callback after closing or opening animation
  2903. error: {
  2904. method : 'The method you called is not defined'
  2905. },
  2906. className : {
  2907. active : 'active',
  2908. animating : 'animating',
  2909. transition: 'transition'
  2910. },
  2911. selector : {
  2912. accordion : '.accordion',
  2913. title : '.title',
  2914. trigger : '.title',
  2915. content : '.content'
  2916. }
  2917. };
  2918. // Adds easing
  2919. $.extend( $.easing, {
  2920. easeOutQuad: function (x, t, b, c, d) {
  2921. return -c *(t/=d)*(t-2) + b;
  2922. }
  2923. });
  2924. })( jQuery, window, document );
  2925. /*!
  2926. * # Fomantic-UI - Calendar
  2927. * http://github.com/fomantic/Fomantic-UI/
  2928. *
  2929. *
  2930. * Released under the MIT license
  2931. * http://opensource.org/licenses/MIT
  2932. *
  2933. */
  2934. ;(function ($, window, document, undefined) {
  2935. 'use strict';
  2936. $.isFunction = $.isFunction || function(obj) {
  2937. return typeof obj === "function" && typeof obj.nodeType !== "number";
  2938. };
  2939. window = (typeof window != 'undefined' && window.Math == Math)
  2940. ? window
  2941. : (typeof self != 'undefined' && self.Math == Math)
  2942. ? self
  2943. : Function('return this')()
  2944. ;
  2945. $.fn.calendar = function(parameters) {
  2946. var
  2947. $allModules = $(this),
  2948. moduleSelector = $allModules.selector || '',
  2949. time = new Date().getTime(),
  2950. performance = [],
  2951. query = arguments[0],
  2952. methodInvoked = (typeof query == 'string'),
  2953. queryArguments = [].slice.call(arguments, 1),
  2954. returnedValue,
  2955. timeGapTable = {
  2956. '5': {'row': 4, 'column': 3 },
  2957. '10': {'row': 3, 'column': 2 },
  2958. '15': {'row': 2, 'column': 2 },
  2959. '20': {'row': 3, 'column': 1 },
  2960. '30': {'row': 2, 'column': 1 }
  2961. }
  2962. ;
  2963. $allModules
  2964. .each(function () {
  2965. var
  2966. settings = ( $.isPlainObject(parameters) )
  2967. ? $.extend(true, {}, $.fn.calendar.settings, parameters)
  2968. : $.extend({}, $.fn.calendar.settings),
  2969. className = settings.className,
  2970. namespace = settings.namespace,
  2971. selector = settings.selector,
  2972. formatter = settings.formatter,
  2973. parser = settings.parser,
  2974. metadata = settings.metadata,
  2975. timeGap = timeGapTable[settings.minTimeGap],
  2976. error = settings.error,
  2977. eventNamespace = '.' + namespace,
  2978. moduleNamespace = 'module-' + namespace,
  2979. $module = $(this),
  2980. $input = $module.find(selector.input),
  2981. $container = $module.find(selector.popup),
  2982. $activator = $module.find(selector.activator),
  2983. element = this,
  2984. instance = $module.data(moduleNamespace),
  2985. isTouch,
  2986. isTouchDown = false,
  2987. focusDateUsedForRange = false,
  2988. module
  2989. ;
  2990. module = {
  2991. initialize: function () {
  2992. module.debug('Initializing calendar for', element, $module);
  2993. isTouch = module.get.isTouch();
  2994. module.setup.config();
  2995. module.setup.popup();
  2996. module.setup.inline();
  2997. module.setup.input();
  2998. module.setup.date();
  2999. module.create.calendar();
  3000. module.bind.events();
  3001. module.instantiate();
  3002. },
  3003. instantiate: function () {
  3004. module.verbose('Storing instance of calendar');
  3005. instance = module;
  3006. $module.data(moduleNamespace, instance);
  3007. },
  3008. destroy: function () {
  3009. module.verbose('Destroying previous calendar for', element);
  3010. $module.removeData(moduleNamespace);
  3011. module.unbind.events();
  3012. },
  3013. setup: {
  3014. config: function () {
  3015. if (module.get.minDate() !== null) {
  3016. module.set.minDate($module.data(metadata.minDate));
  3017. }
  3018. if (module.get.maxDate() !== null) {
  3019. module.set.maxDate($module.data(metadata.maxDate));
  3020. }
  3021. module.setting('type', module.get.type());
  3022. },
  3023. popup: function () {
  3024. if (settings.inline) {
  3025. return;
  3026. }
  3027. if (!$activator.length) {
  3028. $activator = $module.children().first();
  3029. if (!$activator.length) {
  3030. return;
  3031. }
  3032. }
  3033. if ($.fn.popup === undefined) {
  3034. module.error(error.popup);
  3035. return;
  3036. }
  3037. if (!$container.length) {
  3038. //prepend the popup element to the activator's parent so that it has less chance of messing with
  3039. //the styling (eg input action button needs to be the last child to have correct border radius)
  3040. var $activatorParent = $activator.parent(),
  3041. domPositionFunction = $activatorParent.closest(selector.append).length !== 0 ? 'appendTo' : 'prependTo';
  3042. $container = $('<div/>').addClass(className.popup)[domPositionFunction]($activatorParent);
  3043. }
  3044. $container.addClass(className.calendar);
  3045. var onVisible = settings.onVisible;
  3046. var onHidden = settings.onHidden;
  3047. if (!$input.length) {
  3048. //no input, $container has to handle focus/blur
  3049. $container.attr('tabindex', '0');
  3050. onVisible = function () {
  3051. module.focus();
  3052. return settings.onVisible.apply($container, arguments);
  3053. };
  3054. onHidden = function () {
  3055. module.blur();
  3056. return settings.onHidden.apply($container, arguments);
  3057. };
  3058. }
  3059. var onShow = function () {
  3060. //reset the focus date onShow
  3061. module.set.focusDate(module.get.date());
  3062. module.set.mode(settings.startMode);
  3063. return settings.onShow.apply($container, arguments);
  3064. };
  3065. var on = settings.on || ($input.length ? 'focus' : 'click');
  3066. var options = $.extend({}, settings.popupOptions, {
  3067. popup: $container,
  3068. on: on,
  3069. hoverable: on === 'hover',
  3070. onShow: onShow,
  3071. onVisible: onVisible,
  3072. onHide: settings.onHide,
  3073. onHidden: onHidden
  3074. });
  3075. module.popup(options);
  3076. },
  3077. inline: function () {
  3078. if ($activator.length && !settings.inline) {
  3079. return;
  3080. }
  3081. $container = $('<div/>').addClass(className.calendar).appendTo($module);
  3082. if (!$input.length) {
  3083. $container.attr('tabindex', '0');
  3084. }
  3085. },
  3086. input: function () {
  3087. if (settings.touchReadonly && $input.length && isTouch) {
  3088. $input.prop('readonly', true);
  3089. }
  3090. },
  3091. date: function () {
  3092. var date;
  3093. if (settings.initialDate) {
  3094. date = parser.date(settings.initialDate, settings);
  3095. } else if ($module.data(metadata.date) !== undefined) {
  3096. date = parser.date($module.data(metadata.date), settings);
  3097. } else if ($input.length) {
  3098. date = parser.date($input.val(), settings);
  3099. }
  3100. module.set.date(date, settings.formatInput, false);
  3101. }
  3102. },
  3103. create: {
  3104. calendar: function () {
  3105. var i, r, c, p, row, cell, pageGrid;
  3106. var mode = module.get.mode();
  3107. var today = new Date();
  3108. var date = module.get.date();
  3109. var focusDate = module.get.focusDate();
  3110. var display = focusDate || date || settings.initialDate || today;
  3111. display = module.helper.dateInRange(display);
  3112. if (!focusDate) {
  3113. focusDate = display;
  3114. module.set.focusDate(focusDate, false, false);
  3115. }
  3116. var isYear = mode === 'year';
  3117. var isMonth = mode === 'month';
  3118. var isDay = mode === 'day';
  3119. var isHour = mode === 'hour';
  3120. var isMinute = mode === 'minute';
  3121. var isTimeOnly = settings.type === 'time';
  3122. var multiMonth = Math.max(settings.multiMonth, 1);
  3123. var monthOffset = !isDay ? 0 : module.get.monthOffset();
  3124. var minute = display.getMinutes();
  3125. var hour = display.getHours();
  3126. var day = display.getDate();
  3127. var startMonth = display.getMonth() + monthOffset;
  3128. var year = display.getFullYear();
  3129. var columns = isDay ? settings.showWeekNumbers ? 8 : 7 : isHour ? 4 : timeGap['column'];
  3130. var rows = isDay || isHour ? 6 : timeGap['row'];
  3131. var pages = isDay ? multiMonth : 1;
  3132. var container = $container;
  3133. var tooltipPosition = container.hasClass("left") ? "right center" : "left center";
  3134. container.empty();
  3135. if (pages > 1) {
  3136. pageGrid = $('<div/>').addClass(className.grid).appendTo(container);
  3137. }
  3138. for (p = 0; p < pages; p++) {
  3139. if (pages > 1) {
  3140. var pageColumn = $('<div/>').addClass(className.column).appendTo(pageGrid);
  3141. container = pageColumn;
  3142. }
  3143. var month = startMonth + p;
  3144. var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
  3145. if (!settings.constantHeight && isDay) {
  3146. var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
  3147. rows = Math.ceil(requiredCells / 7);
  3148. }
  3149. var yearChange = isYear ? 10 : isMonth ? 1 : 0;
  3150. var monthChange = isDay ? 1 : 0;
  3151. var dayChange = isHour || isMinute ? 1 : 0;
  3152. var prevNextDay = isHour || isMinute ? day : 1;
  3153. var prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour);
  3154. var nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour);
  3155. var prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) :
  3156. isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1);
  3157. var nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) :
  3158. isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1);
  3159. var tempMode = mode;
  3160. if (isDay && settings.showWeekNumbers){
  3161. tempMode += ' andweek';
  3162. }
  3163. var table = $('<table/>').addClass(className.table).addClass(tempMode).appendTo(container);
  3164. var textColumns = columns;
  3165. //no header for time-only mode
  3166. if (!isTimeOnly) {
  3167. var thead = $('<thead/>').appendTo(table);
  3168. row = $('<tr/>').appendTo(thead);
  3169. cell = $('<th/>').attr('colspan', '' + columns).appendTo(row);
  3170. var headerDate = isYear || isMonth ? new Date(year, 0, 1) :
  3171. isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute);
  3172. var headerText = $('<span/>').addClass(className.link).appendTo(cell);
  3173. headerText.text(formatter.header(headerDate, mode, settings));
  3174. var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') :
  3175. isDay ? (settings.disableMonth ? 'year' : 'month') : 'day';
  3176. headerText.data(metadata.mode, newMode);
  3177. if (p === 0) {
  3178. var prev = $('<span/>').addClass(className.prev).appendTo(cell);
  3179. prev.data(metadata.focusDate, prevDate);
  3180. prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
  3181. $('<i/>').addClass(className.prevIcon).appendTo(prev);
  3182. }
  3183. if (p === pages - 1) {
  3184. var next = $('<span/>').addClass(className.next).appendTo(cell);
  3185. next.data(metadata.focusDate, nextDate);
  3186. next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
  3187. $('<i/>').addClass(className.nextIcon).appendTo(next);
  3188. }
  3189. if (isDay) {
  3190. row = $('<tr/>').appendTo(thead);
  3191. if(settings.showWeekNumbers) {
  3192. cell = $('<th/>').appendTo(row);
  3193. cell.text(settings.text.weekNo);
  3194. cell.addClass(className.weekCell);
  3195. textColumns--;
  3196. }
  3197. for (i = 0; i < textColumns; i++) {
  3198. cell = $('<th/>').appendTo(row);
  3199. cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
  3200. }
  3201. }
  3202. }
  3203. var tbody = $('<tbody/>').appendTo(table);
  3204. i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
  3205. for (r = 0; r < rows; r++) {
  3206. row = $('<tr/>').appendTo(tbody);
  3207. if(isDay && settings.showWeekNumbers){
  3208. cell = $('<th/>').appendTo(row);
  3209. cell.text(module.get.weekOfYear(year,month,i+1-settings.firstDayOfWeek));
  3210. cell.addClass(className.weekCell);
  3211. }
  3212. for (c = 0; c < textColumns; c++, i++) {
  3213. var cellDate = isYear ? new Date(i, month, 1, hour, minute) :
  3214. isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) :
  3215. isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * settings.minTimeGap);
  3216. var cellText = isYear ? i :
  3217. isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() :
  3218. formatter.time(cellDate, settings, true);
  3219. cell = $('<td/>').addClass(className.cell).appendTo(row);
  3220. cell.text(cellText);
  3221. cell.data(metadata.date, cellDate);
  3222. var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
  3223. var disabled = (!settings.selectAdjacentDays && adjacent) || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode) || module.helper.isDisabled(cellDate, mode) || !module.helper.isEnabled(cellDate, mode);
  3224. if (disabled) {
  3225. var disabledDate = module.helper.findDayAsObject(cellDate, mode, settings.disabledDates);
  3226. if (disabledDate !== null && disabledDate[metadata.message]) {
  3227. cell.attr("data-tooltip", disabledDate[metadata.message]);
  3228. cell.attr("data-position", tooltipPosition);
  3229. }
  3230. } else {
  3231. var eventDate = module.helper.findDayAsObject(cellDate, mode, settings.eventDates);
  3232. if (eventDate !== null) {
  3233. cell.addClass(eventDate[metadata.class] || settings.eventClass);
  3234. if (eventDate[metadata.message]) {
  3235. cell.attr("data-tooltip", eventDate[metadata.message]);
  3236. cell.attr("data-position", tooltipPosition);
  3237. }
  3238. }
  3239. }
  3240. var active = module.helper.dateEqual(cellDate, date, mode);
  3241. var isToday = module.helper.dateEqual(cellDate, today, mode);
  3242. cell.toggleClass(className.adjacentCell, adjacent);
  3243. cell.toggleClass(className.disabledCell, disabled);
  3244. cell.toggleClass(className.activeCell, active && !adjacent);
  3245. if (!isHour && !isMinute) {
  3246. cell.toggleClass(className.todayCell, !adjacent && isToday);
  3247. }
  3248. // Allow for external modifications of each cell
  3249. var cellOptions = {
  3250. mode: mode,
  3251. adjacent: adjacent,
  3252. disabled: disabled,
  3253. active: active,
  3254. today: isToday
  3255. };
  3256. formatter.cell(cell, cellDate, cellOptions);
  3257. if (module.helper.dateEqual(cellDate, focusDate, mode)) {
  3258. //ensure that the focus date is exactly equal to the cell date
  3259. //so that, if selected, the correct value is set
  3260. module.set.focusDate(cellDate, false, false);
  3261. }
  3262. }
  3263. }
  3264. if (settings.today) {
  3265. var todayRow = $('<tr/>').appendTo(tbody);
  3266. var todayButton = $('<td/>').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
  3267. todayButton.text(formatter.today(settings));
  3268. todayButton.data(metadata.date, today);
  3269. }
  3270. module.update.focus(false, table);
  3271. }
  3272. }
  3273. },
  3274. update: {
  3275. focus: function (updateRange, container) {
  3276. container = container || $container;
  3277. var mode = module.get.mode();
  3278. var date = module.get.date();
  3279. var focusDate = module.get.focusDate();
  3280. var startDate = module.get.startDate();
  3281. var endDate = module.get.endDate();
  3282. var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
  3283. container.find('td').each(function () {
  3284. var cell = $(this);
  3285. var cellDate = cell.data(metadata.date);
  3286. if (!cellDate) {
  3287. return;
  3288. }
  3289. var disabled = cell.hasClass(className.disabledCell);
  3290. var active = cell.hasClass(className.activeCell);
  3291. var adjacent = cell.hasClass(className.adjacentCell);
  3292. var focused = module.helper.dateEqual(cellDate, focusDate, mode);
  3293. var inRange = !rangeDate ? false :
  3294. ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) ||
  3295. (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
  3296. cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && (!adjacent || (settings.selectAdjacentDays && adjacent)) && !disabled);
  3297. if (module.helper.isTodayButton(cell)) {
  3298. return;
  3299. }
  3300. cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
  3301. });
  3302. }
  3303. },
  3304. refresh: function () {
  3305. module.create.calendar();
  3306. },
  3307. bind: {
  3308. events: function () {
  3309. module.debug('Binding events');
  3310. $container.on('mousedown' + eventNamespace, module.event.mousedown);
  3311. $container.on('touchstart' + eventNamespace, module.event.mousedown);
  3312. $container.on('mouseup' + eventNamespace, module.event.mouseup);
  3313. $container.on('touchend' + eventNamespace, module.event.mouseup);
  3314. $container.on('mouseover' + eventNamespace, module.event.mouseover);
  3315. if ($input.length) {
  3316. $input.on('input' + eventNamespace, module.event.inputChange);
  3317. $input.on('focus' + eventNamespace, module.event.inputFocus);
  3318. $input.on('blur' + eventNamespace, module.event.inputBlur);
  3319. $input.on('click' + eventNamespace, module.event.inputClick);
  3320. $input.on('keydown' + eventNamespace, module.event.keydown);
  3321. } else {
  3322. $container.on('keydown' + eventNamespace, module.event.keydown);
  3323. }
  3324. }
  3325. },
  3326. unbind: {
  3327. events: function () {
  3328. module.debug('Unbinding events');
  3329. $container.off(eventNamespace);
  3330. if ($input.length) {
  3331. $input.off(eventNamespace);
  3332. }
  3333. }
  3334. },
  3335. event: {
  3336. mouseover: function (event) {
  3337. var target = $(event.target);
  3338. var date = target.data(metadata.date);
  3339. var mousedown = event.buttons === 1;
  3340. if (date) {
  3341. module.set.focusDate(date, false, true, mousedown);
  3342. }
  3343. },
  3344. mousedown: function (event) {
  3345. if ($input.length) {
  3346. //prevent the mousedown on the calendar causing the input to lose focus
  3347. event.preventDefault();
  3348. }
  3349. isTouchDown = event.type.indexOf('touch') >= 0;
  3350. var target = $(event.target);
  3351. var date = target.data(metadata.date);
  3352. if (date) {
  3353. module.set.focusDate(date, false, true, true);
  3354. }
  3355. },
  3356. mouseup: function (event) {
  3357. //ensure input has focus so that it receives keydown events for calendar navigation
  3358. module.focus();
  3359. event.preventDefault();
  3360. event.stopPropagation();
  3361. isTouchDown = false;
  3362. var target = $(event.target);
  3363. if (target.hasClass("disabled")) {
  3364. return;
  3365. }
  3366. var parent = target.parent();
  3367. if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
  3368. //clicked on a child element, switch to parent (used when clicking directly on prev/next <i> icon element)
  3369. target = parent;
  3370. }
  3371. var date = target.data(metadata.date);
  3372. var focusDate = target.data(metadata.focusDate);
  3373. var mode = target.data(metadata.mode);
  3374. if (date && settings.onSelect.call(element, date, module.get.mode()) !== false) {
  3375. var forceSet = target.hasClass(className.today);
  3376. module.selectDate(date, forceSet);
  3377. }
  3378. else if (focusDate) {
  3379. module.set.focusDate(focusDate);
  3380. }
  3381. else if (mode) {
  3382. module.set.mode(mode);
  3383. }
  3384. },
  3385. keydown: function (event) {
  3386. var keyCode = event.which;
  3387. if (keyCode === 27 || keyCode === 9) {
  3388. //esc || tab
  3389. module.popup('hide');
  3390. }
  3391. if (module.popup('is visible')) {
  3392. if (keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
  3393. //arrow keys
  3394. var mode = module.get.mode();
  3395. var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : mode === 'minute' ? timeGap['column'] : 3;
  3396. var increment = keyCode === 37 ? -1 : keyCode === 38 ? -bigIncrement : keyCode == 39 ? 1 : bigIncrement;
  3397. increment *= mode === 'minute' ? settings.minTimeGap : 1;
  3398. var focusDate = module.get.focusDate() || module.get.date() || new Date();
  3399. var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
  3400. var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
  3401. var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
  3402. var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
  3403. var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
  3404. var newFocusDate = new Date(year, month, day, hour, minute);
  3405. if (settings.type === 'time') {
  3406. newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
  3407. }
  3408. if (module.helper.isDateInRange(newFocusDate, mode)) {
  3409. module.set.focusDate(newFocusDate);
  3410. }
  3411. } else if (keyCode === 13) {
  3412. //enter
  3413. var mode = module.get.mode();
  3414. var date = module.get.focusDate();
  3415. if (date && !settings.isDisabled(date, mode) && !module.helper.isDisabled(date, mode) && module.helper.isEnabled(date, mode)) {
  3416. module.selectDate(date);
  3417. }
  3418. //disable form submission:
  3419. event.preventDefault();
  3420. event.stopPropagation();
  3421. }
  3422. }
  3423. if (keyCode === 38 || keyCode === 40) {
  3424. //arrow-up || arrow-down
  3425. event.preventDefault(); //don't scroll
  3426. module.popup('show');
  3427. }
  3428. },
  3429. inputChange: function () {
  3430. var val = $input.val();
  3431. var date = parser.date(val, settings);
  3432. module.set.date(date, false);
  3433. },
  3434. inputFocus: function () {
  3435. $container.addClass(className.active);
  3436. },
  3437. inputBlur: function () {
  3438. $container.removeClass(className.active);
  3439. if (settings.formatInput) {
  3440. var date = module.get.date();
  3441. var text = formatter.datetime(date, settings);
  3442. $input.val(text);
  3443. }
  3444. },
  3445. inputClick: function () {
  3446. module.popup('show');
  3447. }
  3448. },
  3449. get: {
  3450. weekOfYear: function(weekYear,weekMonth,weekDay) {
  3451. // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
  3452. var ms1d = 864e5, // milliseconds in a day
  3453. ms7d = 7 * ms1d; // milliseconds in a week
  3454. return function() { // return a closure so constants get calculated only once
  3455. var DC3 = Date.UTC(weekYear, weekMonth, weekDay + 3) / ms1d, // an Absolute Day Number
  3456. AWN = Math.floor(DC3 / 7), // an Absolute Week Number
  3457. Wyr = new Date(AWN * ms7d).getUTCFullYear();
  3458. return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
  3459. }();
  3460. },
  3461. date: function () {
  3462. return module.helper.sanitiseDate($module.data(metadata.date)) || null;
  3463. },
  3464. inputDate: function() {
  3465. return $input.val();
  3466. },
  3467. focusDate: function () {
  3468. return $module.data(metadata.focusDate) || null;
  3469. },
  3470. startDate: function () {
  3471. var startModule = module.get.calendarModule(settings.startCalendar);
  3472. return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
  3473. },
  3474. endDate: function () {
  3475. var endModule = module.get.calendarModule(settings.endCalendar);
  3476. return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
  3477. },
  3478. minDate: function() {
  3479. return $module.data(metadata.minDate) || null;
  3480. },
  3481. maxDate: function() {
  3482. return $module.data(metadata.maxDate) || null;
  3483. },
  3484. monthOffset: function () {
  3485. return $module.data(metadata.monthOffset) || 0;
  3486. },
  3487. mode: function () {
  3488. //only returns valid modes for the current settings
  3489. var mode = $module.data(metadata.mode) || settings.startMode;
  3490. var validModes = module.get.validModes();
  3491. if ($.inArray(mode, validModes) >= 0) {
  3492. return mode;
  3493. }
  3494. return settings.type === 'time' ? 'hour' :
  3495. settings.type === 'month' ? 'month' :
  3496. settings.type === 'year' ? 'year' : 'day';
  3497. },
  3498. type: function() {
  3499. return $module.data(metadata.type) || settings.type;
  3500. },
  3501. validModes: function () {
  3502. var validModes = [];
  3503. if (settings.type !== 'time') {
  3504. if (!settings.disableYear || settings.type === 'year') {
  3505. validModes.push('year');
  3506. }
  3507. if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
  3508. validModes.push('month');
  3509. }
  3510. if (settings.type.indexOf('date') >= 0) {
  3511. validModes.push('day');
  3512. }
  3513. }
  3514. if (settings.type.indexOf('time') >= 0) {
  3515. validModes.push('hour');
  3516. if (!settings.disableMinute) {
  3517. validModes.push('minute');
  3518. }
  3519. }
  3520. return validModes;
  3521. },
  3522. isTouch: function () {
  3523. try {
  3524. document.createEvent('TouchEvent');
  3525. return true;
  3526. }
  3527. catch (e) {
  3528. return false;
  3529. }
  3530. },
  3531. calendarModule: function (selector) {
  3532. if (!selector) {
  3533. return null;
  3534. }
  3535. if (!(selector instanceof $)) {
  3536. selector = $(selector).first();
  3537. }
  3538. //assume range related calendars are using the same namespace
  3539. return selector.data(moduleNamespace);
  3540. }
  3541. },
  3542. set: {
  3543. date: function (date, updateInput, fireChange) {
  3544. updateInput = updateInput !== false;
  3545. fireChange = fireChange !== false;
  3546. date = module.helper.sanitiseDate(date);
  3547. date = module.helper.dateInRange(date);
  3548. var mode = module.get.mode();
  3549. var text = formatter.datetime(date, settings);
  3550. if (fireChange && settings.onBeforeChange.call(element, date, text, mode) === false) {
  3551. return false;
  3552. }
  3553. module.set.focusDate(date);
  3554. if (settings.isDisabled(date, mode)) {
  3555. return false;
  3556. }
  3557. var endDate = module.get.endDate();
  3558. if (!!endDate && !!date && date > endDate) {
  3559. //selected date is greater than end date in range, so clear end date
  3560. module.set.endDate(undefined);
  3561. }
  3562. module.set.dataKeyValue(metadata.date, date);
  3563. if (updateInput && $input.length) {
  3564. $input.val(text);
  3565. }
  3566. if (fireChange) {
  3567. settings.onChange.call(element, date, text, mode);
  3568. }
  3569. },
  3570. startDate: function (date, refreshCalendar) {
  3571. date = module.helper.sanitiseDate(date);
  3572. var startModule = module.get.calendarModule(settings.startCalendar);
  3573. if (startModule) {
  3574. startModule.set.date(date);
  3575. }
  3576. module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
  3577. },
  3578. endDate: function (date, refreshCalendar) {
  3579. date = module.helper.sanitiseDate(date);
  3580. var endModule = module.get.calendarModule(settings.endCalendar);
  3581. if (endModule) {
  3582. endModule.set.date(date);
  3583. }
  3584. module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
  3585. },
  3586. focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
  3587. date = module.helper.sanitiseDate(date);
  3588. date = module.helper.dateInRange(date);
  3589. var isDay = module.get.mode() === 'day';
  3590. var oldFocusDate = module.get.focusDate();
  3591. if (isDay && date && oldFocusDate) {
  3592. var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
  3593. var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
  3594. if (monthDelta) {
  3595. var monthOffset = module.get.monthOffset() - monthDelta;
  3596. module.set.monthOffset(monthOffset, false);
  3597. }
  3598. }
  3599. var changed = module.set.dataKeyValue(metadata.focusDate, date, refreshCalendar);
  3600. updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
  3601. focusDateUsedForRange = updateRange;
  3602. if (updateFocus) {
  3603. module.update.focus(updateRange);
  3604. }
  3605. },
  3606. minDate: function (date) {
  3607. date = module.helper.sanitiseDate(date);
  3608. if (settings.maxDate !== null && settings.maxDate <= date) {
  3609. module.verbose('Unable to set minDate variable bigger that maxDate variable', date, settings.maxDate);
  3610. } else {
  3611. module.setting('minDate', date);
  3612. module.set.dataKeyValue(metadata.minDate, date);
  3613. }
  3614. },
  3615. maxDate: function (date) {
  3616. date = module.helper.sanitiseDate(date);
  3617. if (settings.minDate !== null && settings.minDate >= date) {
  3618. module.verbose('Unable to set maxDate variable lower that minDate variable', date, settings.minDate);
  3619. } else {
  3620. module.setting('maxDate', date);
  3621. module.set.dataKeyValue(metadata.maxDate, date);
  3622. }
  3623. },
  3624. monthOffset: function (monthOffset, refreshCalendar) {
  3625. var multiMonth = Math.max(settings.multiMonth, 1);
  3626. monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
  3627. module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
  3628. },
  3629. mode: function (mode, refreshCalendar) {
  3630. module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
  3631. },
  3632. dataKeyValue: function (key, value, refreshCalendar) {
  3633. var oldValue = $module.data(key);
  3634. var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects
  3635. if (value) {
  3636. $module.data(key, value);
  3637. } else {
  3638. $module.removeData(key);
  3639. }
  3640. refreshCalendar = refreshCalendar !== false && !equal;
  3641. if (refreshCalendar) {
  3642. module.refresh();
  3643. }
  3644. return !equal;
  3645. }
  3646. },
  3647. selectDate: function (date, forceSet) {
  3648. module.verbose('New date selection', date);
  3649. var mode = module.get.mode();
  3650. var complete = forceSet || mode === 'minute' ||
  3651. (settings.disableMinute && mode === 'hour') ||
  3652. (settings.type === 'date' && mode === 'day') ||
  3653. (settings.type === 'month' && mode === 'month') ||
  3654. (settings.type === 'year' && mode === 'year');
  3655. if (complete) {
  3656. var canceled = module.set.date(date) === false;
  3657. if (!canceled && settings.closable) {
  3658. module.popup('hide');
  3659. //if this is a range calendar, show the end date calendar popup and focus the input
  3660. var endModule = module.get.calendarModule(settings.endCalendar);
  3661. if (endModule) {
  3662. endModule.popup('show');
  3663. endModule.focus();
  3664. }
  3665. }
  3666. } else {
  3667. var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') :
  3668. mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute';
  3669. module.set.mode(newMode);
  3670. if (mode === 'hour' || (mode === 'day' && module.get.date())) {
  3671. //the user has chosen enough to consider a valid date/time has been chosen
  3672. module.set.date(date);
  3673. } else {
  3674. module.set.focusDate(date);
  3675. }
  3676. }
  3677. },
  3678. changeDate: function (date) {
  3679. module.set.date(date);
  3680. },
  3681. clear: function () {
  3682. module.set.date(undefined);
  3683. },
  3684. popup: function () {
  3685. return $activator.popup.apply($activator, arguments);
  3686. },
  3687. focus: function () {
  3688. if ($input.length) {
  3689. $input.focus();
  3690. } else {
  3691. $container.focus();
  3692. }
  3693. },
  3694. blur: function () {
  3695. if ($input.length) {
  3696. $input.blur();
  3697. } else {
  3698. $container.blur();
  3699. }
  3700. },
  3701. helper: {
  3702. isDisabled: function(date, mode) {
  3703. return (mode === 'day' || mode === 'month' || mode === 'year') && ((settings.disabledDaysOfWeek.indexOf(date.getDay()) !== -1) || settings.disabledDates.some(function(d){
  3704. if(typeof d === 'string') {
  3705. d = module.helper.sanitiseDate(d);
  3706. }
  3707. if (d instanceof Date) {
  3708. return module.helper.dateEqual(date, d, mode);
  3709. }
  3710. if (d !== null && typeof d === 'object') {
  3711. if (d[metadata.year]) {
  3712. if (typeof d[metadata.year] === 'number') {
  3713. return date.getFullYear() == d[metadata.year];
  3714. } else if (Array.isArray(d[metadata.year])) {
  3715. return d[metadata.year].indexOf(date.getFullYear()) > -1;
  3716. }
  3717. } else if (d[metadata.month]) {
  3718. if (typeof d[metadata.month] === 'number') {
  3719. return date.getMonth() == d[metadata.month];
  3720. } else if (Array.isArray(d[metadata.month])) {
  3721. return d[metadata.month].indexOf(date.getMonth()) > -1;
  3722. } else if (d[metadata.month] instanceof Date) {
  3723. var sdate = module.helper.sanitiseDate(d[metadata.month]);
  3724. return (date.getMonth() == sdate.getMonth()) && (date.getFullYear() == sdate.getFullYear())
  3725. }
  3726. } else if (d[metadata.date] && mode === 'day') {
  3727. if (d[metadata.date] instanceof Date) {
  3728. return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
  3729. } else if (Array.isArray(d[metadata.date])) {
  3730. return d[metadata.date].some(function(idate) {
  3731. return module.helper.dateEqual(date, idate, mode);
  3732. });
  3733. }
  3734. }
  3735. }
  3736. }));
  3737. },
  3738. isEnabled: function(date, mode) {
  3739. if (mode === 'day') {
  3740. return settings.enabledDates.length === 0 || settings.enabledDates.some(function(d){
  3741. if(typeof d === 'string') {
  3742. d = module.helper.sanitiseDate(d);
  3743. }
  3744. if (d instanceof Date) {
  3745. return module.helper.dateEqual(date, d, mode);
  3746. }
  3747. if (d !== null && typeof d === 'object' && d[metadata.date]) {
  3748. return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
  3749. }
  3750. });
  3751. } else {
  3752. return true;
  3753. }
  3754. },
  3755. findDayAsObject: function(date, mode, dates) {
  3756. if (mode === 'day' || mode === 'month' || mode === 'year') {
  3757. var d;
  3758. for (var i = 0; i < dates.length; i++) {
  3759. d = dates[i];
  3760. if(typeof d === 'string') {
  3761. d = module.helper.sanitiseDate(d);
  3762. }
  3763. if (d instanceof Date && module.helper.dateEqual(date, d, mode)) {
  3764. var dateObject = {};
  3765. dateObject[metadata.date] = d;
  3766. return dateObject;
  3767. }
  3768. else if (d !== null && typeof d === 'object') {
  3769. if (d[metadata.year]) {
  3770. if (typeof d[metadata.year] === 'number' && date.getFullYear() == d[metadata.year]) {
  3771. return d;
  3772. } else if (Array.isArray(d[metadata.year])) {
  3773. if (d[metadata.year].indexOf(date.getFullYear()) > -1) {
  3774. return d;
  3775. }
  3776. }
  3777. } else if (d[metadata.month]) {
  3778. if (typeof d[metadata.month] === 'number' && date.getMonth() == d[metadata.month]) {
  3779. return d;
  3780. } else if (Array.isArray(d[metadata.month])) {
  3781. if (d[metadata.month].indexOf(date.getMonth()) > -1) {
  3782. return d;
  3783. }
  3784. } else if (d[metadata.month] instanceof Date) {
  3785. var sdate = module.helper.sanitiseDate(d[metadata.month]);
  3786. if ((date.getMonth() == sdate.getMonth()) && (date.getFullYear() == sdate.getFullYear())) {
  3787. return d;
  3788. }
  3789. }
  3790. } else if (d[metadata.date] && mode === 'day') {
  3791. if (d[metadata.date] instanceof Date && module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode)) {
  3792. return d;
  3793. } else if (Array.isArray(d[metadata.date])) {
  3794. if(d[metadata.date].some(function(idate) { return module.helper.dateEqual(date, idate, mode); })) {
  3795. return d;
  3796. }
  3797. }
  3798. }
  3799. }
  3800. }
  3801. }
  3802. return null;
  3803. },
  3804. sanitiseDate: function (date) {
  3805. if (!date) {
  3806. return undefined;
  3807. }
  3808. if (!(date instanceof Date)) {
  3809. date = parser.date('' + date, settings);
  3810. }
  3811. if (!date || date === null || isNaN(date.getTime())) {
  3812. return undefined;
  3813. }
  3814. return date;
  3815. },
  3816. dateDiff: function (date1, date2, mode) {
  3817. mode = mode || 'day';
  3818. var isTimeOnly = settings.type === 'time';
  3819. var isYear = mode === 'year';
  3820. var isYearOrMonth = isYear || mode === 'month';
  3821. var isMinute = mode === 'minute';
  3822. var isHourOrMinute = isMinute || mode === 'hour';
  3823. //only care about a minute accuracy of settings.minTimeGap
  3824. date1 = new Date(
  3825. isTimeOnly ? 2000 : date1.getFullYear(),
  3826. isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
  3827. isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
  3828. !isHourOrMinute ? 0 : date1.getHours(),
  3829. !isMinute ? 0 : settings.minTimeGap * Math.floor(date1.getMinutes() / settings.minTimeGap));
  3830. date2 = new Date(
  3831. isTimeOnly ? 2000 : date2.getFullYear(),
  3832. isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
  3833. isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
  3834. !isHourOrMinute ? 0 : date2.getHours(),
  3835. !isMinute ? 0 : settings.minTimeGap * Math.floor(date2.getMinutes() / settings.minTimeGap));
  3836. return date2.getTime() - date1.getTime();
  3837. },
  3838. dateEqual: function (date1, date2, mode) {
  3839. return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
  3840. },
  3841. isDateInRange: function (date, mode, minDate, maxDate) {
  3842. if (!minDate && !maxDate) {
  3843. var startDate = module.get.startDate();
  3844. minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
  3845. maxDate = settings.maxDate;
  3846. }
  3847. minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
  3848. return !(!date ||
  3849. (minDate && module.helper.dateDiff(date, minDate, mode) > 0) ||
  3850. (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
  3851. },
  3852. dateInRange: function (date, minDate, maxDate) {
  3853. if (!minDate && !maxDate) {
  3854. var startDate = module.get.startDate();
  3855. minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
  3856. maxDate = settings.maxDate;
  3857. }
  3858. minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
  3859. var isTimeOnly = settings.type === 'time';
  3860. return !date ? date :
  3861. (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ?
  3862. (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) :
  3863. (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ?
  3864. (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) :
  3865. date;
  3866. },
  3867. mergeDateTime: function (date, time) {
  3868. return (!date || !time) ? time :
  3869. new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
  3870. },
  3871. isTodayButton: function(element) {
  3872. return element.text() === settings.text.today;
  3873. }
  3874. },
  3875. setting: function (name, value) {
  3876. module.debug('Changing setting', name, value);
  3877. if ($.isPlainObject(name)) {
  3878. $.extend(true, settings, name);
  3879. }
  3880. else if (value !== undefined) {
  3881. if ($.isPlainObject(settings[name])) {
  3882. $.extend(true, settings[name], value);
  3883. }
  3884. else {
  3885. settings[name] = value;
  3886. }
  3887. }
  3888. else {
  3889. return settings[name];
  3890. }
  3891. },
  3892. internal: function (name, value) {
  3893. if( $.isPlainObject(name) ) {
  3894. $.extend(true, module, name);
  3895. }
  3896. else if(value !== undefined) {
  3897. module[name] = value;
  3898. }
  3899. else {
  3900. return module[name];
  3901. }
  3902. },
  3903. debug: function () {
  3904. if (!settings.silent && settings.debug) {
  3905. if (settings.performance) {
  3906. module.performance.log(arguments);
  3907. }
  3908. else {
  3909. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3910. module.debug.apply(console, arguments);
  3911. }
  3912. }
  3913. },
  3914. verbose: function () {
  3915. if (!settings.silent && settings.verbose && settings.debug) {
  3916. if (settings.performance) {
  3917. module.performance.log(arguments);
  3918. }
  3919. else {
  3920. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3921. module.verbose.apply(console, arguments);
  3922. }
  3923. }
  3924. },
  3925. error: function () {
  3926. if (!settings.silent) {
  3927. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3928. module.error.apply(console, arguments);
  3929. }
  3930. },
  3931. performance: {
  3932. log: function (message) {
  3933. var
  3934. currentTime,
  3935. executionTime,
  3936. previousTime
  3937. ;
  3938. if (settings.performance) {
  3939. currentTime = new Date().getTime();
  3940. previousTime = time || currentTime;
  3941. executionTime = currentTime - previousTime;
  3942. time = currentTime;
  3943. performance.push({
  3944. 'Name': message[0],
  3945. 'Arguments': [].slice.call(message, 1) || '',
  3946. 'Element': element,
  3947. 'Execution Time': executionTime
  3948. });
  3949. }
  3950. clearTimeout(module.performance.timer);
  3951. module.performance.timer = setTimeout(module.performance.display, 500);
  3952. },
  3953. display: function () {
  3954. var
  3955. title = settings.name + ':',
  3956. totalTime = 0
  3957. ;
  3958. time = false;
  3959. clearTimeout(module.performance.timer);
  3960. $.each(performance, function (index, data) {
  3961. totalTime += data['Execution Time'];
  3962. });
  3963. title += ' ' + totalTime + 'ms';
  3964. if (moduleSelector) {
  3965. title += ' \'' + moduleSelector + '\'';
  3966. }
  3967. if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3968. console.groupCollapsed(title);
  3969. if (console.table) {
  3970. console.table(performance);
  3971. }
  3972. else {
  3973. $.each(performance, function (index, data) {
  3974. console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
  3975. });
  3976. }
  3977. console.groupEnd();
  3978. }
  3979. performance = [];
  3980. }
  3981. },
  3982. invoke: function (query, passedArguments, context) {
  3983. var
  3984. object = instance,
  3985. maxDepth,
  3986. found,
  3987. response
  3988. ;
  3989. passedArguments = passedArguments || queryArguments;
  3990. context = element || context;
  3991. if (typeof query == 'string' && object !== undefined) {
  3992. query = query.split(/[\. ]/);
  3993. maxDepth = query.length - 1;
  3994. $.each(query, function (depth, value) {
  3995. var camelCaseValue = (depth != maxDepth)
  3996. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3997. : query
  3998. ;
  3999. if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
  4000. object = object[camelCaseValue];
  4001. }
  4002. else if (object[camelCaseValue] !== undefined) {
  4003. found = object[camelCaseValue];
  4004. return false;
  4005. }
  4006. else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
  4007. object = object[value];
  4008. }
  4009. else if (object[value] !== undefined) {
  4010. found = object[value];
  4011. return false;
  4012. }
  4013. else {
  4014. module.error(error.method, query);
  4015. return false;
  4016. }
  4017. });
  4018. }
  4019. if ($.isFunction(found)) {
  4020. response = found.apply(context, passedArguments);
  4021. }
  4022. else if (found !== undefined) {
  4023. response = found;
  4024. }
  4025. if (Array.isArray(returnedValue)) {
  4026. returnedValue.push(response);
  4027. }
  4028. else if (returnedValue !== undefined) {
  4029. returnedValue = [returnedValue, response];
  4030. }
  4031. else if (response !== undefined) {
  4032. returnedValue = response;
  4033. }
  4034. return found;
  4035. }
  4036. };
  4037. if (methodInvoked) {
  4038. if (instance === undefined) {
  4039. module.initialize();
  4040. }
  4041. module.invoke(query);
  4042. }
  4043. else {
  4044. if (instance !== undefined) {
  4045. instance.invoke('destroy');
  4046. }
  4047. module.initialize();
  4048. }
  4049. })
  4050. ;
  4051. return (returnedValue !== undefined)
  4052. ? returnedValue
  4053. : this
  4054. ;
  4055. };
  4056. $.fn.calendar.settings = {
  4057. name : 'Calendar',
  4058. namespace : 'calendar',
  4059. silent: false,
  4060. debug: false,
  4061. verbose: false,
  4062. performance: false,
  4063. type : 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
  4064. firstDayOfWeek : 0, // day for first day column (0 = Sunday)
  4065. constantHeight : true, // add rows to shorter months to keep day calendar height consistent (6 rows)
  4066. today : false, // show a 'today/now' button at the bottom of the calendar
  4067. closable : true, // close the popup after selecting a date/time
  4068. monthFirst : true, // month before day when parsing/converting date from/to text
  4069. touchReadonly : true, // set input to readonly on touch devices
  4070. inline : false, // create the calendar inline instead of inside a popup
  4071. on : null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
  4072. initialDate : null, // date to display initially when no date is selected (null = now)
  4073. startMode : false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
  4074. minDate : null, // minimum date/time that can be selected, dates/times before are disabled
  4075. maxDate : null, // maximum date/time that can be selected, dates/times after are disabled
  4076. ampm : true, // show am/pm in time mode
  4077. disableYear : false, // disable year selection mode
  4078. disableMonth : false, // disable month selection mode
  4079. disableMinute : false, // disable minute selection mode
  4080. formatInput : true, // format the input text upon input blur and module creation
  4081. startCalendar : null, // jquery object or selector for another calendar that represents the start date of a date range
  4082. endCalendar : null, // jquery object or selector for another calendar that represents the end date of a date range
  4083. multiMonth : 1, // show multiple months when in 'day' mode
  4084. minTimeGap : 5,
  4085. showWeekNumbers : null, // show Number of Week at the very first column of a dayView
  4086. disabledDates : [], // specific day(s) which won't be selectable and contain additional information.
  4087. disabledDaysOfWeek : [], // day(s) which won't be selectable(s) (0 = Sunday)
  4088. enabledDates : [], // specific day(s) which will be selectable, all other days will be disabled
  4089. eventDates : [], // specific day(s) which will be shown in a different color and using tooltips
  4090. centuryBreak : 60, // starting short year until 99 where it will be assumed to belong to the last century
  4091. currentCentury : 2000, // century to be added to 2-digit years (00 to {centuryBreak}-1)
  4092. selectAdjacentDays : false, // The calendar can show dates from adjacent month. These adjacent month dates can also be made selectable.
  4093. // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
  4094. popupOptions: {
  4095. position: 'bottom left',
  4096. lastResort: 'bottom left',
  4097. prefer: 'opposite',
  4098. hideOnScroll: false
  4099. },
  4100. text: {
  4101. days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
  4102. months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  4103. monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  4104. today: 'Today',
  4105. now: 'Now',
  4106. am: 'AM',
  4107. pm: 'PM',
  4108. weekNo: 'Week'
  4109. },
  4110. formatter: {
  4111. header: function (date, mode, settings) {
  4112. return mode === 'year' ? settings.formatter.yearHeader(date, settings) :
  4113. mode === 'month' ? settings.formatter.monthHeader(date, settings) :
  4114. mode === 'day' ? settings.formatter.dayHeader(date, settings) :
  4115. mode === 'hour' ? settings.formatter.hourHeader(date, settings) :
  4116. settings.formatter.minuteHeader(date, settings);
  4117. },
  4118. yearHeader: function (date, settings) {
  4119. var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
  4120. return (decadeYear - 9) + ' - ' + (decadeYear + 2);
  4121. },
  4122. monthHeader: function (date, settings) {
  4123. return date.getFullYear();
  4124. },
  4125. dayHeader: function (date, settings) {
  4126. var month = settings.text.months[date.getMonth()];
  4127. var year = date.getFullYear();
  4128. return month + ' ' + year;
  4129. },
  4130. hourHeader: function (date, settings) {
  4131. return settings.formatter.date(date, settings);
  4132. },
  4133. minuteHeader: function (date, settings) {
  4134. return settings.formatter.date(date, settings);
  4135. },
  4136. dayColumnHeader: function (day, settings) {
  4137. return settings.text.days[day];
  4138. },
  4139. datetime: function (date, settings) {
  4140. if (!date) {
  4141. return '';
  4142. }
  4143. var day = settings.type === 'time' ? '' : settings.formatter.date(date, settings);
  4144. var time = settings.type.indexOf('time') < 0 ? '' : settings.formatter.time(date, settings, false);
  4145. var separator = settings.type === 'datetime' ? ' ' : '';
  4146. return day + separator + time;
  4147. },
  4148. date: function (date, settings) {
  4149. if (!date) {
  4150. return '';
  4151. }
  4152. var day = date.getDate();
  4153. var month = settings.text.months[date.getMonth()];
  4154. var year = date.getFullYear();
  4155. return settings.type === 'year' ? year :
  4156. settings.type === 'month' ? month + ' ' + year :
  4157. (settings.monthFirst ? month + ' ' + day : day + ' ' + month) + ', ' + year;
  4158. },
  4159. time: function (date, settings, forCalendar) {
  4160. if (!date) {
  4161. return '';
  4162. }
  4163. var hour = date.getHours();
  4164. var minute = date.getMinutes();
  4165. var ampm = '';
  4166. if (settings.ampm) {
  4167. ampm = ' ' + (hour < 12 ? settings.text.am : settings.text.pm);
  4168. hour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
  4169. }
  4170. return hour + ':' + (minute < 10 ? '0' : '') + minute + ampm;
  4171. },
  4172. today: function (settings) {
  4173. return settings.type === 'date' ? settings.text.today : settings.text.now;
  4174. },
  4175. cell: function (cell, date, cellOptions) {
  4176. }
  4177. },
  4178. parser: {
  4179. date: function (text, settings) {
  4180. if (text instanceof Date) {
  4181. return text;
  4182. }
  4183. if (!text) {
  4184. return null;
  4185. }
  4186. text = ('' + text).trim().toLowerCase();
  4187. if (text.length === 0) {
  4188. return null;
  4189. }
  4190. // Reverse date and month in some cases
  4191. text = settings.monthFirst ? text : text.replace(/[\/\-\.]/g,'/').replace(/([0-9]+)\/([0-9]+)/,'$2/$1');
  4192. var textDate = new Date(text);
  4193. if(!isNaN(textDate.getDate())) {
  4194. return textDate;
  4195. }
  4196. var i, j, k;
  4197. var minute = -1, hour = -1, day = -1, month = -1, year = -1;
  4198. var isAm = undefined;
  4199. var isTimeOnly = settings.type === 'time';
  4200. var isDateOnly = settings.type.indexOf('time') < 0;
  4201. var words = text.split(settings.regExp.dateWords), word;
  4202. var numbers = text.split(settings.regExp.dateNumbers), number;
  4203. var parts;
  4204. var monthString;
  4205. if (!isDateOnly) {
  4206. //am/pm
  4207. isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true :
  4208. $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
  4209. //time with ':'
  4210. for (i = 0; i < numbers.length; i++) {
  4211. number = numbers[i];
  4212. if (number.indexOf(':') >= 0) {
  4213. if (hour < 0 || minute < 0) {
  4214. parts = number.split(':');
  4215. for (k = 0; k < Math.min(2, parts.length); k++) {
  4216. j = parseInt(parts[k]);
  4217. if (isNaN(j)) {
  4218. j = 0;
  4219. }
  4220. if (k === 0) {
  4221. hour = j % 24;
  4222. } else {
  4223. minute = j % 60;
  4224. }
  4225. }
  4226. }
  4227. numbers.splice(i, 1);
  4228. }
  4229. }
  4230. }
  4231. if (!isTimeOnly) {
  4232. //textual month
  4233. for (i = 0; i < words.length; i++) {
  4234. word = words[i];
  4235. if (word.length <= 0) {
  4236. continue;
  4237. }
  4238. for (j = 0; j < settings.text.months.length; j++) {
  4239. monthString = settings.text.months[j];
  4240. monthString = monthString.substring(0, word.length).toLowerCase();
  4241. if (monthString === word) {
  4242. month = j + 1;
  4243. break;
  4244. }
  4245. }
  4246. if (month >= 0) {
  4247. break;
  4248. }
  4249. }
  4250. //year > settings.centuryBreak
  4251. for (i = 0; i < numbers.length; i++) {
  4252. j = parseInt(numbers[i]);
  4253. if (isNaN(j)) {
  4254. continue;
  4255. }
  4256. if (j >= settings.centuryBreak && i === numbers.length-1) {
  4257. if (j <= 99) {
  4258. j += settings.currentCentury - 100;
  4259. }
  4260. year = j;
  4261. numbers.splice(i, 1);
  4262. break;
  4263. }
  4264. }
  4265. //numeric month
  4266. if (month < 0) {
  4267. for (i = 0; i < numbers.length; i++) {
  4268. k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
  4269. j = parseInt(numbers[k]);
  4270. if (isNaN(j)) {
  4271. continue;
  4272. }
  4273. if (1 <= j && j <= 12) {
  4274. month = j;
  4275. numbers.splice(k, 1);
  4276. break;
  4277. }
  4278. }
  4279. }
  4280. //day
  4281. for (i = 0; i < numbers.length; i++) {
  4282. j = parseInt(numbers[i]);
  4283. if (isNaN(j)) {
  4284. continue;
  4285. }
  4286. if (1 <= j && j <= 31) {
  4287. day = j;
  4288. numbers.splice(i, 1);
  4289. break;
  4290. }
  4291. }
  4292. //year <= settings.centuryBreak
  4293. if (year < 0) {
  4294. for (i = numbers.length - 1; i >= 0; i--) {
  4295. j = parseInt(numbers[i]);
  4296. if (isNaN(j)) {
  4297. continue;
  4298. }
  4299. if (j <= 99) {
  4300. j += settings.currentCentury;
  4301. }
  4302. year = j;
  4303. numbers.splice(i, 1);
  4304. break;
  4305. }
  4306. }
  4307. }
  4308. if (!isDateOnly) {
  4309. //hour
  4310. if (hour < 0) {
  4311. for (i = 0; i < numbers.length; i++) {
  4312. j = parseInt(numbers[i]);
  4313. if (isNaN(j)) {
  4314. continue;
  4315. }
  4316. if (0 <= j && j <= 23) {
  4317. hour = j;
  4318. numbers.splice(i, 1);
  4319. break;
  4320. }
  4321. }
  4322. }
  4323. //minute
  4324. if (minute < 0) {
  4325. for (i = 0; i < numbers.length; i++) {
  4326. j = parseInt(numbers[i]);
  4327. if (isNaN(j)) {
  4328. continue;
  4329. }
  4330. if (0 <= j && j <= 59) {
  4331. minute = j;
  4332. numbers.splice(i, 1);
  4333. break;
  4334. }
  4335. }
  4336. }
  4337. }
  4338. if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
  4339. return null;
  4340. }
  4341. if (minute < 0) {
  4342. minute = 0;
  4343. }
  4344. if (hour < 0) {
  4345. hour = 0;
  4346. }
  4347. if (day < 0) {
  4348. day = 1;
  4349. }
  4350. if (month < 0) {
  4351. month = 1;
  4352. }
  4353. if (year < 0) {
  4354. year = new Date().getFullYear();
  4355. }
  4356. if (isAm !== undefined) {
  4357. if (isAm) {
  4358. if (hour === 12) {
  4359. hour = 0;
  4360. }
  4361. } else if (hour < 12) {
  4362. hour += 12;
  4363. }
  4364. }
  4365. var date = new Date(year, month - 1, day, hour, minute);
  4366. if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
  4367. //month or year don't match up, switch to last day of the month
  4368. date = new Date(year, month, 0, hour, minute);
  4369. }
  4370. return isNaN(date.getTime()) ? null : date;
  4371. }
  4372. },
  4373. // callback before date is changed, return false to cancel the change
  4374. onBeforeChange: function (date, text, mode) {
  4375. return true;
  4376. },
  4377. // callback when date changes
  4378. onChange: function (date, text, mode) {
  4379. },
  4380. // callback before show animation, return false to prevent show
  4381. onShow: function () {
  4382. },
  4383. // callback after show animation
  4384. onVisible: function () {
  4385. },
  4386. // callback before hide animation, return false to prevent hide
  4387. onHide: function () {
  4388. },
  4389. // callback after hide animation
  4390. onHidden: function () {
  4391. },
  4392. // callback before item is selected, return false to prevent selection
  4393. onSelect: function (date, mode) {
  4394. },
  4395. // is the given date disabled?
  4396. isDisabled: function (date, mode) {
  4397. return false;
  4398. },
  4399. selector: {
  4400. popup: '.ui.popup',
  4401. input: 'input',
  4402. activator: 'input',
  4403. append: '.inline.field,.inline.fields'
  4404. },
  4405. regExp: {
  4406. dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
  4407. dateNumbers: /[^\d:]+/g
  4408. },
  4409. error: {
  4410. popup: 'UI Popup, a required component is not included in this page',
  4411. method: 'The method you called is not defined.'
  4412. },
  4413. className: {
  4414. calendar: 'calendar',
  4415. active: 'active',
  4416. popup: 'ui popup',
  4417. grid: 'ui equal width grid',
  4418. column: 'column',
  4419. table: 'ui celled center aligned unstackable table',
  4420. prev: 'prev link',
  4421. next: 'next link',
  4422. prevIcon: 'chevron left icon',
  4423. nextIcon: 'chevron right icon',
  4424. link: 'link',
  4425. cell: 'link',
  4426. disabledCell: 'disabled',
  4427. weekCell: 'disabled',
  4428. adjacentCell: 'adjacent',
  4429. activeCell: 'active',
  4430. rangeCell: 'range',
  4431. focusCell: 'focus',
  4432. todayCell: 'today',
  4433. today: 'today link'
  4434. },
  4435. metadata: {
  4436. date: 'date',
  4437. focusDate: 'focusDate',
  4438. startDate: 'startDate',
  4439. endDate: 'endDate',
  4440. minDate: 'minDate',
  4441. maxDate: 'maxDate',
  4442. mode: 'mode',
  4443. type: 'type',
  4444. monthOffset: 'monthOffset',
  4445. message: 'message',
  4446. class: 'class',
  4447. month: 'month',
  4448. year: 'year'
  4449. },
  4450. eventClass: 'blue'
  4451. };
  4452. })(jQuery, window, document);
  4453. /*!
  4454. * # Fomantic-UI - Checkbox
  4455. * http://github.com/fomantic/Fomantic-UI/
  4456. *
  4457. *
  4458. * Released under the MIT license
  4459. * http://opensource.org/licenses/MIT
  4460. *
  4461. */
  4462. ;(function ($, window, document, undefined) {
  4463. 'use strict';
  4464. $.isFunction = $.isFunction || function(obj) {
  4465. return typeof obj === "function" && typeof obj.nodeType !== "number";
  4466. };
  4467. window = (typeof window != 'undefined' && window.Math == Math)
  4468. ? window
  4469. : (typeof self != 'undefined' && self.Math == Math)
  4470. ? self
  4471. : Function('return this')()
  4472. ;
  4473. $.fn.checkbox = function(parameters) {
  4474. var
  4475. $allModules = $(this),
  4476. moduleSelector = $allModules.selector || '',
  4477. time = new Date().getTime(),
  4478. performance = [],
  4479. query = arguments[0],
  4480. methodInvoked = (typeof query == 'string'),
  4481. queryArguments = [].slice.call(arguments, 1),
  4482. returnedValue
  4483. ;
  4484. $allModules
  4485. .each(function() {
  4486. var
  4487. settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
  4488. className = settings.className,
  4489. namespace = settings.namespace,
  4490. selector = settings.selector,
  4491. error = settings.error,
  4492. eventNamespace = '.' + namespace,
  4493. moduleNamespace = 'module-' + namespace,
  4494. $module = $(this),
  4495. $label = $(this).children(selector.label),
  4496. $input = $(this).children(selector.input),
  4497. input = $input[0],
  4498. initialLoad = false,
  4499. shortcutPressed = false,
  4500. instance = $module.data(moduleNamespace),
  4501. observer,
  4502. element = this,
  4503. module
  4504. ;
  4505. module = {
  4506. initialize: function() {
  4507. module.verbose('Initializing checkbox', settings);
  4508. module.create.label();
  4509. module.bind.events();
  4510. module.set.tabbable();
  4511. module.hide.input();
  4512. module.observeChanges();
  4513. module.instantiate();
  4514. module.setup();
  4515. },
  4516. instantiate: function() {
  4517. module.verbose('Storing instance of module', module);
  4518. instance = module;
  4519. $module
  4520. .data(moduleNamespace, module)
  4521. ;
  4522. },
  4523. destroy: function() {
  4524. module.verbose('Destroying module');
  4525. module.unbind.events();
  4526. module.show.input();
  4527. $module.removeData(moduleNamespace);
  4528. },
  4529. fix: {
  4530. reference: function() {
  4531. if( $module.is(selector.input) ) {
  4532. module.debug('Behavior called on <input> adjusting invoked element');
  4533. $module = $module.closest(selector.checkbox);
  4534. module.refresh();
  4535. }
  4536. }
  4537. },
  4538. setup: function() {
  4539. module.set.initialLoad();
  4540. if( module.is.indeterminate() ) {
  4541. module.debug('Initial value is indeterminate');
  4542. module.indeterminate();
  4543. }
  4544. else if( module.is.checked() ) {
  4545. module.debug('Initial value is checked');
  4546. module.check();
  4547. }
  4548. else {
  4549. module.debug('Initial value is unchecked');
  4550. module.uncheck();
  4551. }
  4552. module.remove.initialLoad();
  4553. },
  4554. refresh: function() {
  4555. $label = $module.children(selector.label);
  4556. $input = $module.children(selector.input);
  4557. input = $input[0];
  4558. },
  4559. hide: {
  4560. input: function() {
  4561. module.verbose('Modifying <input> z-index to be unselectable');
  4562. $input.addClass(className.hidden);
  4563. }
  4564. },
  4565. show: {
  4566. input: function() {
  4567. module.verbose('Modifying <input> z-index to be selectable');
  4568. $input.removeClass(className.hidden);
  4569. }
  4570. },
  4571. observeChanges: function() {
  4572. if('MutationObserver' in window) {
  4573. observer = new MutationObserver(function(mutations) {
  4574. module.debug('DOM tree modified, updating selector cache');
  4575. module.refresh();
  4576. });
  4577. observer.observe(element, {
  4578. childList : true,
  4579. subtree : true
  4580. });
  4581. module.debug('Setting up mutation observer', observer);
  4582. }
  4583. },
  4584. attachEvents: function(selector, event) {
  4585. var
  4586. $element = $(selector)
  4587. ;
  4588. event = $.isFunction(module[event])
  4589. ? module[event]
  4590. : module.toggle
  4591. ;
  4592. if($element.length > 0) {
  4593. module.debug('Attaching checkbox events to element', selector, event);
  4594. $element
  4595. .on('click' + eventNamespace, event)
  4596. ;
  4597. }
  4598. else {
  4599. module.error(error.notFound);
  4600. }
  4601. },
  4602. preventDefaultOnInputTarget: function() {
  4603. if(typeof event !== 'undefined' && event !== null && $(event.target).is(selector.input)) {
  4604. module.verbose('Preventing default check action after manual check action');
  4605. event.preventDefault();
  4606. }
  4607. },
  4608. event: {
  4609. change: function(event) {
  4610. if( !module.should.ignoreCallbacks() ) {
  4611. settings.onChange.call(input);
  4612. }
  4613. },
  4614. click: function(event) {
  4615. var
  4616. $target = $(event.target)
  4617. ;
  4618. if( $target.is(selector.input) ) {
  4619. module.verbose('Using default check action on initialized checkbox');
  4620. return;
  4621. }
  4622. if( $target.is(selector.link) ) {
  4623. module.debug('Clicking link inside checkbox, skipping toggle');
  4624. return;
  4625. }
  4626. module.toggle();
  4627. $input.focus();
  4628. event.preventDefault();
  4629. },
  4630. keydown: function(event) {
  4631. var
  4632. key = event.which,
  4633. keyCode = {
  4634. enter : 13,
  4635. space : 32,
  4636. escape : 27,
  4637. left : 37,
  4638. up : 38,
  4639. right : 39,
  4640. down : 40
  4641. }
  4642. ;
  4643. var r = module.get.radios(),
  4644. rIndex = r.index($module),
  4645. rLen = r.length,
  4646. checkIndex = false;
  4647. if(key == keyCode.left || key == keyCode.up) {
  4648. checkIndex = (rIndex === 0 ? rLen : rIndex) - 1;
  4649. } else if(key == keyCode.right || key == keyCode.down) {
  4650. checkIndex = rIndex === rLen-1 ? 0 : rIndex+1;
  4651. }
  4652. if (!module.should.ignoreCallbacks() && checkIndex !== false) {
  4653. if(settings.beforeUnchecked.apply(input)===false) {
  4654. module.verbose('Option not allowed to be unchecked, cancelling key navigation');
  4655. return false;
  4656. }
  4657. if (settings.beforeChecked.apply($(r[checkIndex]).children(selector.input)[0])===false) {
  4658. module.verbose('Next option should not allow check, cancelling key navigation');
  4659. return false;
  4660. }
  4661. }
  4662. if(key == keyCode.escape) {
  4663. module.verbose('Escape key pressed blurring field');
  4664. $input.blur();
  4665. shortcutPressed = true;
  4666. }
  4667. else if(!event.ctrlKey && ( key == keyCode.space || (key == keyCode.enter && settings.enableEnterKey)) ) {
  4668. module.verbose('Enter/space key pressed, toggling checkbox');
  4669. module.toggle();
  4670. shortcutPressed = true;
  4671. }
  4672. else {
  4673. shortcutPressed = false;
  4674. }
  4675. },
  4676. keyup: function(event) {
  4677. if(shortcutPressed) {
  4678. event.preventDefault();
  4679. }
  4680. }
  4681. },
  4682. check: function() {
  4683. if( !module.should.allowCheck() ) {
  4684. return;
  4685. }
  4686. module.debug('Checking checkbox', $input);
  4687. module.set.checked();
  4688. if( !module.should.ignoreCallbacks() ) {
  4689. settings.onChecked.call(input);
  4690. module.trigger.change();
  4691. }
  4692. module.preventDefaultOnInputTarget();
  4693. },
  4694. uncheck: function() {
  4695. if( !module.should.allowUncheck() ) {
  4696. return;
  4697. }
  4698. module.debug('Unchecking checkbox');
  4699. module.set.unchecked();
  4700. if( !module.should.ignoreCallbacks() ) {
  4701. settings.onUnchecked.call(input);
  4702. module.trigger.change();
  4703. }
  4704. module.preventDefaultOnInputTarget();
  4705. },
  4706. indeterminate: function() {
  4707. if( module.should.allowIndeterminate() ) {
  4708. module.debug('Checkbox is already indeterminate');
  4709. return;
  4710. }
  4711. module.debug('Making checkbox indeterminate');
  4712. module.set.indeterminate();
  4713. if( !module.should.ignoreCallbacks() ) {
  4714. settings.onIndeterminate.call(input);
  4715. module.trigger.change();
  4716. }
  4717. },
  4718. determinate: function() {
  4719. if( module.should.allowDeterminate() ) {
  4720. module.debug('Checkbox is already determinate');
  4721. return;
  4722. }
  4723. module.debug('Making checkbox determinate');
  4724. module.set.determinate();
  4725. if( !module.should.ignoreCallbacks() ) {
  4726. settings.onDeterminate.call(input);
  4727. module.trigger.change();
  4728. }
  4729. },
  4730. enable: function() {
  4731. if( module.is.enabled() ) {
  4732. module.debug('Checkbox is already enabled');
  4733. return;
  4734. }
  4735. module.debug('Enabling checkbox');
  4736. module.set.enabled();
  4737. if( !module.should.ignoreCallbacks() ) {
  4738. settings.onEnable.call(input);
  4739. // preserve legacy callbacks
  4740. settings.onEnabled.call(input);
  4741. module.trigger.change();
  4742. }
  4743. },
  4744. disable: function() {
  4745. if( module.is.disabled() ) {
  4746. module.debug('Checkbox is already disabled');
  4747. return;
  4748. }
  4749. module.debug('Disabling checkbox');
  4750. module.set.disabled();
  4751. if( !module.should.ignoreCallbacks() ) {
  4752. settings.onDisable.call(input);
  4753. // preserve legacy callbacks
  4754. settings.onDisabled.call(input);
  4755. module.trigger.change();
  4756. }
  4757. },
  4758. get: {
  4759. radios: function() {
  4760. var
  4761. name = module.get.name()
  4762. ;
  4763. return $('input[name="' + name + '"]').closest(selector.checkbox);
  4764. },
  4765. otherRadios: function() {
  4766. return module.get.radios().not($module);
  4767. },
  4768. name: function() {
  4769. return $input.attr('name');
  4770. }
  4771. },
  4772. is: {
  4773. initialLoad: function() {
  4774. return initialLoad;
  4775. },
  4776. radio: function() {
  4777. return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
  4778. },
  4779. indeterminate: function() {
  4780. return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
  4781. },
  4782. checked: function() {
  4783. return $input.prop('checked') !== undefined && $input.prop('checked');
  4784. },
  4785. disabled: function() {
  4786. return $input.prop('disabled') !== undefined && $input.prop('disabled');
  4787. },
  4788. enabled: function() {
  4789. return !module.is.disabled();
  4790. },
  4791. determinate: function() {
  4792. return !module.is.indeterminate();
  4793. },
  4794. unchecked: function() {
  4795. return !module.is.checked();
  4796. }
  4797. },
  4798. should: {
  4799. allowCheck: function() {
  4800. if(module.is.determinate() && module.is.checked() && !module.is.initialLoad() ) {
  4801. module.debug('Should not allow check, checkbox is already checked');
  4802. return false;
  4803. }
  4804. if(!module.should.ignoreCallbacks() && settings.beforeChecked.apply(input) === false) {
  4805. module.debug('Should not allow check, beforeChecked cancelled');
  4806. return false;
  4807. }
  4808. return true;
  4809. },
  4810. allowUncheck: function() {
  4811. if(module.is.determinate() && module.is.unchecked() && !module.is.initialLoad() ) {
  4812. module.debug('Should not allow uncheck, checkbox is already unchecked');
  4813. return false;
  4814. }
  4815. if(!module.should.ignoreCallbacks() && settings.beforeUnchecked.apply(input) === false) {
  4816. module.debug('Should not allow uncheck, beforeUnchecked cancelled');
  4817. return false;
  4818. }
  4819. return true;
  4820. },
  4821. allowIndeterminate: function() {
  4822. if(module.is.indeterminate() && !module.is.initialLoad() ) {
  4823. module.debug('Should not allow indeterminate, checkbox is already indeterminate');
  4824. return false;
  4825. }
  4826. if(!module.should.ignoreCallbacks() && settings.beforeIndeterminate.apply(input) === false) {
  4827. module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
  4828. return false;
  4829. }
  4830. return true;
  4831. },
  4832. allowDeterminate: function() {
  4833. if(module.is.determinate() && !module.is.initialLoad() ) {
  4834. module.debug('Should not allow determinate, checkbox is already determinate');
  4835. return false;
  4836. }
  4837. if(!module.should.ignoreCallbacks() && settings.beforeDeterminate.apply(input) === false) {
  4838. module.debug('Should not allow determinate, beforeDeterminate cancelled');
  4839. return false;
  4840. }
  4841. return true;
  4842. },
  4843. ignoreCallbacks: function() {
  4844. return (initialLoad && !settings.fireOnInit);
  4845. }
  4846. },
  4847. can: {
  4848. change: function() {
  4849. return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
  4850. },
  4851. uncheck: function() {
  4852. return (typeof settings.uncheckable === 'boolean')
  4853. ? settings.uncheckable
  4854. : !module.is.radio()
  4855. ;
  4856. }
  4857. },
  4858. set: {
  4859. initialLoad: function() {
  4860. initialLoad = true;
  4861. },
  4862. checked: function() {
  4863. module.verbose('Setting class to checked');
  4864. $module
  4865. .removeClass(className.indeterminate)
  4866. .addClass(className.checked)
  4867. ;
  4868. if( module.is.radio() ) {
  4869. module.uncheckOthers();
  4870. }
  4871. if(!module.is.indeterminate() && module.is.checked()) {
  4872. module.debug('Input is already checked, skipping input property change');
  4873. return;
  4874. }
  4875. module.verbose('Setting state to checked', input);
  4876. $input
  4877. .prop('indeterminate', false)
  4878. .prop('checked', true)
  4879. ;
  4880. },
  4881. unchecked: function() {
  4882. module.verbose('Removing checked class');
  4883. $module
  4884. .removeClass(className.indeterminate)
  4885. .removeClass(className.checked)
  4886. ;
  4887. if(!module.is.indeterminate() && module.is.unchecked() ) {
  4888. module.debug('Input is already unchecked');
  4889. return;
  4890. }
  4891. module.debug('Setting state to unchecked');
  4892. $input
  4893. .prop('indeterminate', false)
  4894. .prop('checked', false)
  4895. ;
  4896. },
  4897. indeterminate: function() {
  4898. module.verbose('Setting class to indeterminate');
  4899. $module
  4900. .addClass(className.indeterminate)
  4901. ;
  4902. if( module.is.indeterminate() ) {
  4903. module.debug('Input is already indeterminate, skipping input property change');
  4904. return;
  4905. }
  4906. module.debug('Setting state to indeterminate');
  4907. $input
  4908. .prop('indeterminate', true)
  4909. ;
  4910. },
  4911. determinate: function() {
  4912. module.verbose('Removing indeterminate class');
  4913. $module
  4914. .removeClass(className.indeterminate)
  4915. ;
  4916. if( module.is.determinate() ) {
  4917. module.debug('Input is already determinate, skipping input property change');
  4918. return;
  4919. }
  4920. module.debug('Setting state to determinate');
  4921. $input
  4922. .prop('indeterminate', false)
  4923. ;
  4924. },
  4925. disabled: function() {
  4926. module.verbose('Setting class to disabled');
  4927. $module
  4928. .addClass(className.disabled)
  4929. ;
  4930. if( module.is.disabled() ) {
  4931. module.debug('Input is already disabled, skipping input property change');
  4932. return;
  4933. }
  4934. module.debug('Setting state to disabled');
  4935. $input
  4936. .prop('disabled', 'disabled')
  4937. ;
  4938. },
  4939. enabled: function() {
  4940. module.verbose('Removing disabled class');
  4941. $module.removeClass(className.disabled);
  4942. if( module.is.enabled() ) {
  4943. module.debug('Input is already enabled, skipping input property change');
  4944. return;
  4945. }
  4946. module.debug('Setting state to enabled');
  4947. $input
  4948. .prop('disabled', false)
  4949. ;
  4950. },
  4951. tabbable: function() {
  4952. module.verbose('Adding tabindex to checkbox');
  4953. if( $input.attr('tabindex') === undefined) {
  4954. $input.attr('tabindex', 0);
  4955. }
  4956. }
  4957. },
  4958. remove: {
  4959. initialLoad: function() {
  4960. initialLoad = false;
  4961. }
  4962. },
  4963. trigger: {
  4964. change: function() {
  4965. var
  4966. events = document.createEvent('HTMLEvents'),
  4967. inputElement = $input[0]
  4968. ;
  4969. if(inputElement) {
  4970. module.verbose('Triggering native change event');
  4971. events.initEvent('change', true, false);
  4972. inputElement.dispatchEvent(events);
  4973. }
  4974. }
  4975. },
  4976. create: {
  4977. label: function() {
  4978. if($input.prevAll(selector.label).length > 0) {
  4979. $input.prev(selector.label).detach().insertAfter($input);
  4980. module.debug('Moving existing label', $label);
  4981. }
  4982. else if( !module.has.label() ) {
  4983. $label = $('<label>').insertAfter($input);
  4984. module.debug('Creating label', $label);
  4985. }
  4986. }
  4987. },
  4988. has: {
  4989. label: function() {
  4990. return ($label.length > 0);
  4991. }
  4992. },
  4993. bind: {
  4994. events: function() {
  4995. module.verbose('Attaching checkbox events');
  4996. $module
  4997. .on('click' + eventNamespace, module.event.click)
  4998. .on('change' + eventNamespace, module.event.change)
  4999. .on('keydown' + eventNamespace, selector.input, module.event.keydown)
  5000. .on('keyup' + eventNamespace, selector.input, module.event.keyup)
  5001. ;
  5002. }
  5003. },
  5004. unbind: {
  5005. events: function() {
  5006. module.debug('Removing events');
  5007. $module
  5008. .off(eventNamespace)
  5009. ;
  5010. }
  5011. },
  5012. uncheckOthers: function() {
  5013. var
  5014. $radios = module.get.otherRadios()
  5015. ;
  5016. module.debug('Unchecking other radios', $radios);
  5017. $radios.removeClass(className.checked);
  5018. },
  5019. toggle: function() {
  5020. if( !module.can.change() ) {
  5021. if(!module.is.radio()) {
  5022. module.debug('Checkbox is read-only or disabled, ignoring toggle');
  5023. }
  5024. return;
  5025. }
  5026. if( module.is.indeterminate() || module.is.unchecked() ) {
  5027. module.debug('Currently unchecked');
  5028. module.check();
  5029. }
  5030. else if( module.is.checked() && module.can.uncheck() ) {
  5031. module.debug('Currently checked');
  5032. module.uncheck();
  5033. }
  5034. },
  5035. setting: function(name, value) {
  5036. module.debug('Changing setting', name, value);
  5037. if( $.isPlainObject(name) ) {
  5038. $.extend(true, settings, name);
  5039. }
  5040. else if(value !== undefined) {
  5041. if($.isPlainObject(settings[name])) {
  5042. $.extend(true, settings[name], value);
  5043. }
  5044. else {
  5045. settings[name] = value;
  5046. }
  5047. }
  5048. else {
  5049. return settings[name];
  5050. }
  5051. },
  5052. internal: function(name, value) {
  5053. if( $.isPlainObject(name) ) {
  5054. $.extend(true, module, name);
  5055. }
  5056. else if(value !== undefined) {
  5057. module[name] = value;
  5058. }
  5059. else {
  5060. return module[name];
  5061. }
  5062. },
  5063. debug: function() {
  5064. if(!settings.silent && settings.debug) {
  5065. if(settings.performance) {
  5066. module.performance.log(arguments);
  5067. }
  5068. else {
  5069. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  5070. module.debug.apply(console, arguments);
  5071. }
  5072. }
  5073. },
  5074. verbose: function() {
  5075. if(!settings.silent && settings.verbose && settings.debug) {
  5076. if(settings.performance) {
  5077. module.performance.log(arguments);
  5078. }
  5079. else {
  5080. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  5081. module.verbose.apply(console, arguments);
  5082. }
  5083. }
  5084. },
  5085. error: function() {
  5086. if(!settings.silent) {
  5087. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  5088. module.error.apply(console, arguments);
  5089. }
  5090. },
  5091. performance: {
  5092. log: function(message) {
  5093. var
  5094. currentTime,
  5095. executionTime,
  5096. previousTime
  5097. ;
  5098. if(settings.performance) {
  5099. currentTime = new Date().getTime();
  5100. previousTime = time || currentTime;
  5101. executionTime = currentTime - previousTime;
  5102. time = currentTime;
  5103. performance.push({
  5104. 'Name' : message[0],
  5105. 'Arguments' : [].slice.call(message, 1) || '',
  5106. 'Element' : element,
  5107. 'Execution Time' : executionTime
  5108. });
  5109. }
  5110. clearTimeout(module.performance.timer);
  5111. module.performance.timer = setTimeout(module.performance.display, 500);
  5112. },
  5113. display: function() {
  5114. var
  5115. title = settings.name + ':',
  5116. totalTime = 0
  5117. ;
  5118. time = false;
  5119. clearTimeout(module.performance.timer);
  5120. $.each(performance, function(index, data) {
  5121. totalTime += data['Execution Time'];
  5122. });
  5123. title += ' ' + totalTime + 'ms';
  5124. if(moduleSelector) {
  5125. title += ' \'' + moduleSelector + '\'';
  5126. }
  5127. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  5128. console.groupCollapsed(title);
  5129. if(console.table) {
  5130. console.table(performance);
  5131. }
  5132. else {
  5133. $.each(performance, function(index, data) {
  5134. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  5135. });
  5136. }
  5137. console.groupEnd();
  5138. }
  5139. performance = [];
  5140. }
  5141. },
  5142. invoke: function(query, passedArguments, context) {
  5143. var
  5144. object = instance,
  5145. maxDepth,
  5146. found,
  5147. response
  5148. ;
  5149. passedArguments = passedArguments || queryArguments;
  5150. context = element || context;
  5151. if(typeof query == 'string' && object !== undefined) {
  5152. query = query.split(/[\. ]/);
  5153. maxDepth = query.length - 1;
  5154. $.each(query, function(depth, value) {
  5155. var camelCaseValue = (depth != maxDepth)
  5156. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  5157. : query
  5158. ;
  5159. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  5160. object = object[camelCaseValue];
  5161. }
  5162. else if( object[camelCaseValue] !== undefined ) {
  5163. found = object[camelCaseValue];
  5164. return false;
  5165. }
  5166. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  5167. object = object[value];
  5168. }
  5169. else if( object[value] !== undefined ) {
  5170. found = object[value];
  5171. return false;
  5172. }
  5173. else {
  5174. module.error(error.method, query);
  5175. return false;
  5176. }
  5177. });
  5178. }
  5179. if ( $.isFunction( found ) ) {
  5180. response = found.apply(context, passedArguments);
  5181. }
  5182. else if(found !== undefined) {
  5183. response = found;
  5184. }
  5185. if(Array.isArray(returnedValue)) {
  5186. returnedValue.push(response);
  5187. }
  5188. else if(returnedValue !== undefined) {
  5189. returnedValue = [returnedValue, response];
  5190. }
  5191. else if(response !== undefined) {
  5192. returnedValue = response;
  5193. }
  5194. return found;
  5195. }
  5196. };
  5197. if(methodInvoked) {
  5198. if(instance === undefined) {
  5199. module.initialize();
  5200. }
  5201. module.invoke(query);
  5202. }
  5203. else {
  5204. if(instance !== undefined) {
  5205. instance.invoke('destroy');
  5206. }
  5207. module.initialize();
  5208. }
  5209. })
  5210. ;
  5211. return (returnedValue !== undefined)
  5212. ? returnedValue
  5213. : this
  5214. ;
  5215. };
  5216. $.fn.checkbox.settings = {
  5217. name : 'Checkbox',
  5218. namespace : 'checkbox',
  5219. silent : false,
  5220. debug : false,
  5221. verbose : true,
  5222. performance : true,
  5223. // delegated event context
  5224. uncheckable : 'auto',
  5225. fireOnInit : false,
  5226. enableEnterKey : true,
  5227. onChange : function(){},
  5228. beforeChecked : function(){},
  5229. beforeUnchecked : function(){},
  5230. beforeDeterminate : function(){},
  5231. beforeIndeterminate : function(){},
  5232. onChecked : function(){},
  5233. onUnchecked : function(){},
  5234. onDeterminate : function() {},
  5235. onIndeterminate : function() {},
  5236. onEnable : function(){},
  5237. onDisable : function(){},
  5238. // preserve misspelled callbacks (will be removed in 3.0)
  5239. onEnabled : function(){},
  5240. onDisabled : function(){},
  5241. className : {
  5242. checked : 'checked',
  5243. indeterminate : 'indeterminate',
  5244. disabled : 'disabled',
  5245. hidden : 'hidden',
  5246. radio : 'radio',
  5247. readOnly : 'read-only'
  5248. },
  5249. error : {
  5250. method : 'The method you called is not defined'
  5251. },
  5252. selector : {
  5253. checkbox : '.ui.checkbox',
  5254. label : 'label, .box',
  5255. input : 'input[type="checkbox"], input[type="radio"]',
  5256. link : 'a[href]'
  5257. }
  5258. };
  5259. })( jQuery, window, document );
  5260. /*!
  5261. * # Fomantic-UI - Dimmer
  5262. * http://github.com/fomantic/Fomantic-UI/
  5263. *
  5264. *
  5265. * Released under the MIT license
  5266. * http://opensource.org/licenses/MIT
  5267. *
  5268. */
  5269. ;(function ($, window, document, undefined) {
  5270. 'use strict';
  5271. $.isFunction = $.isFunction || function(obj) {
  5272. return typeof obj === "function" && typeof obj.nodeType !== "number";
  5273. };
  5274. window = (typeof window != 'undefined' && window.Math == Math)
  5275. ? window
  5276. : (typeof self != 'undefined' && self.Math == Math)
  5277. ? self
  5278. : Function('return this')()
  5279. ;
  5280. $.fn.dimmer = function(parameters) {
  5281. var
  5282. $allModules = $(this),
  5283. time = new Date().getTime(),
  5284. performance = [],
  5285. query = arguments[0],
  5286. methodInvoked = (typeof query == 'string'),
  5287. queryArguments = [].slice.call(arguments, 1),
  5288. returnedValue
  5289. ;
  5290. $allModules
  5291. .each(function() {
  5292. var
  5293. settings = ( $.isPlainObject(parameters) )
  5294. ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
  5295. : $.extend({}, $.fn.dimmer.settings),
  5296. selector = settings.selector,
  5297. namespace = settings.namespace,
  5298. className = settings.className,
  5299. error = settings.error,
  5300. eventNamespace = '.' + namespace,
  5301. moduleNamespace = 'module-' + namespace,
  5302. moduleSelector = $allModules.selector || '',
  5303. clickEvent = ('ontouchstart' in document.documentElement)
  5304. ? 'touchstart'
  5305. : 'click',
  5306. $module = $(this),
  5307. $dimmer,
  5308. $dimmable,
  5309. element = this,
  5310. instance = $module.data(moduleNamespace),
  5311. module
  5312. ;
  5313. module = {
  5314. preinitialize: function() {
  5315. if( module.is.dimmer() ) {
  5316. $dimmable = $module.parent();
  5317. $dimmer = $module;
  5318. }
  5319. else {
  5320. $dimmable = $module;
  5321. if( module.has.dimmer() ) {
  5322. if(settings.dimmerName) {
  5323. $dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
  5324. }
  5325. else {
  5326. $dimmer = $dimmable.find(selector.dimmer);
  5327. }
  5328. }
  5329. else {
  5330. $dimmer = module.create();
  5331. }
  5332. }
  5333. },
  5334. initialize: function() {
  5335. module.debug('Initializing dimmer', settings);
  5336. module.bind.events();
  5337. module.set.dimmable();
  5338. module.instantiate();
  5339. },
  5340. instantiate: function() {
  5341. module.verbose('Storing instance of module', module);
  5342. instance = module;
  5343. $module
  5344. .data(moduleNamespace, instance)
  5345. ;
  5346. },
  5347. destroy: function() {
  5348. module.verbose('Destroying previous module', $dimmer);
  5349. module.unbind.events();
  5350. module.remove.variation();
  5351. $dimmable
  5352. .off(eventNamespace)
  5353. ;
  5354. },
  5355. bind: {
  5356. events: function() {
  5357. if(settings.on == 'hover') {
  5358. $dimmable
  5359. .on('mouseenter' + eventNamespace, module.show)
  5360. .on('mouseleave' + eventNamespace, module.hide)
  5361. ;
  5362. }
  5363. else if(settings.on == 'click') {
  5364. $dimmable
  5365. .on(clickEvent + eventNamespace, module.toggle)
  5366. ;
  5367. }
  5368. if( module.is.page() ) {
  5369. module.debug('Setting as a page dimmer', $dimmable);
  5370. module.set.pageDimmer();
  5371. }
  5372. if( module.is.closable() ) {
  5373. module.verbose('Adding dimmer close event', $dimmer);
  5374. $dimmable
  5375. .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
  5376. ;
  5377. }
  5378. }
  5379. },
  5380. unbind: {
  5381. events: function() {
  5382. $module
  5383. .removeData(moduleNamespace)
  5384. ;
  5385. $dimmable
  5386. .off(eventNamespace)
  5387. ;
  5388. }
  5389. },
  5390. event: {
  5391. click: function(event) {
  5392. module.verbose('Determining if event occured on dimmer', event);
  5393. if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
  5394. module.hide();
  5395. event.stopImmediatePropagation();
  5396. }
  5397. }
  5398. },
  5399. addContent: function(element) {
  5400. var
  5401. $content = $(element)
  5402. ;
  5403. module.debug('Add content to dimmer', $content);
  5404. if($content.parent()[0] !== $dimmer[0]) {
  5405. $content.detach().appendTo($dimmer);
  5406. }
  5407. },
  5408. create: function() {
  5409. var
  5410. $element = $( settings.template.dimmer(settings) )
  5411. ;
  5412. if(settings.dimmerName) {
  5413. module.debug('Creating named dimmer', settings.dimmerName);
  5414. $element.addClass(settings.dimmerName);
  5415. }
  5416. $element
  5417. .appendTo($dimmable)
  5418. ;
  5419. return $element;
  5420. },
  5421. show: function(callback) {
  5422. callback = $.isFunction(callback)
  5423. ? callback
  5424. : function(){}
  5425. ;
  5426. module.debug('Showing dimmer', $dimmer, settings);
  5427. module.set.variation();
  5428. if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
  5429. module.animate.show(callback);
  5430. settings.onShow.call(element);
  5431. settings.onChange.call(element);
  5432. }
  5433. else {
  5434. module.debug('Dimmer is already shown or disabled');
  5435. }
  5436. },
  5437. hide: function(callback) {
  5438. callback = $.isFunction(callback)
  5439. ? callback
  5440. : function(){}
  5441. ;
  5442. if( module.is.dimmed() || module.is.animating() ) {
  5443. module.debug('Hiding dimmer', $dimmer);
  5444. module.animate.hide(callback);
  5445. settings.onHide.call(element);
  5446. settings.onChange.call(element);
  5447. }
  5448. else {
  5449. module.debug('Dimmer is not visible');
  5450. }
  5451. },
  5452. toggle: function() {
  5453. module.verbose('Toggling dimmer visibility', $dimmer);
  5454. if( !module.is.dimmed() ) {
  5455. module.show();
  5456. }
  5457. else {
  5458. if ( module.is.closable() ) {
  5459. module.hide();
  5460. }
  5461. }
  5462. },
  5463. animate: {
  5464. show: function(callback) {
  5465. callback = $.isFunction(callback)
  5466. ? callback
  5467. : function(){}
  5468. ;
  5469. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  5470. if(settings.useFlex) {
  5471. module.debug('Using flex dimmer');
  5472. module.remove.legacy();
  5473. }
  5474. else {
  5475. module.debug('Using legacy non-flex dimmer');
  5476. module.set.legacy();
  5477. }
  5478. if(settings.opacity !== 'auto') {
  5479. module.set.opacity();
  5480. }
  5481. $dimmer
  5482. .transition({
  5483. displayType : settings.useFlex
  5484. ? 'flex'
  5485. : 'block',
  5486. animation : settings.transition + ' in',
  5487. queue : false,
  5488. duration : module.get.duration(),
  5489. useFailSafe : true,
  5490. onStart : function() {
  5491. module.set.dimmed();
  5492. },
  5493. onComplete : function() {
  5494. module.set.active();
  5495. callback();
  5496. }
  5497. })
  5498. ;
  5499. }
  5500. else {
  5501. module.verbose('Showing dimmer animation with javascript');
  5502. module.set.dimmed();
  5503. if(settings.opacity == 'auto') {
  5504. settings.opacity = 0.8;
  5505. }
  5506. $dimmer
  5507. .stop()
  5508. .css({
  5509. opacity : 0,
  5510. width : '100%',
  5511. height : '100%'
  5512. })
  5513. .fadeTo(module.get.duration(), settings.opacity, function() {
  5514. $dimmer.removeAttr('style');
  5515. module.set.active();
  5516. callback();
  5517. })
  5518. ;
  5519. }
  5520. },
  5521. hide: function(callback) {
  5522. callback = $.isFunction(callback)
  5523. ? callback
  5524. : function(){}
  5525. ;
  5526. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  5527. module.verbose('Hiding dimmer with css');
  5528. $dimmer
  5529. .transition({
  5530. displayType : settings.useFlex
  5531. ? 'flex'
  5532. : 'block',
  5533. animation : settings.transition + ' out',
  5534. queue : false,
  5535. duration : module.get.duration(),
  5536. useFailSafe : true,
  5537. onComplete : function() {
  5538. module.remove.dimmed();
  5539. module.remove.variation();
  5540. module.remove.active();
  5541. callback();
  5542. }
  5543. })
  5544. ;
  5545. }
  5546. else {
  5547. module.verbose('Hiding dimmer with javascript');
  5548. $dimmer
  5549. .stop()
  5550. .fadeOut(module.get.duration(), function() {
  5551. module.remove.dimmed();
  5552. module.remove.active();
  5553. $dimmer.removeAttr('style');
  5554. callback();
  5555. })
  5556. ;
  5557. }
  5558. }
  5559. },
  5560. get: {
  5561. dimmer: function() {
  5562. return $dimmer;
  5563. },
  5564. duration: function() {
  5565. if(typeof settings.duration == 'object') {
  5566. if( module.is.active() ) {
  5567. return settings.duration.hide;
  5568. }
  5569. else {
  5570. return settings.duration.show;
  5571. }
  5572. }
  5573. return settings.duration;
  5574. }
  5575. },
  5576. has: {
  5577. dimmer: function() {
  5578. if(settings.dimmerName) {
  5579. return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
  5580. }
  5581. else {
  5582. return ( $module.find(selector.dimmer).length > 0 );
  5583. }
  5584. }
  5585. },
  5586. is: {
  5587. active: function() {
  5588. return $dimmer.hasClass(className.active);
  5589. },
  5590. animating: function() {
  5591. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
  5592. },
  5593. closable: function() {
  5594. if(settings.closable == 'auto') {
  5595. if(settings.on == 'hover') {
  5596. return false;
  5597. }
  5598. return true;
  5599. }
  5600. return settings.closable;
  5601. },
  5602. dimmer: function() {
  5603. return $module.hasClass(className.dimmer);
  5604. },
  5605. dimmable: function() {
  5606. return $module.hasClass(className.dimmable);
  5607. },
  5608. dimmed: function() {
  5609. return $dimmable.hasClass(className.dimmed);
  5610. },
  5611. disabled: function() {
  5612. return $dimmable.hasClass(className.disabled);
  5613. },
  5614. enabled: function() {
  5615. return !module.is.disabled();
  5616. },
  5617. page: function () {
  5618. return $dimmable.is('body');
  5619. },
  5620. pageDimmer: function() {
  5621. return $dimmer.hasClass(className.pageDimmer);
  5622. }
  5623. },
  5624. can: {
  5625. show: function() {
  5626. return !$dimmer.hasClass(className.disabled);
  5627. }
  5628. },
  5629. set: {
  5630. opacity: function(opacity) {
  5631. var
  5632. color = $dimmer.css('background-color'),
  5633. colorArray = color.split(','),
  5634. isRGB = (colorArray && colorArray.length == 3),
  5635. isRGBA = (colorArray && colorArray.length == 4)
  5636. ;
  5637. opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
  5638. if(isRGB || isRGBA) {
  5639. colorArray[3] = opacity + ')';
  5640. color = colorArray.join(',');
  5641. }
  5642. else {
  5643. color = 'rgba(0, 0, 0, ' + opacity + ')';
  5644. }
  5645. module.debug('Setting opacity to', opacity);
  5646. $dimmer.css('background-color', color);
  5647. },
  5648. legacy: function() {
  5649. $dimmer.addClass(className.legacy);
  5650. },
  5651. active: function() {
  5652. $dimmer.addClass(className.active);
  5653. },
  5654. dimmable: function() {
  5655. $dimmable.addClass(className.dimmable);
  5656. },
  5657. dimmed: function() {
  5658. $dimmable.addClass(className.dimmed);
  5659. },
  5660. pageDimmer: function() {
  5661. $dimmer.addClass(className.pageDimmer);
  5662. },
  5663. disabled: function() {
  5664. $dimmer.addClass(className.disabled);
  5665. },
  5666. variation: function(variation) {
  5667. variation = variation || settings.variation;
  5668. if(variation) {
  5669. $dimmer.addClass(variation);
  5670. }
  5671. }
  5672. },
  5673. remove: {
  5674. active: function() {
  5675. $dimmer
  5676. .removeClass(className.active)
  5677. ;
  5678. },
  5679. legacy: function() {
  5680. $dimmer.removeClass(className.legacy);
  5681. },
  5682. dimmed: function() {
  5683. $dimmable.removeClass(className.dimmed);
  5684. },
  5685. disabled: function() {
  5686. $dimmer.removeClass(className.disabled);
  5687. },
  5688. variation: function(variation) {
  5689. variation = variation || settings.variation;
  5690. if(variation) {
  5691. $dimmer.removeClass(variation);
  5692. }
  5693. }
  5694. },
  5695. setting: function(name, value) {
  5696. module.debug('Changing setting', name, value);
  5697. if( $.isPlainObject(name) ) {
  5698. $.extend(true, settings, name);
  5699. }
  5700. else if(value !== undefined) {
  5701. if($.isPlainObject(settings[name])) {
  5702. $.extend(true, settings[name], value);
  5703. }
  5704. else {
  5705. settings[name] = value;
  5706. }
  5707. }
  5708. else {
  5709. return settings[name];
  5710. }
  5711. },
  5712. internal: function(name, value) {
  5713. if( $.isPlainObject(name) ) {
  5714. $.extend(true, module, name);
  5715. }
  5716. else if(value !== undefined) {
  5717. module[name] = value;
  5718. }
  5719. else {
  5720. return module[name];
  5721. }
  5722. },
  5723. debug: function() {
  5724. if(!settings.silent && settings.debug) {
  5725. if(settings.performance) {
  5726. module.performance.log(arguments);
  5727. }
  5728. else {
  5729. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  5730. module.debug.apply(console, arguments);
  5731. }
  5732. }
  5733. },
  5734. verbose: function() {
  5735. if(!settings.silent && settings.verbose && settings.debug) {
  5736. if(settings.performance) {
  5737. module.performance.log(arguments);
  5738. }
  5739. else {
  5740. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  5741. module.verbose.apply(console, arguments);
  5742. }
  5743. }
  5744. },
  5745. error: function() {
  5746. if(!settings.silent) {
  5747. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  5748. module.error.apply(console, arguments);
  5749. }
  5750. },
  5751. performance: {
  5752. log: function(message) {
  5753. var
  5754. currentTime,
  5755. executionTime,
  5756. previousTime
  5757. ;
  5758. if(settings.performance) {
  5759. currentTime = new Date().getTime();
  5760. previousTime = time || currentTime;
  5761. executionTime = currentTime - previousTime;
  5762. time = currentTime;
  5763. performance.push({
  5764. 'Name' : message[0],
  5765. 'Arguments' : [].slice.call(message, 1) || '',
  5766. 'Element' : element,
  5767. 'Execution Time' : executionTime
  5768. });
  5769. }
  5770. clearTimeout(module.performance.timer);
  5771. module.performance.timer = setTimeout(module.performance.display, 500);
  5772. },
  5773. display: function() {
  5774. var
  5775. title = settings.name + ':',
  5776. totalTime = 0
  5777. ;
  5778. time = false;
  5779. clearTimeout(module.performance.timer);
  5780. $.each(performance, function(index, data) {
  5781. totalTime += data['Execution Time'];
  5782. });
  5783. title += ' ' + totalTime + 'ms';
  5784. if(moduleSelector) {
  5785. title += ' \'' + moduleSelector + '\'';
  5786. }
  5787. if($allModules.length > 1) {
  5788. title += ' ' + '(' + $allModules.length + ')';
  5789. }
  5790. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  5791. console.groupCollapsed(title);
  5792. if(console.table) {
  5793. console.table(performance);
  5794. }
  5795. else {
  5796. $.each(performance, function(index, data) {
  5797. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  5798. });
  5799. }
  5800. console.groupEnd();
  5801. }
  5802. performance = [];
  5803. }
  5804. },
  5805. invoke: function(query, passedArguments, context) {
  5806. var
  5807. object = instance,
  5808. maxDepth,
  5809. found,
  5810. response
  5811. ;
  5812. passedArguments = passedArguments || queryArguments;
  5813. context = element || context;
  5814. if(typeof query == 'string' && object !== undefined) {
  5815. query = query.split(/[\. ]/);
  5816. maxDepth = query.length - 1;
  5817. $.each(query, function(depth, value) {
  5818. var camelCaseValue = (depth != maxDepth)
  5819. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  5820. : query
  5821. ;
  5822. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  5823. object = object[camelCaseValue];
  5824. }
  5825. else if( object[camelCaseValue] !== undefined ) {
  5826. found = object[camelCaseValue];
  5827. return false;
  5828. }
  5829. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  5830. object = object[value];
  5831. }
  5832. else if( object[value] !== undefined ) {
  5833. found = object[value];
  5834. return false;
  5835. }
  5836. else {
  5837. module.error(error.method, query);
  5838. return false;
  5839. }
  5840. });
  5841. }
  5842. if ( $.isFunction( found ) ) {
  5843. response = found.apply(context, passedArguments);
  5844. }
  5845. else if(found !== undefined) {
  5846. response = found;
  5847. }
  5848. if(Array.isArray(returnedValue)) {
  5849. returnedValue.push(response);
  5850. }
  5851. else if(returnedValue !== undefined) {
  5852. returnedValue = [returnedValue, response];
  5853. }
  5854. else if(response !== undefined) {
  5855. returnedValue = response;
  5856. }
  5857. return found;
  5858. }
  5859. };
  5860. module.preinitialize();
  5861. if(methodInvoked) {
  5862. if(instance === undefined) {
  5863. module.initialize();
  5864. }
  5865. module.invoke(query);
  5866. }
  5867. else {
  5868. if(instance !== undefined) {
  5869. instance.invoke('destroy');
  5870. }
  5871. module.initialize();
  5872. }
  5873. })
  5874. ;
  5875. return (returnedValue !== undefined)
  5876. ? returnedValue
  5877. : this
  5878. ;
  5879. };
  5880. $.fn.dimmer.settings = {
  5881. name : 'Dimmer',
  5882. namespace : 'dimmer',
  5883. silent : false,
  5884. debug : false,
  5885. verbose : false,
  5886. performance : true,
  5887. // whether should use flex layout
  5888. useFlex : true,
  5889. // name to distinguish between multiple dimmers in context
  5890. dimmerName : false,
  5891. // whether to add a variation type
  5892. variation : false,
  5893. // whether to bind close events
  5894. closable : 'auto',
  5895. // whether to use css animations
  5896. useCSS : true,
  5897. // css animation to use
  5898. transition : 'fade',
  5899. // event to bind to
  5900. on : false,
  5901. // overriding opacity value
  5902. opacity : 'auto',
  5903. // transition durations
  5904. duration : {
  5905. show : 500,
  5906. hide : 500
  5907. },
  5908. // whether the dynamically created dimmer should have a loader
  5909. displayLoader: false,
  5910. loaderText : false,
  5911. loaderVariation : '',
  5912. onChange : function(){},
  5913. onShow : function(){},
  5914. onHide : function(){},
  5915. error : {
  5916. method : 'The method you called is not defined.'
  5917. },
  5918. className : {
  5919. active : 'active',
  5920. animating : 'animating',
  5921. dimmable : 'dimmable',
  5922. dimmed : 'dimmed',
  5923. dimmer : 'dimmer',
  5924. disabled : 'disabled',
  5925. hide : 'hide',
  5926. legacy : 'legacy',
  5927. pageDimmer : 'page',
  5928. show : 'show',
  5929. loader : 'ui loader'
  5930. },
  5931. selector: {
  5932. dimmer : '> .ui.dimmer',
  5933. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  5934. },
  5935. template: {
  5936. dimmer: function(settings) {
  5937. var d = $('<div/>').addClass('ui dimmer'),l;
  5938. if(settings.displayLoader) {
  5939. l = $('<div/>')
  5940. .addClass(settings.className.loader)
  5941. .addClass(settings.loaderVariation);
  5942. if(!!settings.loaderText){
  5943. l.text(settings.loaderText);
  5944. l.addClass('text');
  5945. }
  5946. d.append(l);
  5947. }
  5948. return d;
  5949. }
  5950. }
  5951. };
  5952. })( jQuery, window, document );
  5953. /*!
  5954. * # Fomantic-UI - Dropdown
  5955. * http://github.com/fomantic/Fomantic-UI/
  5956. *
  5957. *
  5958. * Released under the MIT license
  5959. * http://opensource.org/licenses/MIT
  5960. *
  5961. */
  5962. ;(function ($, window, document, undefined) {
  5963. 'use strict';
  5964. $.isFunction = $.isFunction || function(obj) {
  5965. return typeof obj === "function" && typeof obj.nodeType !== "number";
  5966. };
  5967. window = (typeof window != 'undefined' && window.Math == Math)
  5968. ? window
  5969. : (typeof self != 'undefined' && self.Math == Math)
  5970. ? self
  5971. : Function('return this')()
  5972. ;
  5973. $.fn.dropdown = function(parameters) {
  5974. var
  5975. $allModules = $(this),
  5976. $document = $(document),
  5977. moduleSelector = $allModules.selector || '',
  5978. hasTouch = ('ontouchstart' in document.documentElement),
  5979. clickEvent = hasTouch
  5980. ? 'touchstart'
  5981. : 'click',
  5982. time = new Date().getTime(),
  5983. performance = [],
  5984. query = arguments[0],
  5985. methodInvoked = (typeof query == 'string'),
  5986. queryArguments = [].slice.call(arguments, 1),
  5987. returnedValue
  5988. ;
  5989. $allModules
  5990. .each(function(elementIndex) {
  5991. var
  5992. settings = ( $.isPlainObject(parameters) )
  5993. ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
  5994. : $.extend({}, $.fn.dropdown.settings),
  5995. className = settings.className,
  5996. message = settings.message,
  5997. fields = settings.fields,
  5998. keys = settings.keys,
  5999. metadata = settings.metadata,
  6000. namespace = settings.namespace,
  6001. regExp = settings.regExp,
  6002. selector = settings.selector,
  6003. error = settings.error,
  6004. templates = settings.templates,
  6005. eventNamespace = '.' + namespace,
  6006. moduleNamespace = 'module-' + namespace,
  6007. $module = $(this),
  6008. $context = $(settings.context),
  6009. $text = $module.find(selector.text),
  6010. $search = $module.find(selector.search),
  6011. $sizer = $module.find(selector.sizer),
  6012. $input = $module.find(selector.input),
  6013. $icon = $module.find(selector.icon),
  6014. $clear = $module.find(selector.clearIcon),
  6015. $combo = ($module.prev().find(selector.text).length > 0)
  6016. ? $module.prev().find(selector.text)
  6017. : $module.prev(),
  6018. $menu = $module.children(selector.menu),
  6019. $item = $menu.find(selector.item),
  6020. $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $(),
  6021. activated = false,
  6022. itemActivated = false,
  6023. internalChange = false,
  6024. iconClicked = false,
  6025. element = this,
  6026. instance = $module.data(moduleNamespace),
  6027. selectActionActive,
  6028. initialLoad,
  6029. pageLostFocus,
  6030. willRefocus,
  6031. elementNamespace,
  6032. id,
  6033. selectObserver,
  6034. menuObserver,
  6035. module
  6036. ;
  6037. module = {
  6038. initialize: function() {
  6039. module.debug('Initializing dropdown', settings);
  6040. if( module.is.alreadySetup() ) {
  6041. module.setup.reference();
  6042. }
  6043. else {
  6044. if (settings.ignoreDiacritics && !String.prototype.normalize) {
  6045. settings.ignoreDiacritics = false;
  6046. module.error(error.noNormalize, element);
  6047. }
  6048. module.setup.layout();
  6049. if(settings.values) {
  6050. module.change.values(settings.values);
  6051. }
  6052. module.refreshData();
  6053. module.save.defaults();
  6054. module.restore.selected();
  6055. module.create.id();
  6056. module.bind.events();
  6057. module.observeChanges();
  6058. module.instantiate();
  6059. }
  6060. },
  6061. instantiate: function() {
  6062. module.verbose('Storing instance of dropdown', module);
  6063. instance = module;
  6064. $module
  6065. .data(moduleNamespace, module)
  6066. ;
  6067. },
  6068. destroy: function() {
  6069. module.verbose('Destroying previous dropdown', $module);
  6070. module.remove.tabbable();
  6071. module.remove.active();
  6072. $menu.transition('stop all');
  6073. $menu.removeClass(className.visible).addClass(className.hidden);
  6074. $module
  6075. .off(eventNamespace)
  6076. .removeData(moduleNamespace)
  6077. ;
  6078. $menu
  6079. .off(eventNamespace)
  6080. ;
  6081. $document
  6082. .off(elementNamespace)
  6083. ;
  6084. module.disconnect.menuObserver();
  6085. module.disconnect.selectObserver();
  6086. },
  6087. observeChanges: function() {
  6088. if('MutationObserver' in window) {
  6089. selectObserver = new MutationObserver(module.event.select.mutation);
  6090. menuObserver = new MutationObserver(module.event.menu.mutation);
  6091. module.debug('Setting up mutation observer', selectObserver, menuObserver);
  6092. module.observe.select();
  6093. module.observe.menu();
  6094. }
  6095. },
  6096. disconnect: {
  6097. menuObserver: function() {
  6098. if(menuObserver) {
  6099. menuObserver.disconnect();
  6100. }
  6101. },
  6102. selectObserver: function() {
  6103. if(selectObserver) {
  6104. selectObserver.disconnect();
  6105. }
  6106. }
  6107. },
  6108. observe: {
  6109. select: function() {
  6110. if(module.has.input() && selectObserver) {
  6111. selectObserver.observe($module[0], {
  6112. childList : true,
  6113. subtree : true
  6114. });
  6115. }
  6116. },
  6117. menu: function() {
  6118. if(module.has.menu() && menuObserver) {
  6119. menuObserver.observe($menu[0], {
  6120. childList : true,
  6121. subtree : true
  6122. });
  6123. }
  6124. }
  6125. },
  6126. create: {
  6127. id: function() {
  6128. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  6129. elementNamespace = '.' + id;
  6130. module.verbose('Creating unique id for element', id);
  6131. },
  6132. userChoice: function(values) {
  6133. var
  6134. $userChoices,
  6135. $userChoice,
  6136. isUserValue,
  6137. html
  6138. ;
  6139. values = values || module.get.userValues();
  6140. if(!values) {
  6141. return false;
  6142. }
  6143. values = Array.isArray(values)
  6144. ? values
  6145. : [values]
  6146. ;
  6147. $.each(values, function(index, value) {
  6148. if(module.get.item(value) === false) {
  6149. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  6150. $userChoice = $('<div />')
  6151. .html(html)
  6152. .attr('data-' + metadata.value, value)
  6153. .attr('data-' + metadata.text, value)
  6154. .addClass(className.addition)
  6155. .addClass(className.item)
  6156. ;
  6157. if(settings.hideAdditions) {
  6158. $userChoice.addClass(className.hidden);
  6159. }
  6160. $userChoices = ($userChoices === undefined)
  6161. ? $userChoice
  6162. : $userChoices.add($userChoice)
  6163. ;
  6164. module.verbose('Creating user choices for value', value, $userChoice);
  6165. }
  6166. });
  6167. return $userChoices;
  6168. },
  6169. userLabels: function(value) {
  6170. var
  6171. userValues = module.get.userValues()
  6172. ;
  6173. if(userValues) {
  6174. module.debug('Adding user labels', userValues);
  6175. $.each(userValues, function(index, value) {
  6176. module.verbose('Adding custom user value');
  6177. module.add.label(value, value);
  6178. });
  6179. }
  6180. },
  6181. menu: function() {
  6182. $menu = $('<div />')
  6183. .addClass(className.menu)
  6184. .appendTo($module)
  6185. ;
  6186. },
  6187. sizer: function() {
  6188. $sizer = $('<span />')
  6189. .addClass(className.sizer)
  6190. .insertAfter($search)
  6191. ;
  6192. }
  6193. },
  6194. search: function(query) {
  6195. query = (query !== undefined)
  6196. ? query
  6197. : module.get.query()
  6198. ;
  6199. module.verbose('Searching for query', query);
  6200. if(module.has.minCharacters(query)) {
  6201. module.filter(query);
  6202. }
  6203. else {
  6204. module.hide(null,true);
  6205. }
  6206. },
  6207. select: {
  6208. firstUnfiltered: function() {
  6209. module.verbose('Selecting first non-filtered element');
  6210. module.remove.selectedItem();
  6211. $item
  6212. .not(selector.unselectable)
  6213. .not(selector.addition + selector.hidden)
  6214. .eq(0)
  6215. .addClass(className.selected)
  6216. ;
  6217. },
  6218. nextAvailable: function($selected) {
  6219. $selected = $selected.eq(0);
  6220. var
  6221. $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
  6222. $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
  6223. hasNext = ($nextAvailable.length > 0)
  6224. ;
  6225. if(hasNext) {
  6226. module.verbose('Moving selection to', $nextAvailable);
  6227. $nextAvailable.addClass(className.selected);
  6228. }
  6229. else {
  6230. module.verbose('Moving selection to', $prevAvailable);
  6231. $prevAvailable.addClass(className.selected);
  6232. }
  6233. }
  6234. },
  6235. setup: {
  6236. api: function() {
  6237. var
  6238. apiSettings = {
  6239. debug : settings.debug,
  6240. urlData : {
  6241. value : module.get.value(),
  6242. query : module.get.query()
  6243. },
  6244. on : false
  6245. }
  6246. ;
  6247. module.verbose('First request, initializing API');
  6248. $module
  6249. .api(apiSettings)
  6250. ;
  6251. },
  6252. layout: function() {
  6253. if( $module.is('select') ) {
  6254. module.setup.select();
  6255. module.setup.returnedObject();
  6256. }
  6257. if( !module.has.menu() ) {
  6258. module.create.menu();
  6259. }
  6260. if ( module.is.selection() && module.is.clearable() && !module.has.clearItem() ) {
  6261. module.verbose('Adding clear icon');
  6262. $clear = $('<i />')
  6263. .addClass('remove icon')
  6264. .insertBefore($text)
  6265. ;
  6266. }
  6267. if( module.is.search() && !module.has.search() ) {
  6268. module.verbose('Adding search input');
  6269. $search = $('<input />')
  6270. .addClass(className.search)
  6271. .prop('autocomplete', 'off')
  6272. .insertBefore($text)
  6273. ;
  6274. }
  6275. if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
  6276. module.create.sizer();
  6277. }
  6278. if(settings.allowTab) {
  6279. module.set.tabbable();
  6280. }
  6281. },
  6282. select: function() {
  6283. var
  6284. selectValues = module.get.selectValues()
  6285. ;
  6286. module.debug('Dropdown initialized on a select', selectValues);
  6287. if( $module.is('select') ) {
  6288. $input = $module;
  6289. }
  6290. // see if select is placed correctly already
  6291. if($input.parent(selector.dropdown).length > 0) {
  6292. module.debug('UI dropdown already exists. Creating dropdown menu only');
  6293. $module = $input.closest(selector.dropdown);
  6294. if( !module.has.menu() ) {
  6295. module.create.menu();
  6296. }
  6297. $menu = $module.children(selector.menu);
  6298. module.setup.menu(selectValues);
  6299. }
  6300. else {
  6301. module.debug('Creating entire dropdown from select');
  6302. $module = $('<div />')
  6303. .attr('class', $input.attr('class') )
  6304. .addClass(className.selection)
  6305. .addClass(className.dropdown)
  6306. .html( templates.dropdown(selectValues, fields, settings.preserveHTML, settings.className) )
  6307. .insertBefore($input)
  6308. ;
  6309. if($input.hasClass(className.multiple) && $input.prop('multiple') === false) {
  6310. module.error(error.missingMultiple);
  6311. $input.prop('multiple', true);
  6312. }
  6313. if($input.is('[multiple]')) {
  6314. module.set.multiple();
  6315. }
  6316. if ($input.prop('disabled')) {
  6317. module.debug('Disabling dropdown');
  6318. $module.addClass(className.disabled);
  6319. }
  6320. $input
  6321. .removeAttr('required')
  6322. .removeAttr('class')
  6323. .detach()
  6324. .prependTo($module)
  6325. ;
  6326. }
  6327. module.refresh();
  6328. },
  6329. menu: function(values) {
  6330. $menu.html( templates.menu(values, fields,settings.preserveHTML,settings.className));
  6331. $item = $menu.find(selector.item);
  6332. $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
  6333. },
  6334. reference: function() {
  6335. module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
  6336. // replace module reference
  6337. $module = $module.parent(selector.dropdown);
  6338. instance = $module.data(moduleNamespace);
  6339. element = $module.get(0);
  6340. module.refresh();
  6341. module.setup.returnedObject();
  6342. },
  6343. returnedObject: function() {
  6344. var
  6345. $firstModules = $allModules.slice(0, elementIndex),
  6346. $lastModules = $allModules.slice(elementIndex + 1)
  6347. ;
  6348. // adjust all modules to use correct reference
  6349. $allModules = $firstModules.add($module).add($lastModules);
  6350. }
  6351. },
  6352. refresh: function() {
  6353. module.refreshSelectors();
  6354. module.refreshData();
  6355. },
  6356. refreshItems: function() {
  6357. $item = $menu.find(selector.item);
  6358. $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
  6359. },
  6360. refreshSelectors: function() {
  6361. module.verbose('Refreshing selector cache');
  6362. $text = $module.find(selector.text);
  6363. $search = $module.find(selector.search);
  6364. $input = $module.find(selector.input);
  6365. $icon = $module.find(selector.icon);
  6366. $combo = ($module.prev().find(selector.text).length > 0)
  6367. ? $module.prev().find(selector.text)
  6368. : $module.prev()
  6369. ;
  6370. $menu = $module.children(selector.menu);
  6371. $item = $menu.find(selector.item);
  6372. $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
  6373. },
  6374. refreshData: function() {
  6375. module.verbose('Refreshing cached metadata');
  6376. $item
  6377. .removeData(metadata.text)
  6378. .removeData(metadata.value)
  6379. ;
  6380. },
  6381. clearData: function() {
  6382. module.verbose('Clearing metadata');
  6383. $item
  6384. .removeData(metadata.text)
  6385. .removeData(metadata.value)
  6386. ;
  6387. $module
  6388. .removeData(metadata.defaultText)
  6389. .removeData(metadata.defaultValue)
  6390. .removeData(metadata.placeholderText)
  6391. ;
  6392. },
  6393. toggle: function() {
  6394. module.verbose('Toggling menu visibility');
  6395. if( !module.is.active() ) {
  6396. module.show();
  6397. }
  6398. else {
  6399. module.hide();
  6400. }
  6401. },
  6402. show: function(callback, preventFocus) {
  6403. callback = $.isFunction(callback)
  6404. ? callback
  6405. : function(){}
  6406. ;
  6407. if(!module.can.show() && module.is.remote()) {
  6408. module.debug('No API results retrieved, searching before show');
  6409. module.queryRemote(module.get.query(), module.show);
  6410. }
  6411. if( module.can.show() && !module.is.active() ) {
  6412. module.debug('Showing dropdown');
  6413. if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
  6414. module.remove.message();
  6415. }
  6416. if(module.is.allFiltered()) {
  6417. return true;
  6418. }
  6419. if(settings.onShow.call(element) !== false) {
  6420. module.animate.show(function() {
  6421. if( module.can.click() ) {
  6422. module.bind.intent();
  6423. }
  6424. if(module.has.search() && !preventFocus) {
  6425. module.focusSearch();
  6426. }
  6427. module.set.visible();
  6428. callback.call(element);
  6429. });
  6430. }
  6431. }
  6432. },
  6433. hide: function(callback, preventBlur) {
  6434. callback = $.isFunction(callback)
  6435. ? callback
  6436. : function(){}
  6437. ;
  6438. if( module.is.active() && !module.is.animatingOutward() ) {
  6439. module.debug('Hiding dropdown');
  6440. if(settings.onHide.call(element) !== false) {
  6441. module.animate.hide(function() {
  6442. module.remove.visible();
  6443. // hidding search focus
  6444. if ( module.is.focusedOnSearch() && preventBlur !== true ) {
  6445. $search.blur();
  6446. }
  6447. callback.call(element);
  6448. });
  6449. }
  6450. } else if( module.can.click() ) {
  6451. module.unbind.intent();
  6452. }
  6453. },
  6454. hideOthers: function() {
  6455. module.verbose('Finding other dropdowns to hide');
  6456. $allModules
  6457. .not($module)
  6458. .has(selector.menu + '.' + className.visible)
  6459. .dropdown('hide')
  6460. ;
  6461. },
  6462. hideMenu: function() {
  6463. module.verbose('Hiding menu instantaneously');
  6464. module.remove.active();
  6465. module.remove.visible();
  6466. $menu.transition('hide');
  6467. },
  6468. hideSubMenus: function() {
  6469. var
  6470. $subMenus = $menu.children(selector.item).find(selector.menu)
  6471. ;
  6472. module.verbose('Hiding sub menus', $subMenus);
  6473. $subMenus.transition('hide');
  6474. },
  6475. bind: {
  6476. events: function() {
  6477. module.bind.keyboardEvents();
  6478. module.bind.inputEvents();
  6479. module.bind.mouseEvents();
  6480. },
  6481. keyboardEvents: function() {
  6482. module.verbose('Binding keyboard events');
  6483. $module
  6484. .on('keydown' + eventNamespace, module.event.keydown)
  6485. ;
  6486. if( module.has.search() ) {
  6487. $module
  6488. .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
  6489. ;
  6490. }
  6491. if( module.is.multiple() ) {
  6492. $document
  6493. .on('keydown' + elementNamespace, module.event.document.keydown)
  6494. ;
  6495. }
  6496. },
  6497. inputEvents: function() {
  6498. module.verbose('Binding input change events');
  6499. $module
  6500. .on('change' + eventNamespace, selector.input, module.event.change)
  6501. ;
  6502. },
  6503. mouseEvents: function() {
  6504. module.verbose('Binding mouse events');
  6505. if(module.is.multiple()) {
  6506. $module
  6507. .on(clickEvent + eventNamespace, selector.label, module.event.label.click)
  6508. .on(clickEvent + eventNamespace, selector.remove, module.event.remove.click)
  6509. ;
  6510. }
  6511. if( module.is.searchSelection() ) {
  6512. $module
  6513. .on('mousedown' + eventNamespace, module.event.mousedown)
  6514. .on('mouseup' + eventNamespace, module.event.mouseup)
  6515. .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
  6516. .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
  6517. .on(clickEvent + eventNamespace, selector.icon, module.event.icon.click)
  6518. .on(clickEvent + eventNamespace, selector.clearIcon, module.event.clearIcon.click)
  6519. .on('focus' + eventNamespace, selector.search, module.event.search.focus)
  6520. .on(clickEvent + eventNamespace, selector.search, module.event.search.focus)
  6521. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  6522. .on(clickEvent + eventNamespace, selector.text, module.event.text.focus)
  6523. ;
  6524. if(module.is.multiple()) {
  6525. $module
  6526. .on(clickEvent + eventNamespace, module.event.click)
  6527. ;
  6528. }
  6529. }
  6530. else {
  6531. if(settings.on == 'click') {
  6532. $module
  6533. .on(clickEvent + eventNamespace, selector.icon, module.event.icon.click)
  6534. .on(clickEvent + eventNamespace, module.event.test.toggle)
  6535. ;
  6536. }
  6537. else if(settings.on == 'hover') {
  6538. $module
  6539. .on('mouseenter' + eventNamespace, module.delay.show)
  6540. .on('mouseleave' + eventNamespace, module.delay.hide)
  6541. ;
  6542. }
  6543. else {
  6544. $module
  6545. .on(settings.on + eventNamespace, module.toggle)
  6546. ;
  6547. }
  6548. $module
  6549. .on('mousedown' + eventNamespace, module.event.mousedown)
  6550. .on('mouseup' + eventNamespace, module.event.mouseup)
  6551. .on('focus' + eventNamespace, module.event.focus)
  6552. .on(clickEvent + eventNamespace, selector.clearIcon, module.event.clearIcon.click)
  6553. ;
  6554. if(module.has.menuSearch() ) {
  6555. $module
  6556. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  6557. ;
  6558. }
  6559. else {
  6560. $module
  6561. .on('blur' + eventNamespace, module.event.blur)
  6562. ;
  6563. }
  6564. }
  6565. $menu
  6566. .on((hasTouch ? 'touchstart' : 'mouseenter') + eventNamespace, selector.item, module.event.item.mouseenter)
  6567. .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
  6568. .on('click' + eventNamespace, selector.item, module.event.item.click)
  6569. ;
  6570. },
  6571. intent: function() {
  6572. module.verbose('Binding hide intent event to document');
  6573. if(hasTouch) {
  6574. $document
  6575. .on('touchstart' + elementNamespace, module.event.test.touch)
  6576. .on('touchmove' + elementNamespace, module.event.test.touch)
  6577. ;
  6578. }
  6579. $document
  6580. .on(clickEvent + elementNamespace, module.event.test.hide)
  6581. ;
  6582. }
  6583. },
  6584. unbind: {
  6585. intent: function() {
  6586. module.verbose('Removing hide intent event from document');
  6587. if(hasTouch) {
  6588. $document
  6589. .off('touchstart' + elementNamespace)
  6590. .off('touchmove' + elementNamespace)
  6591. ;
  6592. }
  6593. $document
  6594. .off(clickEvent + elementNamespace)
  6595. ;
  6596. }
  6597. },
  6598. filter: function(query) {
  6599. var
  6600. searchTerm = (query !== undefined)
  6601. ? query
  6602. : module.get.query(),
  6603. afterFiltered = function() {
  6604. if(module.is.multiple()) {
  6605. module.filterActive();
  6606. }
  6607. if(query || (!query && module.get.activeItem().length == 0)) {
  6608. module.select.firstUnfiltered();
  6609. }
  6610. if( module.has.allResultsFiltered() ) {
  6611. if( settings.onNoResults.call(element, searchTerm) ) {
  6612. if(settings.allowAdditions) {
  6613. if(settings.hideAdditions) {
  6614. module.verbose('User addition with no menu, setting empty style');
  6615. module.set.empty();
  6616. module.hideMenu();
  6617. }
  6618. }
  6619. else {
  6620. module.verbose('All items filtered, showing message', searchTerm);
  6621. module.add.message(message.noResults);
  6622. }
  6623. }
  6624. else {
  6625. module.verbose('All items filtered, hiding dropdown', searchTerm);
  6626. module.hideMenu();
  6627. }
  6628. }
  6629. else {
  6630. module.remove.empty();
  6631. module.remove.message();
  6632. }
  6633. if(settings.allowAdditions) {
  6634. module.add.userSuggestion(module.escape.htmlEntities(query));
  6635. }
  6636. if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
  6637. module.show();
  6638. }
  6639. }
  6640. ;
  6641. if(settings.useLabels && module.has.maxSelections()) {
  6642. return;
  6643. }
  6644. if(settings.apiSettings) {
  6645. if( module.can.useAPI() ) {
  6646. module.queryRemote(searchTerm, function() {
  6647. if(settings.filterRemoteData) {
  6648. module.filterItems(searchTerm);
  6649. }
  6650. var preSelected = $input.val();
  6651. if(!Array.isArray(preSelected)) {
  6652. preSelected = preSelected && preSelected!=="" ? preSelected.split(settings.delimiter) : [];
  6653. }
  6654. $.each(preSelected,function(index,value){
  6655. $item.filter('[data-value="'+value+'"]')
  6656. .addClass(className.filtered)
  6657. ;
  6658. });
  6659. afterFiltered();
  6660. });
  6661. }
  6662. else {
  6663. module.error(error.noAPI);
  6664. }
  6665. }
  6666. else {
  6667. module.filterItems(searchTerm);
  6668. afterFiltered();
  6669. }
  6670. },
  6671. queryRemote: function(query, callback) {
  6672. var
  6673. apiSettings = {
  6674. errorDuration : false,
  6675. cache : 'local',
  6676. throttle : settings.throttle,
  6677. urlData : {
  6678. query: query
  6679. },
  6680. onError: function() {
  6681. module.add.message(message.serverError);
  6682. callback();
  6683. },
  6684. onFailure: function() {
  6685. module.add.message(message.serverError);
  6686. callback();
  6687. },
  6688. onSuccess : function(response) {
  6689. var
  6690. values = response[fields.remoteValues]
  6691. ;
  6692. if (!Array.isArray(values)){
  6693. values = [];
  6694. }
  6695. module.remove.message();
  6696. module.setup.menu({
  6697. values: values
  6698. });
  6699. if(values.length===0 && !settings.allowAdditions) {
  6700. module.add.message(message.noResults);
  6701. }
  6702. callback();
  6703. }
  6704. }
  6705. ;
  6706. if( !$module.api('get request') ) {
  6707. module.setup.api();
  6708. }
  6709. apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
  6710. $module
  6711. .api('setting', apiSettings)
  6712. .api('query')
  6713. ;
  6714. },
  6715. filterItems: function(query) {
  6716. var
  6717. searchTerm = module.remove.diacritics(query !== undefined
  6718. ? query
  6719. : module.get.query()
  6720. ),
  6721. results = null,
  6722. escapedTerm = module.escape.string(searchTerm),
  6723. regExpFlags = (settings.ignoreSearchCase ? 'i' : '') + 'gm',
  6724. beginsWithRegExp = new RegExp('^' + escapedTerm, regExpFlags)
  6725. ;
  6726. // avoid loop if we're matching nothing
  6727. if( module.has.query() ) {
  6728. results = [];
  6729. module.verbose('Searching for matching values', searchTerm);
  6730. $item
  6731. .each(function(){
  6732. var
  6733. $choice = $(this),
  6734. text,
  6735. value
  6736. ;
  6737. if($choice.hasClass(className.unfilterable)) {
  6738. results.push(this);
  6739. return true;
  6740. }
  6741. if(settings.match === 'both' || settings.match === 'text') {
  6742. text = module.remove.diacritics(String(module.get.choiceText($choice, false)));
  6743. if(text.search(beginsWithRegExp) !== -1) {
  6744. results.push(this);
  6745. return true;
  6746. }
  6747. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) {
  6748. results.push(this);
  6749. return true;
  6750. }
  6751. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) {
  6752. results.push(this);
  6753. return true;
  6754. }
  6755. }
  6756. if(settings.match === 'both' || settings.match === 'value') {
  6757. value = module.remove.diacritics(String(module.get.choiceValue($choice, text)));
  6758. if(value.search(beginsWithRegExp) !== -1) {
  6759. results.push(this);
  6760. return true;
  6761. }
  6762. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, value)) {
  6763. results.push(this);
  6764. return true;
  6765. }
  6766. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, value)) {
  6767. results.push(this);
  6768. return true;
  6769. }
  6770. }
  6771. })
  6772. ;
  6773. }
  6774. module.debug('Showing only matched items', searchTerm);
  6775. module.remove.filteredItem();
  6776. if(results) {
  6777. $item
  6778. .not(results)
  6779. .addClass(className.filtered)
  6780. ;
  6781. }
  6782. if(!module.has.query()) {
  6783. $divider
  6784. .removeClass(className.hidden);
  6785. } else if(settings.hideDividers === true) {
  6786. $divider
  6787. .addClass(className.hidden);
  6788. } else if(settings.hideDividers === 'empty') {
  6789. $divider
  6790. .removeClass(className.hidden)
  6791. .filter(function() {
  6792. // First find the last divider in this divider group
  6793. // Dividers which are direct siblings are considered a group
  6794. var lastDivider = $(this).nextUntil(selector.item);
  6795. return (lastDivider.length ? lastDivider : $(this))
  6796. // Count all non-filtered items until the next divider (or end of the dropdown)
  6797. .nextUntil(selector.divider)
  6798. .filter(selector.item + ":not(." + className.filtered + ")")
  6799. // Hide divider if no items are found
  6800. .length === 0;
  6801. })
  6802. .addClass(className.hidden);
  6803. }
  6804. },
  6805. fuzzySearch: function(query, term) {
  6806. var
  6807. termLength = term.length,
  6808. queryLength = query.length
  6809. ;
  6810. query = (settings.ignoreSearchCase ? query.toLowerCase() : query);
  6811. term = (settings.ignoreSearchCase ? term.toLowerCase() : term);
  6812. if(queryLength > termLength) {
  6813. return false;
  6814. }
  6815. if(queryLength === termLength) {
  6816. return (query === term);
  6817. }
  6818. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  6819. var
  6820. queryCharacter = query.charCodeAt(characterIndex)
  6821. ;
  6822. while(nextCharacterIndex < termLength) {
  6823. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  6824. continue search;
  6825. }
  6826. }
  6827. return false;
  6828. }
  6829. return true;
  6830. },
  6831. exactSearch: function (query, term) {
  6832. query = (settings.ignoreSearchCase ? query.toLowerCase() : query);
  6833. term = (settings.ignoreSearchCase ? term.toLowerCase() : term);
  6834. return term.indexOf(query) > -1;
  6835. },
  6836. filterActive: function() {
  6837. if(settings.useLabels) {
  6838. $item.filter('.' + className.active)
  6839. .addClass(className.filtered)
  6840. ;
  6841. }
  6842. },
  6843. focusSearch: function(skipHandler) {
  6844. if( module.has.search() && !module.is.focusedOnSearch() ) {
  6845. if(skipHandler) {
  6846. $module.off('focus' + eventNamespace, selector.search);
  6847. $search.focus();
  6848. $module.on('focus' + eventNamespace, selector.search, module.event.search.focus);
  6849. }
  6850. else {
  6851. $search.focus();
  6852. }
  6853. }
  6854. },
  6855. blurSearch: function() {
  6856. if( module.has.search() ) {
  6857. $search.blur();
  6858. }
  6859. },
  6860. forceSelection: function() {
  6861. var
  6862. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  6863. $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
  6864. $selectedItem = ($currentlySelected.length > 0)
  6865. ? $currentlySelected
  6866. : $activeItem,
  6867. hasSelected = ($selectedItem.length > 0)
  6868. ;
  6869. if(settings.allowAdditions || (hasSelected && !module.is.multiple())) {
  6870. module.debug('Forcing partial selection to selected item', $selectedItem);
  6871. module.event.item.click.call($selectedItem, {}, true);
  6872. }
  6873. else {
  6874. module.remove.searchTerm();
  6875. }
  6876. },
  6877. change: {
  6878. values: function(values) {
  6879. if(!settings.allowAdditions) {
  6880. module.clear();
  6881. }
  6882. module.debug('Creating dropdown with specified values', values);
  6883. module.setup.menu({values: values});
  6884. $.each(values, function(index, item) {
  6885. if(item.selected == true) {
  6886. module.debug('Setting initial selection to', item[fields.value]);
  6887. module.set.selected(item[fields.value]);
  6888. if(!module.is.multiple()) {
  6889. return false;
  6890. }
  6891. }
  6892. });
  6893. if(module.has.selectInput()) {
  6894. module.disconnect.selectObserver();
  6895. $input.html('');
  6896. $input.append('<option disabled selected value></option>');
  6897. $.each(values, function(index, item) {
  6898. var
  6899. value = settings.templates.deQuote(item[fields.value]),
  6900. name = settings.templates.escape(
  6901. item[fields.name] || '',
  6902. settings.preserveHTML
  6903. )
  6904. ;
  6905. $input.append('<option value="' + value + '">' + name + '</option>');
  6906. });
  6907. module.observe.select();
  6908. }
  6909. }
  6910. },
  6911. event: {
  6912. change: function() {
  6913. if(!internalChange) {
  6914. module.debug('Input changed, updating selection');
  6915. module.set.selected();
  6916. }
  6917. },
  6918. focus: function() {
  6919. if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
  6920. module.show();
  6921. }
  6922. },
  6923. blur: function(event) {
  6924. pageLostFocus = (document.activeElement === this);
  6925. if(!activated && !pageLostFocus) {
  6926. module.remove.activeLabel();
  6927. module.hide();
  6928. }
  6929. },
  6930. mousedown: function() {
  6931. if(module.is.searchSelection()) {
  6932. // prevent menu hiding on immediate re-focus
  6933. willRefocus = true;
  6934. }
  6935. else {
  6936. // prevents focus callback from occurring on mousedown
  6937. activated = true;
  6938. }
  6939. },
  6940. mouseup: function() {
  6941. if(module.is.searchSelection()) {
  6942. // prevent menu hiding on immediate re-focus
  6943. willRefocus = false;
  6944. }
  6945. else {
  6946. activated = false;
  6947. }
  6948. },
  6949. click: function(event) {
  6950. var
  6951. $target = $(event.target)
  6952. ;
  6953. // focus search
  6954. if($target.is($module)) {
  6955. if(!module.is.focusedOnSearch()) {
  6956. module.focusSearch();
  6957. }
  6958. else {
  6959. module.show();
  6960. }
  6961. }
  6962. },
  6963. search: {
  6964. focus: function(event) {
  6965. activated = true;
  6966. if(module.is.multiple()) {
  6967. module.remove.activeLabel();
  6968. }
  6969. if(settings.showOnFocus || (event.type !== 'focus' && event.type !== 'focusin')) {
  6970. module.search();
  6971. }
  6972. },
  6973. blur: function(event) {
  6974. pageLostFocus = (document.activeElement === this);
  6975. if(module.is.searchSelection() && !willRefocus) {
  6976. if(!itemActivated && !pageLostFocus) {
  6977. if(settings.forceSelection) {
  6978. module.forceSelection();
  6979. } else if(!settings.allowAdditions){
  6980. module.remove.searchTerm();
  6981. }
  6982. module.hide();
  6983. }
  6984. }
  6985. willRefocus = false;
  6986. }
  6987. },
  6988. clearIcon: {
  6989. click: function(event) {
  6990. module.clear();
  6991. if(module.is.searchSelection()) {
  6992. module.remove.searchTerm();
  6993. }
  6994. module.hide();
  6995. event.stopPropagation();
  6996. }
  6997. },
  6998. icon: {
  6999. click: function(event) {
  7000. iconClicked=true;
  7001. if(module.has.search()) {
  7002. if(!module.is.active()) {
  7003. if(settings.showOnFocus){
  7004. module.focusSearch();
  7005. } else {
  7006. module.toggle();
  7007. }
  7008. } else {
  7009. module.blurSearch();
  7010. }
  7011. } else {
  7012. module.toggle();
  7013. }
  7014. }
  7015. },
  7016. text: {
  7017. focus: function(event) {
  7018. activated = true;
  7019. module.focusSearch();
  7020. }
  7021. },
  7022. input: function(event) {
  7023. if(module.is.multiple() || module.is.searchSelection()) {
  7024. module.set.filtered();
  7025. }
  7026. clearTimeout(module.timer);
  7027. module.timer = setTimeout(module.search, settings.delay.search);
  7028. },
  7029. label: {
  7030. click: function(event) {
  7031. var
  7032. $label = $(this),
  7033. $labels = $module.find(selector.label),
  7034. $activeLabels = $labels.filter('.' + className.active),
  7035. $nextActive = $label.nextAll('.' + className.active),
  7036. $prevActive = $label.prevAll('.' + className.active),
  7037. $range = ($nextActive.length > 0)
  7038. ? $label.nextUntil($nextActive).add($activeLabels).add($label)
  7039. : $label.prevUntil($prevActive).add($activeLabels).add($label)
  7040. ;
  7041. if(event.shiftKey) {
  7042. $activeLabels.removeClass(className.active);
  7043. $range.addClass(className.active);
  7044. }
  7045. else if(event.ctrlKey) {
  7046. $label.toggleClass(className.active);
  7047. }
  7048. else {
  7049. $activeLabels.removeClass(className.active);
  7050. $label.addClass(className.active);
  7051. }
  7052. settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
  7053. }
  7054. },
  7055. remove: {
  7056. click: function() {
  7057. var
  7058. $label = $(this).parent()
  7059. ;
  7060. if( $label.hasClass(className.active) ) {
  7061. // remove all selected labels
  7062. module.remove.activeLabels();
  7063. }
  7064. else {
  7065. // remove this label only
  7066. module.remove.activeLabels( $label );
  7067. }
  7068. }
  7069. },
  7070. test: {
  7071. toggle: function(event) {
  7072. var
  7073. toggleBehavior = (module.is.multiple())
  7074. ? module.show
  7075. : module.toggle
  7076. ;
  7077. if(module.is.bubbledLabelClick(event) || module.is.bubbledIconClick(event)) {
  7078. return;
  7079. }
  7080. if( module.determine.eventOnElement(event, toggleBehavior) ) {
  7081. event.preventDefault();
  7082. }
  7083. },
  7084. touch: function(event) {
  7085. module.determine.eventOnElement(event, function() {
  7086. if(event.type == 'touchstart') {
  7087. module.timer = setTimeout(function() {
  7088. module.hide();
  7089. }, settings.delay.touch);
  7090. }
  7091. else if(event.type == 'touchmove') {
  7092. clearTimeout(module.timer);
  7093. }
  7094. });
  7095. event.stopPropagation();
  7096. },
  7097. hide: function(event) {
  7098. if(module.determine.eventInModule(event, module.hide)){
  7099. if(element.id && $(event.target).attr('for') === element.id){
  7100. event.preventDefault();
  7101. }
  7102. }
  7103. }
  7104. },
  7105. select: {
  7106. mutation: function(mutations) {
  7107. module.debug('<select> modified, recreating menu');
  7108. if(module.is.selectMutation(mutations)) {
  7109. module.disconnect.selectObserver();
  7110. module.refresh();
  7111. module.setup.select();
  7112. module.set.selected();
  7113. module.observe.select();
  7114. }
  7115. }
  7116. },
  7117. menu: {
  7118. mutation: function(mutations) {
  7119. var
  7120. mutation = mutations[0],
  7121. $addedNode = mutation.addedNodes
  7122. ? $(mutation.addedNodes[0])
  7123. : $(false),
  7124. $removedNode = mutation.removedNodes
  7125. ? $(mutation.removedNodes[0])
  7126. : $(false),
  7127. $changedNodes = $addedNode.add($removedNode),
  7128. isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
  7129. isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
  7130. ;
  7131. if(isUserAddition || isMessage) {
  7132. module.debug('Updating item selector cache');
  7133. module.refreshItems();
  7134. }
  7135. else {
  7136. module.debug('Menu modified, updating selector cache');
  7137. module.refresh();
  7138. }
  7139. },
  7140. mousedown: function() {
  7141. itemActivated = true;
  7142. },
  7143. mouseup: function() {
  7144. itemActivated = false;
  7145. }
  7146. },
  7147. item: {
  7148. mouseenter: function(event) {
  7149. var
  7150. $target = $(event.target),
  7151. $item = $(this),
  7152. $subMenu = $item.children(selector.menu),
  7153. $otherMenus = $item.siblings(selector.item).children(selector.menu),
  7154. hasSubMenu = ($subMenu.length > 0),
  7155. isBubbledEvent = ($subMenu.find($target).length > 0)
  7156. ;
  7157. if( !isBubbledEvent && hasSubMenu ) {
  7158. clearTimeout(module.itemTimer);
  7159. module.itemTimer = setTimeout(function() {
  7160. module.verbose('Showing sub-menu', $subMenu);
  7161. $.each($otherMenus, function() {
  7162. module.animate.hide(false, $(this));
  7163. });
  7164. module.animate.show(false, $subMenu);
  7165. }, settings.delay.show);
  7166. event.preventDefault();
  7167. }
  7168. },
  7169. mouseleave: function(event) {
  7170. var
  7171. $subMenu = $(this).children(selector.menu)
  7172. ;
  7173. if($subMenu.length > 0) {
  7174. clearTimeout(module.itemTimer);
  7175. module.itemTimer = setTimeout(function() {
  7176. module.verbose('Hiding sub-menu', $subMenu);
  7177. module.animate.hide(false, $subMenu);
  7178. }, settings.delay.hide);
  7179. }
  7180. },
  7181. click: function (event, skipRefocus) {
  7182. var
  7183. $choice = $(this),
  7184. $target = (event)
  7185. ? $(event.target)
  7186. : $(''),
  7187. $subMenu = $choice.find(selector.menu),
  7188. text = module.get.choiceText($choice),
  7189. value = module.get.choiceValue($choice, text),
  7190. hasSubMenu = ($subMenu.length > 0),
  7191. isBubbledEvent = ($subMenu.find($target).length > 0)
  7192. ;
  7193. // prevents IE11 bug where menu receives focus even though `tabindex=-1`
  7194. if (document.activeElement.tagName.toLowerCase() !== 'input') {
  7195. $(document.activeElement).blur();
  7196. }
  7197. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  7198. if(module.is.searchSelection()) {
  7199. if(settings.allowAdditions) {
  7200. module.remove.userAddition();
  7201. }
  7202. module.remove.searchTerm();
  7203. if(!module.is.focusedOnSearch() && !(skipRefocus == true)) {
  7204. module.focusSearch(true);
  7205. }
  7206. }
  7207. if(!settings.useLabels) {
  7208. module.remove.filteredItem();
  7209. module.set.scrollPosition($choice);
  7210. }
  7211. module.determine.selectAction.call(this, text, value);
  7212. }
  7213. }
  7214. },
  7215. document: {
  7216. // label selection should occur even when element has no focus
  7217. keydown: function(event) {
  7218. var
  7219. pressedKey = event.which,
  7220. isShortcutKey = module.is.inObject(pressedKey, keys)
  7221. ;
  7222. if(isShortcutKey) {
  7223. var
  7224. $label = $module.find(selector.label),
  7225. $activeLabel = $label.filter('.' + className.active),
  7226. activeValue = $activeLabel.data(metadata.value),
  7227. labelIndex = $label.index($activeLabel),
  7228. labelCount = $label.length,
  7229. hasActiveLabel = ($activeLabel.length > 0),
  7230. hasMultipleActive = ($activeLabel.length > 1),
  7231. isFirstLabel = (labelIndex === 0),
  7232. isLastLabel = (labelIndex + 1 == labelCount),
  7233. isSearch = module.is.searchSelection(),
  7234. isFocusedOnSearch = module.is.focusedOnSearch(),
  7235. isFocused = module.is.focused(),
  7236. caretAtStart = (isFocusedOnSearch && module.get.caretPosition(false) === 0),
  7237. isSelectedSearch = (caretAtStart && module.get.caretPosition(true) !== 0),
  7238. $nextLabel
  7239. ;
  7240. if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
  7241. return;
  7242. }
  7243. if(pressedKey == keys.leftArrow) {
  7244. // activate previous label
  7245. if((isFocused || caretAtStart) && !hasActiveLabel) {
  7246. module.verbose('Selecting previous label');
  7247. $label.last().addClass(className.active);
  7248. }
  7249. else if(hasActiveLabel) {
  7250. if(!event.shiftKey) {
  7251. module.verbose('Selecting previous label');
  7252. $label.removeClass(className.active);
  7253. }
  7254. else {
  7255. module.verbose('Adding previous label to selection');
  7256. }
  7257. if(isFirstLabel && !hasMultipleActive) {
  7258. $activeLabel.addClass(className.active);
  7259. }
  7260. else {
  7261. $activeLabel.prev(selector.siblingLabel)
  7262. .addClass(className.active)
  7263. .end()
  7264. ;
  7265. }
  7266. event.preventDefault();
  7267. }
  7268. }
  7269. else if(pressedKey == keys.rightArrow) {
  7270. // activate first label
  7271. if(isFocused && !hasActiveLabel) {
  7272. $label.first().addClass(className.active);
  7273. }
  7274. // activate next label
  7275. if(hasActiveLabel) {
  7276. if(!event.shiftKey) {
  7277. module.verbose('Selecting next label');
  7278. $label.removeClass(className.active);
  7279. }
  7280. else {
  7281. module.verbose('Adding next label to selection');
  7282. }
  7283. if(isLastLabel) {
  7284. if(isSearch) {
  7285. if(!isFocusedOnSearch) {
  7286. module.focusSearch();
  7287. }
  7288. else {
  7289. $label.removeClass(className.active);
  7290. }
  7291. }
  7292. else if(hasMultipleActive) {
  7293. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  7294. }
  7295. else {
  7296. $activeLabel.addClass(className.active);
  7297. }
  7298. }
  7299. else {
  7300. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  7301. }
  7302. event.preventDefault();
  7303. }
  7304. }
  7305. else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
  7306. if(hasActiveLabel) {
  7307. module.verbose('Removing active labels');
  7308. if(isLastLabel) {
  7309. if(isSearch && !isFocusedOnSearch) {
  7310. module.focusSearch();
  7311. }
  7312. }
  7313. $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
  7314. module.remove.activeLabels($activeLabel);
  7315. event.preventDefault();
  7316. }
  7317. else if(caretAtStart && !isSelectedSearch && !hasActiveLabel && pressedKey == keys.backspace) {
  7318. module.verbose('Removing last label on input backspace');
  7319. $activeLabel = $label.last().addClass(className.active);
  7320. module.remove.activeLabels($activeLabel);
  7321. }
  7322. }
  7323. else {
  7324. $activeLabel.removeClass(className.active);
  7325. }
  7326. }
  7327. }
  7328. },
  7329. keydown: function(event) {
  7330. var
  7331. pressedKey = event.which,
  7332. isShortcutKey = module.is.inObject(pressedKey, keys)
  7333. ;
  7334. if(isShortcutKey) {
  7335. var
  7336. $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
  7337. $activeItem = $menu.children('.' + className.active).eq(0),
  7338. $selectedItem = ($currentlySelected.length > 0)
  7339. ? $currentlySelected
  7340. : $activeItem,
  7341. $visibleItems = ($selectedItem.length > 0)
  7342. ? $selectedItem.siblings(':not(.' + className.filtered +')').addBack()
  7343. : $menu.children(':not(.' + className.filtered +')'),
  7344. $subMenu = $selectedItem.children(selector.menu),
  7345. $parentMenu = $selectedItem.closest(selector.menu),
  7346. inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
  7347. hasSubMenu = ($subMenu.length> 0),
  7348. hasSelectedItem = ($selectedItem.length > 0),
  7349. selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
  7350. delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
  7351. isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable),
  7352. $nextItem,
  7353. isSubMenuItem,
  7354. newIndex
  7355. ;
  7356. // allow selection with menu closed
  7357. if(isAdditionWithoutMenu) {
  7358. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  7359. module.event.item.click.call($selectedItem, event);
  7360. if(module.is.searchSelection()) {
  7361. module.remove.searchTerm();
  7362. }
  7363. if(module.is.multiple()){
  7364. event.preventDefault();
  7365. }
  7366. }
  7367. // visible menu keyboard shortcuts
  7368. if( module.is.visible() ) {
  7369. // enter (select or open sub-menu)
  7370. if(pressedKey == keys.enter || delimiterPressed) {
  7371. if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
  7372. module.verbose('Pressed enter on unselectable category, opening sub menu');
  7373. pressedKey = keys.rightArrow;
  7374. }
  7375. else if(selectedIsSelectable) {
  7376. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  7377. module.event.item.click.call($selectedItem, event);
  7378. if(module.is.searchSelection()) {
  7379. module.remove.searchTerm();
  7380. if(module.is.multiple()) {
  7381. $search.focus();
  7382. }
  7383. }
  7384. }
  7385. event.preventDefault();
  7386. }
  7387. // sub-menu actions
  7388. if(hasSelectedItem) {
  7389. if(pressedKey == keys.leftArrow) {
  7390. isSubMenuItem = ($parentMenu[0] !== $menu[0]);
  7391. if(isSubMenuItem) {
  7392. module.verbose('Left key pressed, closing sub-menu');
  7393. module.animate.hide(false, $parentMenu);
  7394. $selectedItem
  7395. .removeClass(className.selected)
  7396. ;
  7397. $parentMenu
  7398. .closest(selector.item)
  7399. .addClass(className.selected)
  7400. ;
  7401. event.preventDefault();
  7402. }
  7403. }
  7404. // right arrow (show sub-menu)
  7405. if(pressedKey == keys.rightArrow) {
  7406. if(hasSubMenu) {
  7407. module.verbose('Right key pressed, opening sub-menu');
  7408. module.animate.show(false, $subMenu);
  7409. $selectedItem
  7410. .removeClass(className.selected)
  7411. ;
  7412. $subMenu
  7413. .find(selector.item).eq(0)
  7414. .addClass(className.selected)
  7415. ;
  7416. event.preventDefault();
  7417. }
  7418. }
  7419. }
  7420. // up arrow (traverse menu up)
  7421. if(pressedKey == keys.upArrow) {
  7422. $nextItem = (hasSelectedItem && inVisibleMenu)
  7423. ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  7424. : $item.eq(0)
  7425. ;
  7426. if($visibleItems.index( $nextItem ) < 0) {
  7427. module.verbose('Up key pressed but reached top of current menu');
  7428. event.preventDefault();
  7429. return;
  7430. }
  7431. else {
  7432. module.verbose('Up key pressed, changing active item');
  7433. $selectedItem
  7434. .removeClass(className.selected)
  7435. ;
  7436. $nextItem
  7437. .addClass(className.selected)
  7438. ;
  7439. module.set.scrollPosition($nextItem);
  7440. if(settings.selectOnKeydown && module.is.single()) {
  7441. module.set.selectedItem($nextItem);
  7442. }
  7443. }
  7444. event.preventDefault();
  7445. }
  7446. // down arrow (traverse menu down)
  7447. if(pressedKey == keys.downArrow) {
  7448. $nextItem = (hasSelectedItem && inVisibleMenu)
  7449. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  7450. : $item.eq(0)
  7451. ;
  7452. if($nextItem.length === 0) {
  7453. module.verbose('Down key pressed but reached bottom of current menu');
  7454. event.preventDefault();
  7455. return;
  7456. }
  7457. else {
  7458. module.verbose('Down key pressed, changing active item');
  7459. $item
  7460. .removeClass(className.selected)
  7461. ;
  7462. $nextItem
  7463. .addClass(className.selected)
  7464. ;
  7465. module.set.scrollPosition($nextItem);
  7466. if(settings.selectOnKeydown && module.is.single()) {
  7467. module.set.selectedItem($nextItem);
  7468. }
  7469. }
  7470. event.preventDefault();
  7471. }
  7472. // page down (show next page)
  7473. if(pressedKey == keys.pageUp) {
  7474. module.scrollPage('up');
  7475. event.preventDefault();
  7476. }
  7477. if(pressedKey == keys.pageDown) {
  7478. module.scrollPage('down');
  7479. event.preventDefault();
  7480. }
  7481. // escape (close menu)
  7482. if(pressedKey == keys.escape) {
  7483. module.verbose('Escape key pressed, closing dropdown');
  7484. module.hide();
  7485. }
  7486. }
  7487. else {
  7488. // delimiter key
  7489. if(delimiterPressed) {
  7490. event.preventDefault();
  7491. }
  7492. // down arrow (open menu)
  7493. if(pressedKey == keys.downArrow && !module.is.visible()) {
  7494. module.verbose('Down key pressed, showing dropdown');
  7495. module.show();
  7496. event.preventDefault();
  7497. }
  7498. }
  7499. }
  7500. else {
  7501. if( !module.has.search() ) {
  7502. module.set.selectedLetter( String.fromCharCode(pressedKey) );
  7503. }
  7504. }
  7505. }
  7506. },
  7507. trigger: {
  7508. change: function() {
  7509. var
  7510. events = document.createEvent('HTMLEvents'),
  7511. inputElement = $input[0]
  7512. ;
  7513. if(inputElement) {
  7514. module.verbose('Triggering native change event');
  7515. events.initEvent('change', true, false);
  7516. inputElement.dispatchEvent(events);
  7517. }
  7518. }
  7519. },
  7520. determine: {
  7521. selectAction: function(text, value) {
  7522. selectActionActive = true;
  7523. module.verbose('Determining action', settings.action);
  7524. if( $.isFunction( module.action[settings.action] ) ) {
  7525. module.verbose('Triggering preset action', settings.action, text, value);
  7526. module.action[ settings.action ].call(element, text, value, this);
  7527. }
  7528. else if( $.isFunction(settings.action) ) {
  7529. module.verbose('Triggering user action', settings.action, text, value);
  7530. settings.action.call(element, text, value, this);
  7531. }
  7532. else {
  7533. module.error(error.action, settings.action);
  7534. }
  7535. selectActionActive = false;
  7536. },
  7537. eventInModule: function(event, callback) {
  7538. var
  7539. $target = $(event.target),
  7540. inDocument = ($target.closest(document.documentElement).length > 0),
  7541. inModule = ($target.closest($module).length > 0)
  7542. ;
  7543. callback = $.isFunction(callback)
  7544. ? callback
  7545. : function(){}
  7546. ;
  7547. if(inDocument && !inModule) {
  7548. module.verbose('Triggering event', callback);
  7549. callback();
  7550. return true;
  7551. }
  7552. else {
  7553. module.verbose('Event occurred in dropdown, canceling callback');
  7554. return false;
  7555. }
  7556. },
  7557. eventOnElement: function(event, callback) {
  7558. var
  7559. $target = $(event.target),
  7560. $label = $target.closest(selector.siblingLabel),
  7561. inVisibleDOM = document.body.contains(event.target),
  7562. notOnLabel = ($module.find($label).length === 0 || !(module.is.multiple() && settings.useLabels)),
  7563. notInMenu = ($target.closest($menu).length === 0)
  7564. ;
  7565. callback = $.isFunction(callback)
  7566. ? callback
  7567. : function(){}
  7568. ;
  7569. if(inVisibleDOM && notOnLabel && notInMenu) {
  7570. module.verbose('Triggering event', callback);
  7571. callback();
  7572. return true;
  7573. }
  7574. else {
  7575. module.verbose('Event occurred in dropdown menu, canceling callback');
  7576. return false;
  7577. }
  7578. }
  7579. },
  7580. action: {
  7581. nothing: function() {},
  7582. activate: function(text, value, element) {
  7583. value = (value !== undefined)
  7584. ? value
  7585. : text
  7586. ;
  7587. if( module.can.activate( $(element) ) ) {
  7588. module.set.selected(value, $(element));
  7589. if(!module.is.multiple()) {
  7590. module.hideAndClear();
  7591. }
  7592. }
  7593. },
  7594. select: function(text, value, element) {
  7595. value = (value !== undefined)
  7596. ? value
  7597. : text
  7598. ;
  7599. if( module.can.activate( $(element) ) ) {
  7600. module.set.value(value, text, $(element));
  7601. if(!module.is.multiple()) {
  7602. module.hideAndClear();
  7603. }
  7604. }
  7605. },
  7606. combo: function(text, value, element) {
  7607. value = (value !== undefined)
  7608. ? value
  7609. : text
  7610. ;
  7611. module.set.selected(value, $(element));
  7612. module.hideAndClear();
  7613. },
  7614. hide: function(text, value, element) {
  7615. module.set.value(value, text, $(element));
  7616. module.hideAndClear();
  7617. }
  7618. },
  7619. get: {
  7620. id: function() {
  7621. return id;
  7622. },
  7623. defaultText: function() {
  7624. return $module.data(metadata.defaultText);
  7625. },
  7626. defaultValue: function() {
  7627. return $module.data(metadata.defaultValue);
  7628. },
  7629. placeholderText: function() {
  7630. if(settings.placeholder != 'auto' && typeof settings.placeholder == 'string') {
  7631. return settings.placeholder;
  7632. }
  7633. return $module.data(metadata.placeholderText) || '';
  7634. },
  7635. text: function() {
  7636. return $text.text();
  7637. },
  7638. query: function() {
  7639. return $.trim($search.val());
  7640. },
  7641. searchWidth: function(value) {
  7642. value = (value !== undefined)
  7643. ? value
  7644. : $search.val()
  7645. ;
  7646. $sizer.text(value);
  7647. // prevent rounding issues
  7648. return Math.ceil( $sizer.width() + 1);
  7649. },
  7650. selectionCount: function() {
  7651. var
  7652. values = module.get.values(),
  7653. count
  7654. ;
  7655. count = ( module.is.multiple() )
  7656. ? Array.isArray(values)
  7657. ? values.length
  7658. : 0
  7659. : (module.get.value() !== '')
  7660. ? 1
  7661. : 0
  7662. ;
  7663. return count;
  7664. },
  7665. transition: function($subMenu) {
  7666. return (settings.transition == 'auto')
  7667. ? module.is.upward($subMenu)
  7668. ? 'slide up'
  7669. : 'slide down'
  7670. : settings.transition
  7671. ;
  7672. },
  7673. userValues: function() {
  7674. var
  7675. values = module.get.values()
  7676. ;
  7677. if(!values) {
  7678. return false;
  7679. }
  7680. values = Array.isArray(values)
  7681. ? values
  7682. : [values]
  7683. ;
  7684. return $.grep(values, function(value) {
  7685. return (module.get.item(value) === false);
  7686. });
  7687. },
  7688. uniqueArray: function(array) {
  7689. return $.grep(array, function (value, index) {
  7690. return $.inArray(value, array) === index;
  7691. });
  7692. },
  7693. caretPosition: function(returnEndPos) {
  7694. var
  7695. input = $search.get(0),
  7696. range,
  7697. rangeLength
  7698. ;
  7699. if(returnEndPos && 'selectionEnd' in input){
  7700. return input.selectionEnd;
  7701. }
  7702. else if(!returnEndPos && 'selectionStart' in input) {
  7703. return input.selectionStart;
  7704. }
  7705. if (document.selection) {
  7706. input.focus();
  7707. range = document.selection.createRange();
  7708. rangeLength = range.text.length;
  7709. if(returnEndPos) {
  7710. return rangeLength;
  7711. }
  7712. range.moveStart('character', -input.value.length);
  7713. return range.text.length - rangeLength;
  7714. }
  7715. },
  7716. value: function() {
  7717. var
  7718. value = ($input.length > 0)
  7719. ? $input.val()
  7720. : $module.data(metadata.value),
  7721. isEmptyMultiselect = (Array.isArray(value) && value.length === 1 && value[0] === '')
  7722. ;
  7723. // prevents placeholder element from being selected when multiple
  7724. return (value === undefined || isEmptyMultiselect)
  7725. ? ''
  7726. : value
  7727. ;
  7728. },
  7729. values: function() {
  7730. var
  7731. value = module.get.value()
  7732. ;
  7733. if(value === '') {
  7734. return '';
  7735. }
  7736. return ( !module.has.selectInput() && module.is.multiple() )
  7737. ? (typeof value == 'string') // delimited string
  7738. ? module.escape.htmlEntities(value).split(settings.delimiter)
  7739. : ''
  7740. : value
  7741. ;
  7742. },
  7743. remoteValues: function() {
  7744. var
  7745. values = module.get.values(),
  7746. remoteValues = false
  7747. ;
  7748. if(values) {
  7749. if(typeof values == 'string') {
  7750. values = [values];
  7751. }
  7752. $.each(values, function(index, value) {
  7753. var
  7754. name = module.read.remoteData(value)
  7755. ;
  7756. module.verbose('Restoring value from session data', name, value);
  7757. if(name) {
  7758. if(!remoteValues) {
  7759. remoteValues = {};
  7760. }
  7761. remoteValues[value] = name;
  7762. }
  7763. });
  7764. }
  7765. return remoteValues;
  7766. },
  7767. choiceText: function($choice, preserveHTML) {
  7768. preserveHTML = (preserveHTML !== undefined)
  7769. ? preserveHTML
  7770. : settings.preserveHTML
  7771. ;
  7772. if($choice) {
  7773. if($choice.find(selector.menu).length > 0) {
  7774. module.verbose('Retrieving text of element with sub-menu');
  7775. $choice = $choice.clone();
  7776. $choice.find(selector.menu).remove();
  7777. $choice.find(selector.menuIcon).remove();
  7778. }
  7779. return ($choice.data(metadata.text) !== undefined)
  7780. ? $choice.data(metadata.text)
  7781. : (preserveHTML)
  7782. ? $.trim($choice.html())
  7783. : $.trim($choice.text())
  7784. ;
  7785. }
  7786. },
  7787. choiceValue: function($choice, choiceText) {
  7788. choiceText = choiceText || module.get.choiceText($choice);
  7789. if(!$choice) {
  7790. return false;
  7791. }
  7792. return ($choice.data(metadata.value) !== undefined)
  7793. ? String( $choice.data(metadata.value) )
  7794. : (typeof choiceText === 'string')
  7795. ? $.trim(
  7796. settings.ignoreSearchCase
  7797. ? choiceText.toLowerCase()
  7798. : choiceText
  7799. )
  7800. : String(choiceText)
  7801. ;
  7802. },
  7803. inputEvent: function() {
  7804. var
  7805. input = $search[0]
  7806. ;
  7807. if(input) {
  7808. return (input.oninput !== undefined)
  7809. ? 'input'
  7810. : (input.onpropertychange !== undefined)
  7811. ? 'propertychange'
  7812. : 'keyup'
  7813. ;
  7814. }
  7815. return false;
  7816. },
  7817. selectValues: function() {
  7818. var
  7819. select = {},
  7820. oldGroup = []
  7821. ;
  7822. select.values = [];
  7823. $module
  7824. .find('option')
  7825. .each(function() {
  7826. var
  7827. $option = $(this),
  7828. name = $option.html(),
  7829. disabled = $option.attr('disabled'),
  7830. value = ( $option.attr('value') !== undefined )
  7831. ? $option.attr('value')
  7832. : name,
  7833. text = ( $option.data(metadata.text) !== undefined )
  7834. ? $option.data(metadata.text)
  7835. : name,
  7836. group = $option.parent('optgroup')
  7837. ;
  7838. if(settings.placeholder === 'auto' && value === '') {
  7839. select.placeholder = name;
  7840. }
  7841. else {
  7842. if(group.length !== oldGroup.length || group[0] !== oldGroup[0]) {
  7843. select.values.push({
  7844. type: 'header',
  7845. divider: settings.headerDivider,
  7846. name: group.attr('label') || ''
  7847. });
  7848. oldGroup = group;
  7849. }
  7850. select.values.push({
  7851. name : name,
  7852. value : value,
  7853. text : text,
  7854. disabled : disabled
  7855. });
  7856. }
  7857. })
  7858. ;
  7859. if(settings.placeholder && settings.placeholder !== 'auto') {
  7860. module.debug('Setting placeholder value to', settings.placeholder);
  7861. select.placeholder = settings.placeholder;
  7862. }
  7863. if(settings.sortSelect) {
  7864. if(settings.sortSelect === true) {
  7865. select.values.sort(function(a, b) {
  7866. return a.name.localeCompare(b.name);
  7867. });
  7868. } else if(settings.sortSelect === 'natural') {
  7869. select.values.sort(function(a, b) {
  7870. return (a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
  7871. });
  7872. } else if($.isFunction(settings.sortSelect)) {
  7873. select.values.sort(settings.sortSelect);
  7874. }
  7875. module.debug('Retrieved and sorted values from select', select);
  7876. }
  7877. else {
  7878. module.debug('Retrieved values from select', select);
  7879. }
  7880. return select;
  7881. },
  7882. activeItem: function() {
  7883. return $item.filter('.' + className.active);
  7884. },
  7885. selectedItem: function() {
  7886. var
  7887. $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
  7888. ;
  7889. return ($selectedItem.length > 0)
  7890. ? $selectedItem
  7891. : $item.eq(0)
  7892. ;
  7893. },
  7894. itemWithAdditions: function(value) {
  7895. var
  7896. $items = module.get.item(value),
  7897. $userItems = module.create.userChoice(value),
  7898. hasUserItems = ($userItems && $userItems.length > 0)
  7899. ;
  7900. if(hasUserItems) {
  7901. $items = ($items.length > 0)
  7902. ? $items.add($userItems)
  7903. : $userItems
  7904. ;
  7905. }
  7906. return $items;
  7907. },
  7908. item: function(value, strict) {
  7909. var
  7910. $selectedItem = false,
  7911. shouldSearch,
  7912. isMultiple
  7913. ;
  7914. value = (value !== undefined)
  7915. ? value
  7916. : ( module.get.values() !== undefined)
  7917. ? module.get.values()
  7918. : module.get.text()
  7919. ;
  7920. isMultiple = (module.is.multiple() && Array.isArray(value));
  7921. shouldSearch = (isMultiple)
  7922. ? (value.length > 0)
  7923. : (value !== undefined && value !== null)
  7924. ;
  7925. strict = (value === '' || value === false || value === true)
  7926. ? true
  7927. : strict || false
  7928. ;
  7929. if(shouldSearch) {
  7930. $item
  7931. .each(function() {
  7932. var
  7933. $choice = $(this),
  7934. optionText = module.get.choiceText($choice),
  7935. optionValue = module.get.choiceValue($choice, optionText)
  7936. ;
  7937. // safe early exit
  7938. if(optionValue === null || optionValue === undefined) {
  7939. return;
  7940. }
  7941. if(isMultiple) {
  7942. if($.inArray(module.escape.htmlEntities(String(optionValue)), value.map(function(v){return String(v);})) !== -1) {
  7943. $selectedItem = ($selectedItem)
  7944. ? $selectedItem.add($choice)
  7945. : $choice
  7946. ;
  7947. }
  7948. }
  7949. else if(strict) {
  7950. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  7951. if( optionValue === value) {
  7952. $selectedItem = $choice;
  7953. return true;
  7954. }
  7955. }
  7956. else {
  7957. if(settings.ignoreCase) {
  7958. optionValue = optionValue.toLowerCase();
  7959. value = value.toLowerCase();
  7960. }
  7961. if(module.escape.htmlEntities(String(optionValue)) === module.escape.htmlEntities(String(value))) {
  7962. module.verbose('Found select item by value', optionValue, value);
  7963. $selectedItem = $choice;
  7964. return true;
  7965. }
  7966. }
  7967. })
  7968. ;
  7969. }
  7970. return $selectedItem;
  7971. }
  7972. },
  7973. check: {
  7974. maxSelections: function(selectionCount) {
  7975. if(settings.maxSelections) {
  7976. selectionCount = (selectionCount !== undefined)
  7977. ? selectionCount
  7978. : module.get.selectionCount()
  7979. ;
  7980. if(selectionCount >= settings.maxSelections) {
  7981. module.debug('Maximum selection count reached');
  7982. if(settings.useLabels) {
  7983. $item.addClass(className.filtered);
  7984. module.add.message(message.maxSelections);
  7985. }
  7986. return true;
  7987. }
  7988. else {
  7989. module.verbose('No longer at maximum selection count');
  7990. module.remove.message();
  7991. module.remove.filteredItem();
  7992. if(module.is.searchSelection()) {
  7993. module.filterItems();
  7994. }
  7995. return false;
  7996. }
  7997. }
  7998. return true;
  7999. }
  8000. },
  8001. restore: {
  8002. defaults: function(preventChangeTrigger) {
  8003. module.clear(preventChangeTrigger);
  8004. module.restore.defaultText();
  8005. module.restore.defaultValue();
  8006. },
  8007. defaultText: function() {
  8008. var
  8009. defaultText = module.get.defaultText(),
  8010. placeholderText = module.get.placeholderText
  8011. ;
  8012. if(defaultText === placeholderText) {
  8013. module.debug('Restoring default placeholder text', defaultText);
  8014. module.set.placeholderText(defaultText);
  8015. }
  8016. else {
  8017. module.debug('Restoring default text', defaultText);
  8018. module.set.text(defaultText);
  8019. }
  8020. },
  8021. placeholderText: function() {
  8022. module.set.placeholderText();
  8023. },
  8024. defaultValue: function() {
  8025. var
  8026. defaultValue = module.get.defaultValue()
  8027. ;
  8028. if(defaultValue !== undefined) {
  8029. module.debug('Restoring default value', defaultValue);
  8030. if(defaultValue !== '') {
  8031. module.set.value(defaultValue);
  8032. module.set.selected();
  8033. }
  8034. else {
  8035. module.remove.activeItem();
  8036. module.remove.selectedItem();
  8037. }
  8038. }
  8039. },
  8040. labels: function() {
  8041. if(settings.allowAdditions) {
  8042. if(!settings.useLabels) {
  8043. module.error(error.labels);
  8044. settings.useLabels = true;
  8045. }
  8046. module.debug('Restoring selected values');
  8047. module.create.userLabels();
  8048. }
  8049. module.check.maxSelections();
  8050. },
  8051. selected: function() {
  8052. module.restore.values();
  8053. if(module.is.multiple()) {
  8054. module.debug('Restoring previously selected values and labels');
  8055. module.restore.labels();
  8056. }
  8057. else {
  8058. module.debug('Restoring previously selected values');
  8059. }
  8060. },
  8061. values: function() {
  8062. // prevents callbacks from occurring on initial load
  8063. module.set.initialLoad();
  8064. if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) {
  8065. module.restore.remoteValues();
  8066. }
  8067. else {
  8068. module.set.selected();
  8069. }
  8070. var value = module.get.value();
  8071. if(value && value !== '' && !(Array.isArray(value) && value.length === 0)) {
  8072. $input.removeClass(className.noselection);
  8073. } else {
  8074. $input.addClass(className.noselection);
  8075. }
  8076. module.remove.initialLoad();
  8077. },
  8078. remoteValues: function() {
  8079. var
  8080. values = module.get.remoteValues()
  8081. ;
  8082. module.debug('Recreating selected from session data', values);
  8083. if(values) {
  8084. if( module.is.single() ) {
  8085. $.each(values, function(value, name) {
  8086. module.set.text(name);
  8087. });
  8088. }
  8089. else {
  8090. $.each(values, function(value, name) {
  8091. module.add.label(value, name);
  8092. });
  8093. }
  8094. }
  8095. }
  8096. },
  8097. read: {
  8098. remoteData: function(value) {
  8099. var
  8100. name
  8101. ;
  8102. if(window.Storage === undefined) {
  8103. module.error(error.noStorage);
  8104. return;
  8105. }
  8106. name = sessionStorage.getItem(value);
  8107. return (name !== undefined)
  8108. ? name
  8109. : false
  8110. ;
  8111. }
  8112. },
  8113. save: {
  8114. defaults: function() {
  8115. module.save.defaultText();
  8116. module.save.placeholderText();
  8117. module.save.defaultValue();
  8118. },
  8119. defaultValue: function() {
  8120. var
  8121. value = module.get.value()
  8122. ;
  8123. module.verbose('Saving default value as', value);
  8124. $module.data(metadata.defaultValue, value);
  8125. },
  8126. defaultText: function() {
  8127. var
  8128. text = module.get.text()
  8129. ;
  8130. module.verbose('Saving default text as', text);
  8131. $module.data(metadata.defaultText, text);
  8132. },
  8133. placeholderText: function() {
  8134. var
  8135. text
  8136. ;
  8137. if(settings.placeholder !== false && $text.hasClass(className.placeholder)) {
  8138. text = module.get.text();
  8139. module.verbose('Saving placeholder text as', text);
  8140. $module.data(metadata.placeholderText, text);
  8141. }
  8142. },
  8143. remoteData: function(name, value) {
  8144. if(window.Storage === undefined) {
  8145. module.error(error.noStorage);
  8146. return;
  8147. }
  8148. module.verbose('Saving remote data to session storage', value, name);
  8149. sessionStorage.setItem(value, name);
  8150. }
  8151. },
  8152. clear: function(preventChangeTrigger) {
  8153. if(module.is.multiple() && settings.useLabels) {
  8154. module.remove.labels();
  8155. }
  8156. else {
  8157. module.remove.activeItem();
  8158. module.remove.selectedItem();
  8159. module.remove.filteredItem();
  8160. }
  8161. module.set.placeholderText();
  8162. module.clearValue(preventChangeTrigger);
  8163. },
  8164. clearValue: function(preventChangeTrigger) {
  8165. module.set.value('', null, null, preventChangeTrigger);
  8166. },
  8167. scrollPage: function(direction, $selectedItem) {
  8168. var
  8169. $currentItem = $selectedItem || module.get.selectedItem(),
  8170. $menu = $currentItem.closest(selector.menu),
  8171. menuHeight = $menu.outerHeight(),
  8172. currentScroll = $menu.scrollTop(),
  8173. itemHeight = $item.eq(0).outerHeight(),
  8174. itemsPerPage = Math.floor(menuHeight / itemHeight),
  8175. maxScroll = $menu.prop('scrollHeight'),
  8176. newScroll = (direction == 'up')
  8177. ? currentScroll - (itemHeight * itemsPerPage)
  8178. : currentScroll + (itemHeight * itemsPerPage),
  8179. $selectableItem = $item.not(selector.unselectable),
  8180. isWithinRange,
  8181. $nextSelectedItem,
  8182. elementIndex
  8183. ;
  8184. elementIndex = (direction == 'up')
  8185. ? $selectableItem.index($currentItem) - itemsPerPage
  8186. : $selectableItem.index($currentItem) + itemsPerPage
  8187. ;
  8188. isWithinRange = (direction == 'up')
  8189. ? (elementIndex >= 0)
  8190. : (elementIndex < $selectableItem.length)
  8191. ;
  8192. $nextSelectedItem = (isWithinRange)
  8193. ? $selectableItem.eq(elementIndex)
  8194. : (direction == 'up')
  8195. ? $selectableItem.first()
  8196. : $selectableItem.last()
  8197. ;
  8198. if($nextSelectedItem.length > 0) {
  8199. module.debug('Scrolling page', direction, $nextSelectedItem);
  8200. $currentItem
  8201. .removeClass(className.selected)
  8202. ;
  8203. $nextSelectedItem
  8204. .addClass(className.selected)
  8205. ;
  8206. if(settings.selectOnKeydown && module.is.single()) {
  8207. module.set.selectedItem($nextSelectedItem);
  8208. }
  8209. $menu
  8210. .scrollTop(newScroll)
  8211. ;
  8212. }
  8213. },
  8214. set: {
  8215. filtered: function() {
  8216. var
  8217. isMultiple = module.is.multiple(),
  8218. isSearch = module.is.searchSelection(),
  8219. isSearchMultiple = (isMultiple && isSearch),
  8220. searchValue = (isSearch)
  8221. ? module.get.query()
  8222. : '',
  8223. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
  8224. searchWidth = module.get.searchWidth(),
  8225. valueIsSet = searchValue !== ''
  8226. ;
  8227. if(isMultiple && hasSearchValue) {
  8228. module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
  8229. $search.css('width', searchWidth);
  8230. }
  8231. if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
  8232. module.verbose('Hiding placeholder text');
  8233. $text.addClass(className.filtered);
  8234. }
  8235. else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
  8236. module.verbose('Showing placeholder text');
  8237. $text.removeClass(className.filtered);
  8238. }
  8239. },
  8240. empty: function() {
  8241. $module.addClass(className.empty);
  8242. },
  8243. loading: function() {
  8244. $module.addClass(className.loading);
  8245. },
  8246. placeholderText: function(text) {
  8247. text = text || module.get.placeholderText();
  8248. module.debug('Setting placeholder text', text);
  8249. module.set.text(text);
  8250. $text.addClass(className.placeholder);
  8251. },
  8252. tabbable: function() {
  8253. if( module.is.searchSelection() ) {
  8254. module.debug('Added tabindex to searchable dropdown');
  8255. $search
  8256. .val('')
  8257. .attr('tabindex', 0)
  8258. ;
  8259. $menu
  8260. .attr('tabindex', -1)
  8261. ;
  8262. }
  8263. else {
  8264. module.debug('Added tabindex to dropdown');
  8265. if( $module.attr('tabindex') === undefined) {
  8266. $module
  8267. .attr('tabindex', 0)
  8268. ;
  8269. $menu
  8270. .attr('tabindex', -1)
  8271. ;
  8272. }
  8273. }
  8274. },
  8275. initialLoad: function() {
  8276. module.verbose('Setting initial load');
  8277. initialLoad = true;
  8278. },
  8279. activeItem: function($item) {
  8280. if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) {
  8281. $item.addClass(className.filtered);
  8282. }
  8283. else {
  8284. $item.addClass(className.active);
  8285. }
  8286. },
  8287. partialSearch: function(text) {
  8288. var
  8289. length = module.get.query().length
  8290. ;
  8291. $search.val( text.substr(0, length));
  8292. },
  8293. scrollPosition: function($item, forceScroll) {
  8294. var
  8295. edgeTolerance = 5,
  8296. $menu,
  8297. hasActive,
  8298. offset,
  8299. itemHeight,
  8300. itemOffset,
  8301. menuOffset,
  8302. menuScroll,
  8303. menuHeight,
  8304. abovePage,
  8305. belowPage
  8306. ;
  8307. $item = $item || module.get.selectedItem();
  8308. $menu = $item.closest(selector.menu);
  8309. hasActive = ($item && $item.length > 0);
  8310. forceScroll = (forceScroll !== undefined)
  8311. ? forceScroll
  8312. : false
  8313. ;
  8314. if(module.get.activeItem().length === 0){
  8315. forceScroll = false;
  8316. }
  8317. if($item && $menu.length > 0 && hasActive) {
  8318. itemOffset = $item.position().top;
  8319. $menu.addClass(className.loading);
  8320. menuScroll = $menu.scrollTop();
  8321. menuOffset = $menu.offset().top;
  8322. itemOffset = $item.offset().top;
  8323. offset = menuScroll - menuOffset + itemOffset;
  8324. if(!forceScroll) {
  8325. menuHeight = $menu.height();
  8326. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  8327. abovePage = ((offset - edgeTolerance) < menuScroll);
  8328. }
  8329. module.debug('Scrolling to active item', offset);
  8330. if(forceScroll || abovePage || belowPage) {
  8331. $menu.scrollTop(offset);
  8332. }
  8333. $menu.removeClass(className.loading);
  8334. }
  8335. },
  8336. text: function(text) {
  8337. if(settings.action === 'combo') {
  8338. module.debug('Changing combo button text', text, $combo);
  8339. if(settings.preserveHTML) {
  8340. $combo.html(text);
  8341. }
  8342. else {
  8343. $combo.text(text);
  8344. }
  8345. }
  8346. else if(settings.action === 'activate') {
  8347. if(text !== module.get.placeholderText()) {
  8348. $text.removeClass(className.placeholder);
  8349. }
  8350. module.debug('Changing text', text, $text);
  8351. $text
  8352. .removeClass(className.filtered)
  8353. ;
  8354. if(settings.preserveHTML) {
  8355. $text.html(text);
  8356. }
  8357. else {
  8358. $text.text(text);
  8359. }
  8360. }
  8361. },
  8362. selectedItem: function($item) {
  8363. var
  8364. value = module.get.choiceValue($item),
  8365. searchText = module.get.choiceText($item, false),
  8366. text = module.get.choiceText($item, true)
  8367. ;
  8368. module.debug('Setting user selection to item', $item);
  8369. module.remove.activeItem();
  8370. module.set.partialSearch(searchText);
  8371. module.set.activeItem($item);
  8372. module.set.selected(value, $item);
  8373. module.set.text(text);
  8374. },
  8375. selectedLetter: function(letter) {
  8376. var
  8377. $selectedItem = $item.filter('.' + className.selected),
  8378. alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter),
  8379. $nextValue = false,
  8380. $nextItem
  8381. ;
  8382. // check next of same letter
  8383. if(alreadySelectedLetter) {
  8384. $nextItem = $selectedItem.nextAll($item).eq(0);
  8385. if( module.has.firstLetter($nextItem, letter) ) {
  8386. $nextValue = $nextItem;
  8387. }
  8388. }
  8389. // check all values
  8390. if(!$nextValue) {
  8391. $item
  8392. .each(function(){
  8393. if(module.has.firstLetter($(this), letter)) {
  8394. $nextValue = $(this);
  8395. return false;
  8396. }
  8397. })
  8398. ;
  8399. }
  8400. // set next value
  8401. if($nextValue) {
  8402. module.verbose('Scrolling to next value with letter', letter);
  8403. module.set.scrollPosition($nextValue);
  8404. $selectedItem.removeClass(className.selected);
  8405. $nextValue.addClass(className.selected);
  8406. if(settings.selectOnKeydown && module.is.single()) {
  8407. module.set.selectedItem($nextValue);
  8408. }
  8409. }
  8410. },
  8411. direction: function($menu) {
  8412. if(settings.direction == 'auto') {
  8413. // reset position, remove upward if it's base menu
  8414. if (!$menu) {
  8415. module.remove.upward();
  8416. } else if (module.is.upward($menu)) {
  8417. //we need make sure when make assertion openDownward for $menu, $menu does not have upward class
  8418. module.remove.upward($menu);
  8419. }
  8420. if(module.can.openDownward($menu)) {
  8421. module.remove.upward($menu);
  8422. }
  8423. else {
  8424. module.set.upward($menu);
  8425. }
  8426. if(!module.is.leftward($menu) && !module.can.openRightward($menu)) {
  8427. module.set.leftward($menu);
  8428. }
  8429. }
  8430. else if(settings.direction == 'upward') {
  8431. module.set.upward($menu);
  8432. }
  8433. },
  8434. upward: function($currentMenu) {
  8435. var $element = $currentMenu || $module;
  8436. $element.addClass(className.upward);
  8437. },
  8438. leftward: function($currentMenu) {
  8439. var $element = $currentMenu || $menu;
  8440. $element.addClass(className.leftward);
  8441. },
  8442. value: function(value, text, $selected, preventChangeTrigger) {
  8443. if(value !== undefined && value !== '' && !(Array.isArray(value) && value.length === 0)) {
  8444. $input.removeClass(className.noselection);
  8445. } else {
  8446. $input.addClass(className.noselection);
  8447. }
  8448. var
  8449. escapedValue = module.escape.value(value),
  8450. hasInput = ($input.length > 0),
  8451. currentValue = module.get.values(),
  8452. stringValue = (value !== undefined)
  8453. ? String(value)
  8454. : value,
  8455. newValue
  8456. ;
  8457. if(hasInput) {
  8458. if(!settings.allowReselection && stringValue == currentValue) {
  8459. module.verbose('Skipping value update already same value', value, currentValue);
  8460. if(!module.is.initialLoad()) {
  8461. return;
  8462. }
  8463. }
  8464. if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) {
  8465. module.debug('Adding user option', value);
  8466. module.add.optionValue(value);
  8467. }
  8468. module.debug('Updating input value', escapedValue, currentValue);
  8469. internalChange = true;
  8470. $input
  8471. .val(escapedValue)
  8472. ;
  8473. if(settings.fireOnInit === false && module.is.initialLoad()) {
  8474. module.debug('Input native change event ignored on initial load');
  8475. }
  8476. else if(preventChangeTrigger !== true) {
  8477. module.trigger.change();
  8478. }
  8479. internalChange = false;
  8480. }
  8481. else {
  8482. module.verbose('Storing value in metadata', escapedValue, $input);
  8483. if(escapedValue !== currentValue) {
  8484. $module.data(metadata.value, stringValue);
  8485. }
  8486. }
  8487. if(settings.fireOnInit === false && module.is.initialLoad()) {
  8488. module.verbose('No callback on initial load', settings.onChange);
  8489. }
  8490. else if(preventChangeTrigger !== true) {
  8491. settings.onChange.call(element, value, text, $selected);
  8492. }
  8493. },
  8494. active: function() {
  8495. $module
  8496. .addClass(className.active)
  8497. ;
  8498. },
  8499. multiple: function() {
  8500. $module.addClass(className.multiple);
  8501. },
  8502. visible: function() {
  8503. $module.addClass(className.visible);
  8504. },
  8505. exactly: function(value, $selectedItem) {
  8506. module.debug('Setting selected to exact values');
  8507. module.clear();
  8508. module.set.selected(value, $selectedItem);
  8509. },
  8510. selected: function(value, $selectedItem) {
  8511. var
  8512. isMultiple = module.is.multiple()
  8513. ;
  8514. $selectedItem = (settings.allowAdditions)
  8515. ? $selectedItem || module.get.itemWithAdditions(value)
  8516. : $selectedItem || module.get.item(value)
  8517. ;
  8518. if(!$selectedItem) {
  8519. return;
  8520. }
  8521. module.debug('Setting selected menu item to', $selectedItem);
  8522. if(module.is.multiple()) {
  8523. module.remove.searchWidth();
  8524. }
  8525. if(module.is.single()) {
  8526. module.remove.activeItem();
  8527. module.remove.selectedItem();
  8528. }
  8529. else if(settings.useLabels) {
  8530. module.remove.selectedItem();
  8531. }
  8532. // select each item
  8533. $selectedItem
  8534. .each(function() {
  8535. var
  8536. $selected = $(this),
  8537. selectedText = module.get.choiceText($selected),
  8538. selectedValue = module.get.choiceValue($selected, selectedText),
  8539. isFiltered = $selected.hasClass(className.filtered),
  8540. isActive = $selected.hasClass(className.active),
  8541. isUserValue = $selected.hasClass(className.addition),
  8542. shouldAnimate = (isMultiple && $selectedItem.length == 1)
  8543. ;
  8544. if(isMultiple) {
  8545. if(!isActive || isUserValue) {
  8546. if(settings.apiSettings && settings.saveRemoteData) {
  8547. module.save.remoteData(selectedText, selectedValue);
  8548. }
  8549. if(settings.useLabels) {
  8550. module.add.label(selectedValue, selectedText, shouldAnimate);
  8551. module.add.value(selectedValue, selectedText, $selected);
  8552. module.set.activeItem($selected);
  8553. module.filterActive();
  8554. module.select.nextAvailable($selectedItem);
  8555. }
  8556. else {
  8557. module.add.value(selectedValue, selectedText, $selected);
  8558. module.set.text(module.add.variables(message.count));
  8559. module.set.activeItem($selected);
  8560. }
  8561. }
  8562. else if(!isFiltered && (settings.useLabels || selectActionActive)) {
  8563. module.debug('Selected active value, removing label');
  8564. module.remove.selected(selectedValue);
  8565. }
  8566. }
  8567. else {
  8568. if(settings.apiSettings && settings.saveRemoteData) {
  8569. module.save.remoteData(selectedText, selectedValue);
  8570. }
  8571. module.set.text(selectedText);
  8572. module.set.value(selectedValue, selectedText, $selected);
  8573. $selected
  8574. .addClass(className.active)
  8575. .addClass(className.selected)
  8576. ;
  8577. }
  8578. })
  8579. ;
  8580. module.remove.searchTerm();
  8581. }
  8582. },
  8583. add: {
  8584. label: function(value, text, shouldAnimate) {
  8585. var
  8586. $next = module.is.searchSelection()
  8587. ? $search
  8588. : $text,
  8589. escapedValue = module.escape.value(value),
  8590. $label
  8591. ;
  8592. if(settings.ignoreCase) {
  8593. escapedValue = escapedValue.toLowerCase();
  8594. }
  8595. $label = $('<a />')
  8596. .addClass(className.label)
  8597. .attr('data-' + metadata.value, escapedValue)
  8598. .html(templates.label(escapedValue, text, settings.preserveHTML, settings.className))
  8599. ;
  8600. $label = settings.onLabelCreate.call($label, escapedValue, text);
  8601. if(module.has.label(value)) {
  8602. module.debug('User selection already exists, skipping', escapedValue);
  8603. return;
  8604. }
  8605. if(settings.label.variation) {
  8606. $label.addClass(settings.label.variation);
  8607. }
  8608. if(shouldAnimate === true) {
  8609. module.debug('Animating in label', $label);
  8610. $label
  8611. .addClass(className.hidden)
  8612. .insertBefore($next)
  8613. .transition({
  8614. animation : settings.label.transition,
  8615. debug : settings.debug,
  8616. verbose : settings.verbose,
  8617. duration : settings.label.duration
  8618. })
  8619. ;
  8620. }
  8621. else {
  8622. module.debug('Adding selection label', $label);
  8623. $label
  8624. .insertBefore($next)
  8625. ;
  8626. }
  8627. },
  8628. message: function(message) {
  8629. var
  8630. $message = $menu.children(selector.message),
  8631. html = settings.templates.message(module.add.variables(message))
  8632. ;
  8633. if($message.length > 0) {
  8634. $message
  8635. .html(html)
  8636. ;
  8637. }
  8638. else {
  8639. $message = $('<div/>')
  8640. .html(html)
  8641. .addClass(className.message)
  8642. .appendTo($menu)
  8643. ;
  8644. }
  8645. },
  8646. optionValue: function(value) {
  8647. var
  8648. escapedValue = module.escape.value(value),
  8649. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  8650. hasOption = ($option.length > 0)
  8651. ;
  8652. if(hasOption) {
  8653. return;
  8654. }
  8655. // temporarily disconnect observer
  8656. module.disconnect.selectObserver();
  8657. if( module.is.single() ) {
  8658. module.verbose('Removing previous user addition');
  8659. $input.find('option.' + className.addition).remove();
  8660. }
  8661. $('<option/>')
  8662. .prop('value', escapedValue)
  8663. .addClass(className.addition)
  8664. .html(value)
  8665. .appendTo($input)
  8666. ;
  8667. module.verbose('Adding user addition as an <option>', value);
  8668. module.observe.select();
  8669. },
  8670. userSuggestion: function(value) {
  8671. var
  8672. $addition = $menu.children(selector.addition),
  8673. $existingItem = module.get.item(value),
  8674. alreadyHasValue = $existingItem && $existingItem.not(selector.addition).length,
  8675. hasUserSuggestion = $addition.length > 0,
  8676. html
  8677. ;
  8678. if(settings.useLabels && module.has.maxSelections()) {
  8679. return;
  8680. }
  8681. if(value === '' || alreadyHasValue) {
  8682. $addition.remove();
  8683. return;
  8684. }
  8685. if(hasUserSuggestion) {
  8686. $addition
  8687. .data(metadata.value, value)
  8688. .data(metadata.text, value)
  8689. .attr('data-' + metadata.value, value)
  8690. .attr('data-' + metadata.text, value)
  8691. .removeClass(className.filtered)
  8692. ;
  8693. if(!settings.hideAdditions) {
  8694. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  8695. $addition
  8696. .html(html)
  8697. ;
  8698. }
  8699. module.verbose('Replacing user suggestion with new value', $addition);
  8700. }
  8701. else {
  8702. $addition = module.create.userChoice(value);
  8703. $addition
  8704. .prependTo($menu)
  8705. ;
  8706. module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
  8707. }
  8708. if(!settings.hideAdditions || module.is.allFiltered()) {
  8709. $addition
  8710. .addClass(className.selected)
  8711. .siblings()
  8712. .removeClass(className.selected)
  8713. ;
  8714. }
  8715. module.refreshItems();
  8716. },
  8717. variables: function(message, term) {
  8718. var
  8719. hasCount = (message.search('{count}') !== -1),
  8720. hasMaxCount = (message.search('{maxCount}') !== -1),
  8721. hasTerm = (message.search('{term}') !== -1),
  8722. count,
  8723. query
  8724. ;
  8725. module.verbose('Adding templated variables to message', message);
  8726. if(hasCount) {
  8727. count = module.get.selectionCount();
  8728. message = message.replace('{count}', count);
  8729. }
  8730. if(hasMaxCount) {
  8731. count = module.get.selectionCount();
  8732. message = message.replace('{maxCount}', settings.maxSelections);
  8733. }
  8734. if(hasTerm) {
  8735. query = term || module.get.query();
  8736. message = message.replace('{term}', query);
  8737. }
  8738. return message;
  8739. },
  8740. value: function(addedValue, addedText, $selectedItem) {
  8741. var
  8742. currentValue = module.get.values(),
  8743. newValue
  8744. ;
  8745. if(module.has.value(addedValue)) {
  8746. module.debug('Value already selected');
  8747. return;
  8748. }
  8749. if(addedValue === '') {
  8750. module.debug('Cannot select blank values from multiselect');
  8751. return;
  8752. }
  8753. // extend current array
  8754. if(Array.isArray(currentValue)) {
  8755. newValue = currentValue.concat([addedValue]);
  8756. newValue = module.get.uniqueArray(newValue);
  8757. }
  8758. else {
  8759. newValue = [addedValue];
  8760. }
  8761. // add values
  8762. if( module.has.selectInput() ) {
  8763. if(module.can.extendSelect()) {
  8764. module.debug('Adding value to select', addedValue, newValue, $input);
  8765. module.add.optionValue(addedValue);
  8766. }
  8767. }
  8768. else {
  8769. newValue = newValue.join(settings.delimiter);
  8770. module.debug('Setting hidden input to delimited value', newValue, $input);
  8771. }
  8772. if(settings.fireOnInit === false && module.is.initialLoad()) {
  8773. module.verbose('Skipping onadd callback on initial load', settings.onAdd);
  8774. }
  8775. else {
  8776. settings.onAdd.call(element, addedValue, addedText, $selectedItem);
  8777. }
  8778. module.set.value(newValue, addedText, $selectedItem);
  8779. module.check.maxSelections();
  8780. },
  8781. },
  8782. remove: {
  8783. active: function() {
  8784. $module.removeClass(className.active);
  8785. },
  8786. activeLabel: function() {
  8787. $module.find(selector.label).removeClass(className.active);
  8788. },
  8789. empty: function() {
  8790. $module.removeClass(className.empty);
  8791. },
  8792. loading: function() {
  8793. $module.removeClass(className.loading);
  8794. },
  8795. initialLoad: function() {
  8796. initialLoad = false;
  8797. },
  8798. upward: function($currentMenu) {
  8799. var $element = $currentMenu || $module;
  8800. $element.removeClass(className.upward);
  8801. },
  8802. leftward: function($currentMenu) {
  8803. var $element = $currentMenu || $menu;
  8804. $element.removeClass(className.leftward);
  8805. },
  8806. visible: function() {
  8807. $module.removeClass(className.visible);
  8808. },
  8809. activeItem: function() {
  8810. $item.removeClass(className.active);
  8811. },
  8812. filteredItem: function() {
  8813. if(settings.useLabels && module.has.maxSelections() ) {
  8814. return;
  8815. }
  8816. if(settings.useLabels && module.is.multiple()) {
  8817. $item.not('.' + className.active).removeClass(className.filtered);
  8818. }
  8819. else {
  8820. $item.removeClass(className.filtered);
  8821. }
  8822. if(settings.hideDividers) {
  8823. $divider.removeClass(className.hidden);
  8824. }
  8825. module.remove.empty();
  8826. },
  8827. optionValue: function(value) {
  8828. var
  8829. escapedValue = module.escape.value(value),
  8830. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  8831. hasOption = ($option.length > 0)
  8832. ;
  8833. if(!hasOption || !$option.hasClass(className.addition)) {
  8834. return;
  8835. }
  8836. // temporarily disconnect observer
  8837. if(selectObserver) {
  8838. selectObserver.disconnect();
  8839. module.verbose('Temporarily disconnecting mutation observer');
  8840. }
  8841. $option.remove();
  8842. module.verbose('Removing user addition as an <option>', escapedValue);
  8843. if(selectObserver) {
  8844. selectObserver.observe($input[0], {
  8845. childList : true,
  8846. subtree : true
  8847. });
  8848. }
  8849. },
  8850. message: function() {
  8851. $menu.children(selector.message).remove();
  8852. },
  8853. searchWidth: function() {
  8854. $search.css('width', '');
  8855. },
  8856. searchTerm: function() {
  8857. module.verbose('Cleared search term');
  8858. $search.val('');
  8859. module.set.filtered();
  8860. },
  8861. userAddition: function() {
  8862. $item.filter(selector.addition).remove();
  8863. },
  8864. selected: function(value, $selectedItem) {
  8865. $selectedItem = (settings.allowAdditions)
  8866. ? $selectedItem || module.get.itemWithAdditions(value)
  8867. : $selectedItem || module.get.item(value)
  8868. ;
  8869. if(!$selectedItem) {
  8870. return false;
  8871. }
  8872. $selectedItem
  8873. .each(function() {
  8874. var
  8875. $selected = $(this),
  8876. selectedText = module.get.choiceText($selected),
  8877. selectedValue = module.get.choiceValue($selected, selectedText)
  8878. ;
  8879. if(module.is.multiple()) {
  8880. if(settings.useLabels) {
  8881. module.remove.value(selectedValue, selectedText, $selected);
  8882. module.remove.label(selectedValue);
  8883. }
  8884. else {
  8885. module.remove.value(selectedValue, selectedText, $selected);
  8886. if(module.get.selectionCount() === 0) {
  8887. module.set.placeholderText();
  8888. }
  8889. else {
  8890. module.set.text(module.add.variables(message.count));
  8891. }
  8892. }
  8893. }
  8894. else {
  8895. module.remove.value(selectedValue, selectedText, $selected);
  8896. }
  8897. $selected
  8898. .removeClass(className.filtered)
  8899. .removeClass(className.active)
  8900. ;
  8901. if(settings.useLabels) {
  8902. $selected.removeClass(className.selected);
  8903. }
  8904. })
  8905. ;
  8906. },
  8907. selectedItem: function() {
  8908. $item.removeClass(className.selected);
  8909. },
  8910. value: function(removedValue, removedText, $removedItem) {
  8911. var
  8912. values = module.get.values(),
  8913. newValue
  8914. ;
  8915. removedValue = module.escape.htmlEntities(removedValue);
  8916. if( module.has.selectInput() ) {
  8917. module.verbose('Input is <select> removing selected option', removedValue);
  8918. newValue = module.remove.arrayValue(removedValue, values);
  8919. module.remove.optionValue(removedValue);
  8920. }
  8921. else {
  8922. module.verbose('Removing from delimited values', removedValue);
  8923. newValue = module.remove.arrayValue(removedValue, values);
  8924. newValue = newValue.join(settings.delimiter);
  8925. }
  8926. if(settings.fireOnInit === false && module.is.initialLoad()) {
  8927. module.verbose('No callback on initial load', settings.onRemove);
  8928. }
  8929. else {
  8930. settings.onRemove.call(element, removedValue, removedText, $removedItem);
  8931. }
  8932. module.set.value(newValue, removedText, $removedItem);
  8933. module.check.maxSelections();
  8934. },
  8935. arrayValue: function(removedValue, values) {
  8936. if( !Array.isArray(values) ) {
  8937. values = [values];
  8938. }
  8939. values = $.grep(values, function(value){
  8940. return (removedValue != value);
  8941. });
  8942. module.verbose('Removed value from delimited string', removedValue, values);
  8943. return values;
  8944. },
  8945. label: function(value, shouldAnimate) {
  8946. var
  8947. $labels = $module.find(selector.label),
  8948. $removedLabel = $labels.filter('[data-' + metadata.value + '="' + module.escape.string(settings.ignoreCase ? value.toLowerCase() : value) +'"]')
  8949. ;
  8950. module.verbose('Removing label', $removedLabel);
  8951. $removedLabel.remove();
  8952. },
  8953. activeLabels: function($activeLabels) {
  8954. $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
  8955. module.verbose('Removing active label selections', $activeLabels);
  8956. module.remove.labels($activeLabels);
  8957. },
  8958. labels: function($labels) {
  8959. $labels = $labels || $module.find(selector.label);
  8960. module.verbose('Removing labels', $labels);
  8961. $labels
  8962. .each(function(){
  8963. var
  8964. $label = $(this),
  8965. value = $label.data(metadata.value),
  8966. stringValue = (value !== undefined)
  8967. ? String(value)
  8968. : value,
  8969. isUserValue = module.is.userValue(stringValue)
  8970. ;
  8971. if(settings.onLabelRemove.call($label, value) === false) {
  8972. module.debug('Label remove callback cancelled removal');
  8973. return;
  8974. }
  8975. module.remove.message();
  8976. if(isUserValue) {
  8977. module.remove.value(stringValue);
  8978. module.remove.label(stringValue);
  8979. }
  8980. else {
  8981. // selected will also remove label
  8982. module.remove.selected(stringValue);
  8983. }
  8984. })
  8985. ;
  8986. },
  8987. tabbable: function() {
  8988. if( module.is.searchSelection() ) {
  8989. module.debug('Searchable dropdown initialized');
  8990. $search
  8991. .removeAttr('tabindex')
  8992. ;
  8993. $menu
  8994. .removeAttr('tabindex')
  8995. ;
  8996. }
  8997. else {
  8998. module.debug('Simple selection dropdown initialized');
  8999. $module
  9000. .removeAttr('tabindex')
  9001. ;
  9002. $menu
  9003. .removeAttr('tabindex')
  9004. ;
  9005. }
  9006. },
  9007. diacritics: function(text) {
  9008. return settings.ignoreDiacritics ? text.normalize('NFD').replace(/[\u0300-\u036f]/g, '') : text;
  9009. }
  9010. },
  9011. has: {
  9012. menuSearch: function() {
  9013. return (module.has.search() && $search.closest($menu).length > 0);
  9014. },
  9015. clearItem: function() {
  9016. return ($clear.length > 0);
  9017. },
  9018. search: function() {
  9019. return ($search.length > 0);
  9020. },
  9021. sizer: function() {
  9022. return ($sizer.length > 0);
  9023. },
  9024. selectInput: function() {
  9025. return ( $input.is('select') );
  9026. },
  9027. minCharacters: function(searchTerm) {
  9028. if(settings.minCharacters && !iconClicked) {
  9029. searchTerm = (searchTerm !== undefined)
  9030. ? String(searchTerm)
  9031. : String(module.get.query())
  9032. ;
  9033. return (searchTerm.length >= settings.minCharacters);
  9034. }
  9035. iconClicked=false;
  9036. return true;
  9037. },
  9038. firstLetter: function($item, letter) {
  9039. var
  9040. text,
  9041. firstLetter
  9042. ;
  9043. if(!$item || $item.length === 0 || typeof letter !== 'string') {
  9044. return false;
  9045. }
  9046. text = module.get.choiceText($item, false);
  9047. letter = letter.toLowerCase();
  9048. firstLetter = String(text).charAt(0).toLowerCase();
  9049. return (letter == firstLetter);
  9050. },
  9051. input: function() {
  9052. return ($input.length > 0);
  9053. },
  9054. items: function() {
  9055. return ($item.length > 0);
  9056. },
  9057. menu: function() {
  9058. return ($menu.length > 0);
  9059. },
  9060. message: function() {
  9061. return ($menu.children(selector.message).length !== 0);
  9062. },
  9063. label: function(value) {
  9064. var
  9065. escapedValue = module.escape.value(value),
  9066. $labels = $module.find(selector.label)
  9067. ;
  9068. if(settings.ignoreCase) {
  9069. escapedValue = escapedValue.toLowerCase();
  9070. }
  9071. return ($labels.filter('[data-' + metadata.value + '="' + module.escape.string(escapedValue) +'"]').length > 0);
  9072. },
  9073. maxSelections: function() {
  9074. return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
  9075. },
  9076. allResultsFiltered: function() {
  9077. var
  9078. $normalResults = $item.not(selector.addition)
  9079. ;
  9080. return ($normalResults.filter(selector.unselectable).length === $normalResults.length);
  9081. },
  9082. userSuggestion: function() {
  9083. return ($menu.children(selector.addition).length > 0);
  9084. },
  9085. query: function() {
  9086. return (module.get.query() !== '');
  9087. },
  9088. value: function(value) {
  9089. return (settings.ignoreCase)
  9090. ? module.has.valueIgnoringCase(value)
  9091. : module.has.valueMatchingCase(value)
  9092. ;
  9093. },
  9094. valueMatchingCase: function(value) {
  9095. var
  9096. values = module.get.values(),
  9097. hasValue = Array.isArray(values)
  9098. ? values && ($.inArray(value, values) !== -1)
  9099. : (values == value)
  9100. ;
  9101. return (hasValue)
  9102. ? true
  9103. : false
  9104. ;
  9105. },
  9106. valueIgnoringCase: function(value) {
  9107. var
  9108. values = module.get.values(),
  9109. hasValue = false
  9110. ;
  9111. if(!Array.isArray(values)) {
  9112. values = [values];
  9113. }
  9114. $.each(values, function(index, existingValue) {
  9115. if(String(value).toLowerCase() == String(existingValue).toLowerCase()) {
  9116. hasValue = true;
  9117. return false;
  9118. }
  9119. });
  9120. return hasValue;
  9121. }
  9122. },
  9123. is: {
  9124. active: function() {
  9125. return $module.hasClass(className.active);
  9126. },
  9127. animatingInward: function() {
  9128. return $menu.transition('is inward');
  9129. },
  9130. animatingOutward: function() {
  9131. return $menu.transition('is outward');
  9132. },
  9133. bubbledLabelClick: function(event) {
  9134. return $(event.target).is('select, input') && $module.closest('label').length > 0;
  9135. },
  9136. bubbledIconClick: function(event) {
  9137. return $(event.target).closest($icon).length > 0;
  9138. },
  9139. alreadySetup: function() {
  9140. return ($module.is('select') && $module.parent(selector.dropdown).data(moduleNamespace) !== undefined && $module.prev().length === 0);
  9141. },
  9142. animating: function($subMenu) {
  9143. return ($subMenu)
  9144. ? $subMenu.transition && $subMenu.transition('is animating')
  9145. : $menu.transition && $menu.transition('is animating')
  9146. ;
  9147. },
  9148. leftward: function($subMenu) {
  9149. var $selectedMenu = $subMenu || $menu;
  9150. return $selectedMenu.hasClass(className.leftward);
  9151. },
  9152. clearable: function() {
  9153. return ($module.hasClass(className.clearable) || settings.clearable);
  9154. },
  9155. disabled: function() {
  9156. return $module.hasClass(className.disabled);
  9157. },
  9158. focused: function() {
  9159. return (document.activeElement === $module[0]);
  9160. },
  9161. focusedOnSearch: function() {
  9162. return (document.activeElement === $search[0]);
  9163. },
  9164. allFiltered: function() {
  9165. return( (module.is.multiple() || module.has.search()) && !(settings.hideAdditions == false && module.has.userSuggestion()) && !module.has.message() && module.has.allResultsFiltered() );
  9166. },
  9167. hidden: function($subMenu) {
  9168. return !module.is.visible($subMenu);
  9169. },
  9170. initialLoad: function() {
  9171. return initialLoad;
  9172. },
  9173. inObject: function(needle, object) {
  9174. var
  9175. found = false
  9176. ;
  9177. $.each(object, function(index, property) {
  9178. if(property == needle) {
  9179. found = true;
  9180. return true;
  9181. }
  9182. });
  9183. return found;
  9184. },
  9185. multiple: function() {
  9186. return $module.hasClass(className.multiple);
  9187. },
  9188. remote: function() {
  9189. return settings.apiSettings && module.can.useAPI();
  9190. },
  9191. single: function() {
  9192. return !module.is.multiple();
  9193. },
  9194. selectMutation: function(mutations) {
  9195. var
  9196. selectChanged = false
  9197. ;
  9198. $.each(mutations, function(index, mutation) {
  9199. if($(mutation.target).is('select') || $(mutation.addedNodes).is('select')) {
  9200. selectChanged = true;
  9201. return false;
  9202. }
  9203. });
  9204. return selectChanged;
  9205. },
  9206. search: function() {
  9207. return $module.hasClass(className.search);
  9208. },
  9209. searchSelection: function() {
  9210. return ( module.has.search() && $search.parent(selector.dropdown).length === 1 );
  9211. },
  9212. selection: function() {
  9213. return $module.hasClass(className.selection);
  9214. },
  9215. userValue: function(value) {
  9216. return ($.inArray(value, module.get.userValues()) !== -1);
  9217. },
  9218. upward: function($menu) {
  9219. var $element = $menu || $module;
  9220. return $element.hasClass(className.upward);
  9221. },
  9222. visible: function($subMenu) {
  9223. return ($subMenu)
  9224. ? $subMenu.hasClass(className.visible)
  9225. : $menu.hasClass(className.visible)
  9226. ;
  9227. },
  9228. verticallyScrollableContext: function() {
  9229. var
  9230. overflowY = ($context.get(0) !== window)
  9231. ? $context.css('overflow-y')
  9232. : false
  9233. ;
  9234. return (overflowY == 'auto' || overflowY == 'scroll');
  9235. },
  9236. horizontallyScrollableContext: function() {
  9237. var
  9238. overflowX = ($context.get(0) !== window)
  9239. ? $context.css('overflow-X')
  9240. : false
  9241. ;
  9242. return (overflowX == 'auto' || overflowX == 'scroll');
  9243. }
  9244. },
  9245. can: {
  9246. activate: function($item) {
  9247. if(settings.useLabels) {
  9248. return true;
  9249. }
  9250. if(!module.has.maxSelections()) {
  9251. return true;
  9252. }
  9253. if(module.has.maxSelections() && $item.hasClass(className.active)) {
  9254. return true;
  9255. }
  9256. return false;
  9257. },
  9258. openDownward: function($subMenu) {
  9259. var
  9260. $currentMenu = $subMenu || $menu,
  9261. canOpenDownward = true,
  9262. onScreen = {},
  9263. calculations
  9264. ;
  9265. $currentMenu
  9266. .addClass(className.loading)
  9267. ;
  9268. calculations = {
  9269. context: {
  9270. offset : ($context.get(0) === window)
  9271. ? { top: 0, left: 0}
  9272. : $context.offset(),
  9273. scrollTop : $context.scrollTop(),
  9274. height : $context.outerHeight()
  9275. },
  9276. menu : {
  9277. offset: $currentMenu.offset(),
  9278. height: $currentMenu.outerHeight()
  9279. }
  9280. };
  9281. if(module.is.verticallyScrollableContext()) {
  9282. calculations.menu.offset.top += calculations.context.scrollTop;
  9283. }
  9284. onScreen = {
  9285. above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.context.offset.top - calculations.menu.height,
  9286. below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top - calculations.context.offset.top + calculations.menu.height
  9287. };
  9288. if(onScreen.below) {
  9289. module.verbose('Dropdown can fit in context downward', onScreen);
  9290. canOpenDownward = true;
  9291. }
  9292. else if(!onScreen.below && !onScreen.above) {
  9293. module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
  9294. canOpenDownward = true;
  9295. }
  9296. else {
  9297. module.verbose('Dropdown cannot fit below, opening upward', onScreen);
  9298. canOpenDownward = false;
  9299. }
  9300. $currentMenu.removeClass(className.loading);
  9301. return canOpenDownward;
  9302. },
  9303. openRightward: function($subMenu) {
  9304. var
  9305. $currentMenu = $subMenu || $menu,
  9306. canOpenRightward = true,
  9307. isOffscreenRight = false,
  9308. calculations
  9309. ;
  9310. $currentMenu
  9311. .addClass(className.loading)
  9312. ;
  9313. calculations = {
  9314. context: {
  9315. offset : ($context.get(0) === window)
  9316. ? { top: 0, left: 0}
  9317. : $context.offset(),
  9318. scrollLeft : $context.scrollLeft(),
  9319. width : $context.outerWidth()
  9320. },
  9321. menu: {
  9322. offset : $currentMenu.offset(),
  9323. width : $currentMenu.outerWidth()
  9324. }
  9325. };
  9326. if(module.is.horizontallyScrollableContext()) {
  9327. calculations.menu.offset.left += calculations.context.scrollLeft;
  9328. }
  9329. isOffscreenRight = (calculations.menu.offset.left - calculations.context.offset.left + calculations.menu.width >= calculations.context.scrollLeft + calculations.context.width);
  9330. if(isOffscreenRight) {
  9331. module.verbose('Dropdown cannot fit in context rightward', isOffscreenRight);
  9332. canOpenRightward = false;
  9333. }
  9334. $currentMenu.removeClass(className.loading);
  9335. return canOpenRightward;
  9336. },
  9337. click: function() {
  9338. return (hasTouch || settings.on == 'click');
  9339. },
  9340. extendSelect: function() {
  9341. return settings.allowAdditions || settings.apiSettings;
  9342. },
  9343. show: function() {
  9344. return !module.is.disabled() && (module.has.items() || module.has.message());
  9345. },
  9346. useAPI: function() {
  9347. return $.fn.api !== undefined;
  9348. }
  9349. },
  9350. animate: {
  9351. show: function(callback, $subMenu) {
  9352. var
  9353. $currentMenu = $subMenu || $menu,
  9354. start = ($subMenu)
  9355. ? function() {}
  9356. : function() {
  9357. module.hideSubMenus();
  9358. module.hideOthers();
  9359. module.set.active();
  9360. },
  9361. transition
  9362. ;
  9363. callback = $.isFunction(callback)
  9364. ? callback
  9365. : function(){}
  9366. ;
  9367. module.verbose('Doing menu show animation', $currentMenu);
  9368. module.set.direction($subMenu);
  9369. transition = module.get.transition($subMenu);
  9370. if( module.is.selection() ) {
  9371. module.set.scrollPosition(module.get.selectedItem(), true);
  9372. }
  9373. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  9374. if(transition == 'none') {
  9375. start();
  9376. $currentMenu.transition('show');
  9377. callback.call(element);
  9378. }
  9379. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  9380. $currentMenu
  9381. .transition({
  9382. animation : transition + ' in',
  9383. debug : settings.debug,
  9384. verbose : settings.verbose,
  9385. duration : settings.duration,
  9386. queue : true,
  9387. onStart : start,
  9388. onComplete : function() {
  9389. callback.call(element);
  9390. }
  9391. })
  9392. ;
  9393. }
  9394. else {
  9395. module.error(error.noTransition, transition);
  9396. }
  9397. }
  9398. },
  9399. hide: function(callback, $subMenu) {
  9400. var
  9401. $currentMenu = $subMenu || $menu,
  9402. start = ($subMenu)
  9403. ? function() {}
  9404. : function() {
  9405. if( module.can.click() ) {
  9406. module.unbind.intent();
  9407. }
  9408. module.remove.active();
  9409. },
  9410. transition = module.get.transition($subMenu)
  9411. ;
  9412. callback = $.isFunction(callback)
  9413. ? callback
  9414. : function(){}
  9415. ;
  9416. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  9417. module.verbose('Doing menu hide animation', $currentMenu);
  9418. if(transition == 'none') {
  9419. start();
  9420. $currentMenu.transition('hide');
  9421. callback.call(element);
  9422. }
  9423. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  9424. $currentMenu
  9425. .transition({
  9426. animation : transition + ' out',
  9427. duration : settings.duration,
  9428. debug : settings.debug,
  9429. verbose : settings.verbose,
  9430. queue : false,
  9431. onStart : start,
  9432. onComplete : function() {
  9433. callback.call(element);
  9434. }
  9435. })
  9436. ;
  9437. }
  9438. else {
  9439. module.error(error.transition);
  9440. }
  9441. }
  9442. }
  9443. },
  9444. hideAndClear: function() {
  9445. module.remove.searchTerm();
  9446. if( module.has.maxSelections() ) {
  9447. return;
  9448. }
  9449. if(module.has.search()) {
  9450. module.hide(function() {
  9451. module.remove.filteredItem();
  9452. });
  9453. }
  9454. else {
  9455. module.hide();
  9456. }
  9457. },
  9458. delay: {
  9459. show: function() {
  9460. module.verbose('Delaying show event to ensure user intent');
  9461. clearTimeout(module.timer);
  9462. module.timer = setTimeout(module.show, settings.delay.show);
  9463. },
  9464. hide: function() {
  9465. module.verbose('Delaying hide event to ensure user intent');
  9466. clearTimeout(module.timer);
  9467. module.timer = setTimeout(module.hide, settings.delay.hide);
  9468. }
  9469. },
  9470. escape: {
  9471. value: function(value) {
  9472. var
  9473. multipleValues = Array.isArray(value),
  9474. stringValue = (typeof value === 'string'),
  9475. isUnparsable = (!stringValue && !multipleValues),
  9476. hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
  9477. values = []
  9478. ;
  9479. if(isUnparsable || !hasQuotes) {
  9480. return value;
  9481. }
  9482. module.debug('Encoding quote values for use in select', value);
  9483. if(multipleValues) {
  9484. $.each(value, function(index, value){
  9485. values.push(value.replace(regExp.quote, '&quot;'));
  9486. });
  9487. return values;
  9488. }
  9489. return value.replace(regExp.quote, '&quot;');
  9490. },
  9491. string: function(text) {
  9492. text = String(text);
  9493. return text.replace(regExp.escape, '\\$&');
  9494. },
  9495. htmlEntities: function(string) {
  9496. var
  9497. badChars = /[<>"'`]/g,
  9498. shouldEscape = /[&<>"'`]/,
  9499. escape = {
  9500. "<": "&lt;",
  9501. ">": "&gt;",
  9502. '"': "&quot;",
  9503. "'": "&#x27;",
  9504. "`": "&#x60;"
  9505. },
  9506. escapedChar = function(chr) {
  9507. return escape[chr];
  9508. }
  9509. ;
  9510. if(shouldEscape.test(string)) {
  9511. string = string.replace(/&(?![a-z0-9#]{1,6};)/, "&amp;");
  9512. return string.replace(badChars, escapedChar);
  9513. }
  9514. return string;
  9515. }
  9516. },
  9517. setting: function(name, value) {
  9518. module.debug('Changing setting', name, value);
  9519. if( $.isPlainObject(name) ) {
  9520. $.extend(true, settings, name);
  9521. }
  9522. else if(value !== undefined) {
  9523. if($.isPlainObject(settings[name])) {
  9524. $.extend(true, settings[name], value);
  9525. }
  9526. else {
  9527. settings[name] = value;
  9528. }
  9529. }
  9530. else {
  9531. return settings[name];
  9532. }
  9533. },
  9534. internal: function(name, value) {
  9535. if( $.isPlainObject(name) ) {
  9536. $.extend(true, module, name);
  9537. }
  9538. else if(value !== undefined) {
  9539. module[name] = value;
  9540. }
  9541. else {
  9542. return module[name];
  9543. }
  9544. },
  9545. debug: function() {
  9546. if(!settings.silent && settings.debug) {
  9547. if(settings.performance) {
  9548. module.performance.log(arguments);
  9549. }
  9550. else {
  9551. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9552. module.debug.apply(console, arguments);
  9553. }
  9554. }
  9555. },
  9556. verbose: function() {
  9557. if(!settings.silent && settings.verbose && settings.debug) {
  9558. if(settings.performance) {
  9559. module.performance.log(arguments);
  9560. }
  9561. else {
  9562. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9563. module.verbose.apply(console, arguments);
  9564. }
  9565. }
  9566. },
  9567. error: function() {
  9568. if(!settings.silent) {
  9569. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9570. module.error.apply(console, arguments);
  9571. }
  9572. },
  9573. performance: {
  9574. log: function(message) {
  9575. var
  9576. currentTime,
  9577. executionTime,
  9578. previousTime
  9579. ;
  9580. if(settings.performance) {
  9581. currentTime = new Date().getTime();
  9582. previousTime = time || currentTime;
  9583. executionTime = currentTime - previousTime;
  9584. time = currentTime;
  9585. performance.push({
  9586. 'Name' : message[0],
  9587. 'Arguments' : [].slice.call(message, 1) || '',
  9588. 'Element' : element,
  9589. 'Execution Time' : executionTime
  9590. });
  9591. }
  9592. clearTimeout(module.performance.timer);
  9593. module.performance.timer = setTimeout(module.performance.display, 500);
  9594. },
  9595. display: function() {
  9596. var
  9597. title = settings.name + ':',
  9598. totalTime = 0
  9599. ;
  9600. time = false;
  9601. clearTimeout(module.performance.timer);
  9602. $.each(performance, function(index, data) {
  9603. totalTime += data['Execution Time'];
  9604. });
  9605. title += ' ' + totalTime + 'ms';
  9606. if(moduleSelector) {
  9607. title += ' \'' + moduleSelector + '\'';
  9608. }
  9609. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9610. console.groupCollapsed(title);
  9611. if(console.table) {
  9612. console.table(performance);
  9613. }
  9614. else {
  9615. $.each(performance, function(index, data) {
  9616. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9617. });
  9618. }
  9619. console.groupEnd();
  9620. }
  9621. performance = [];
  9622. }
  9623. },
  9624. invoke: function(query, passedArguments, context) {
  9625. var
  9626. object = instance,
  9627. maxDepth,
  9628. found,
  9629. response
  9630. ;
  9631. passedArguments = passedArguments || queryArguments;
  9632. context = element || context;
  9633. if(typeof query == 'string' && object !== undefined) {
  9634. query = query.split(/[\. ]/);
  9635. maxDepth = query.length - 1;
  9636. $.each(query, function(depth, value) {
  9637. var camelCaseValue = (depth != maxDepth)
  9638. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9639. : query
  9640. ;
  9641. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9642. object = object[camelCaseValue];
  9643. }
  9644. else if( object[camelCaseValue] !== undefined ) {
  9645. found = object[camelCaseValue];
  9646. return false;
  9647. }
  9648. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9649. object = object[value];
  9650. }
  9651. else if( object[value] !== undefined ) {
  9652. found = object[value];
  9653. return false;
  9654. }
  9655. else {
  9656. module.error(error.method, query);
  9657. return false;
  9658. }
  9659. });
  9660. }
  9661. if ( $.isFunction( found ) ) {
  9662. response = found.apply(context, passedArguments);
  9663. }
  9664. else if(found !== undefined) {
  9665. response = found;
  9666. }
  9667. if(Array.isArray(returnedValue)) {
  9668. returnedValue.push(response);
  9669. }
  9670. else if(returnedValue !== undefined) {
  9671. returnedValue = [returnedValue, response];
  9672. }
  9673. else if(response !== undefined) {
  9674. returnedValue = response;
  9675. }
  9676. return found;
  9677. }
  9678. };
  9679. if(methodInvoked) {
  9680. if(instance === undefined) {
  9681. module.initialize();
  9682. }
  9683. module.invoke(query);
  9684. }
  9685. else {
  9686. if(instance !== undefined) {
  9687. instance.invoke('destroy');
  9688. }
  9689. module.initialize();
  9690. }
  9691. })
  9692. ;
  9693. return (returnedValue !== undefined)
  9694. ? returnedValue
  9695. : $allModules
  9696. ;
  9697. };
  9698. $.fn.dropdown.settings = {
  9699. silent : false,
  9700. debug : false,
  9701. verbose : false,
  9702. performance : true,
  9703. on : 'click', // what event should show menu action on item selection
  9704. action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
  9705. values : false, // specify values to use for dropdown
  9706. clearable : false, // whether the value of the dropdown can be cleared
  9707. apiSettings : false,
  9708. selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
  9709. minCharacters : 0, // Minimum characters required to trigger API call
  9710. filterRemoteData : false, // Whether API results should be filtered after being returned for query term
  9711. saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
  9712. throttle : 200, // How long to wait after last user input to search remotely
  9713. context : window, // Context to use when determining if on screen
  9714. direction : 'auto', // Whether dropdown should always open in one direction
  9715. keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
  9716. match : 'both', // what to match against with search selection (both, text, or label)
  9717. fullTextSearch : false, // search anywhere in value (set to 'exact' to require exact matches)
  9718. ignoreDiacritics : false, // match results also if they contain diacritics of the same base character (for example searching for "a" will also match "á" or "â" or "à", etc...)
  9719. hideDividers : false, // Whether to hide any divider elements (specified in selector.divider) that are sibling to any items when searched (set to true will hide all dividers, set to 'empty' will hide them when they are not followed by a visible item)
  9720. placeholder : 'auto', // whether to convert blank <select> values to placeholder text
  9721. preserveHTML : true, // preserve html when selecting value
  9722. sortSelect : false, // sort selection on init
  9723. forceSelection : true, // force a choice on blur with search selection
  9724. allowAdditions : false, // whether multiple select should allow user added values
  9725. ignoreCase : false, // whether to consider case sensitivity when creating labels
  9726. ignoreSearchCase : true, // whether to consider case sensitivity when filtering items
  9727. hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
  9728. maxSelections : false, // When set to a number limits the number of selections to this count
  9729. useLabels : true, // whether multiple select should filter currently active selections from choices
  9730. delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
  9731. showOnFocus : true, // show menu on focus
  9732. allowReselection : false, // whether current value should trigger callbacks when reselected
  9733. allowTab : true, // add tabindex to element
  9734. allowCategorySelection : false, // allow elements with sub-menus to be selected
  9735. fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
  9736. transition : 'auto', // auto transition will slide down or up based on direction
  9737. duration : 200, // duration of transition
  9738. glyphWidth : 1.037, // widest glyph width in em (W is 1.037 em) used to calculate multiselect input width
  9739. headerDivider : true, // whether option headers should have an additional divider line underneath when converted from <select> <optgroup>
  9740. // label settings on multi-select
  9741. label: {
  9742. transition : 'scale',
  9743. duration : 200,
  9744. variation : false
  9745. },
  9746. // delay before event
  9747. delay : {
  9748. hide : 300,
  9749. show : 200,
  9750. search : 20,
  9751. touch : 50
  9752. },
  9753. /* Callbacks */
  9754. onChange : function(value, text, $selected){},
  9755. onAdd : function(value, text, $selected){},
  9756. onRemove : function(value, text, $selected){},
  9757. onLabelSelect : function($selectedLabels){},
  9758. onLabelCreate : function(value, text) { return $(this); },
  9759. onLabelRemove : function(value) { return true; },
  9760. onNoResults : function(searchTerm) { return true; },
  9761. onShow : function(){},
  9762. onHide : function(){},
  9763. /* Component */
  9764. name : 'Dropdown',
  9765. namespace : 'dropdown',
  9766. message: {
  9767. addResult : 'Add <b>{term}</b>',
  9768. count : '{count} selected',
  9769. maxSelections : 'Max {maxCount} selections',
  9770. noResults : 'No results found.',
  9771. serverError : 'There was an error contacting the server'
  9772. },
  9773. error : {
  9774. action : 'You called a dropdown action that was not defined',
  9775. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  9776. labels : 'Allowing user additions currently requires the use of labels.',
  9777. missingMultiple : '<select> requires multiple property to be set to correctly preserve multiple values',
  9778. method : 'The method you called is not defined.',
  9779. noAPI : 'The API module is required to load resources remotely',
  9780. noStorage : 'Saving remote data requires session storage',
  9781. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  9782. noNormalize : '"ignoreDiacritics" setting will be ignored. Browser does not support String().normalize(). You may consider including <https://cdn.jsdelivr.net/npm/[email protected]/lib/unorm.min.js> as a polyfill.'
  9783. },
  9784. regExp : {
  9785. escape : /[-[\]{}()*+?.,\\^$|#\s:=@]/g,
  9786. quote : /"/g
  9787. },
  9788. metadata : {
  9789. defaultText : 'defaultText',
  9790. defaultValue : 'defaultValue',
  9791. placeholderText : 'placeholder',
  9792. text : 'text',
  9793. value : 'value'
  9794. },
  9795. // property names for remote query
  9796. fields: {
  9797. remoteValues : 'results', // grouping for api results
  9798. values : 'values', // grouping for all dropdown values
  9799. disabled : 'disabled', // whether value should be disabled
  9800. name : 'name', // displayed dropdown text
  9801. value : 'value', // actual dropdown value
  9802. text : 'text', // displayed text when selected
  9803. type : 'type', // type of dropdown element
  9804. image : 'image', // optional image path
  9805. imageClass : 'imageClass', // optional individual class for image
  9806. icon : 'icon', // optional icon name
  9807. iconClass : 'iconClass', // optional individual class for icon (for example to use flag instead)
  9808. class : 'class', // optional individual class for item/header
  9809. divider : 'divider' // optional divider append for group headers
  9810. },
  9811. keys : {
  9812. backspace : 8,
  9813. delimiter : 188, // comma
  9814. deleteKey : 46,
  9815. enter : 13,
  9816. escape : 27,
  9817. pageUp : 33,
  9818. pageDown : 34,
  9819. leftArrow : 37,
  9820. upArrow : 38,
  9821. rightArrow : 39,
  9822. downArrow : 40
  9823. },
  9824. selector : {
  9825. addition : '.addition',
  9826. divider : '.divider, .header',
  9827. dropdown : '.ui.dropdown',
  9828. hidden : '.hidden',
  9829. icon : '> .dropdown.icon',
  9830. input : '> input[type="hidden"], > select',
  9831. item : '.item',
  9832. label : '> .label',
  9833. remove : '> .label > .delete.icon',
  9834. siblingLabel : '.label',
  9835. menu : '.menu',
  9836. message : '.message',
  9837. menuIcon : '.dropdown.icon',
  9838. search : 'input.search, .menu > .search > input, .menu input.search',
  9839. sizer : '> input.sizer',
  9840. text : '> .text:not(.icon)',
  9841. unselectable : '.disabled, .filtered',
  9842. clearIcon : '> .remove.icon'
  9843. },
  9844. className : {
  9845. active : 'active',
  9846. addition : 'addition',
  9847. animating : 'animating',
  9848. disabled : 'disabled',
  9849. empty : 'empty',
  9850. dropdown : 'ui dropdown',
  9851. filtered : 'filtered',
  9852. hidden : 'hidden transition',
  9853. icon : 'icon',
  9854. image : 'image',
  9855. item : 'item',
  9856. label : 'ui label',
  9857. loading : 'loading',
  9858. menu : 'menu',
  9859. message : 'message',
  9860. multiple : 'multiple',
  9861. placeholder : 'default',
  9862. sizer : 'sizer',
  9863. search : 'search',
  9864. selected : 'selected',
  9865. selection : 'selection',
  9866. upward : 'upward',
  9867. leftward : 'left',
  9868. visible : 'visible',
  9869. clearable : 'clearable',
  9870. noselection : 'noselection',
  9871. delete : 'delete',
  9872. header : 'header',
  9873. divider : 'divider',
  9874. groupIcon : '',
  9875. unfilterable : 'unfilterable'
  9876. }
  9877. };
  9878. /* Templates */
  9879. $.fn.dropdown.settings.templates = {
  9880. deQuote: function(string) {
  9881. return String(string).replace(/"/g,"");
  9882. },
  9883. escape: function(string, preserveHTML) {
  9884. if (preserveHTML){
  9885. return string;
  9886. }
  9887. var
  9888. badChars = /[<>"'`]/g,
  9889. shouldEscape = /[&<>"'`]/,
  9890. escape = {
  9891. "<": "&lt;",
  9892. ">": "&gt;",
  9893. '"': "&quot;",
  9894. "'": "&#x27;",
  9895. "`": "&#x60;"
  9896. },
  9897. escapedChar = function(chr) {
  9898. return escape[chr];
  9899. }
  9900. ;
  9901. if(shouldEscape.test(string)) {
  9902. string = string.replace(/&(?![a-z0-9#]{1,6};)/, "&amp;");
  9903. return string.replace(badChars, escapedChar);
  9904. }
  9905. return string;
  9906. },
  9907. // generates dropdown from select values
  9908. dropdown: function(select, fields, preserveHTML, className) {
  9909. var
  9910. placeholder = select.placeholder || false,
  9911. html = '',
  9912. escape = $.fn.dropdown.settings.templates.escape
  9913. ;
  9914. html += '<i class="dropdown icon"></i>';
  9915. if(placeholder) {
  9916. html += '<div class="default text">' + escape(placeholder,preserveHTML) + '</div>';
  9917. }
  9918. else {
  9919. html += '<div class="text"></div>';
  9920. }
  9921. html += '<div class="'+className.menu+'">';
  9922. html += $.fn.dropdown.settings.templates.menu(select, fields, preserveHTML,className);
  9923. html += '</div>';
  9924. return html;
  9925. },
  9926. // generates just menu from select
  9927. menu: function(response, fields, preserveHTML, className) {
  9928. var
  9929. values = response[fields.values] || [],
  9930. html = '',
  9931. escape = $.fn.dropdown.settings.templates.escape,
  9932. deQuote = $.fn.dropdown.settings.templates.deQuote
  9933. ;
  9934. $.each(values, function(index, option) {
  9935. var
  9936. itemType = (option[fields.type])
  9937. ? option[fields.type]
  9938. : 'item'
  9939. ;
  9940. if( itemType === 'item' ) {
  9941. var
  9942. maybeText = (option[fields.text])
  9943. ? ' data-text="' + deQuote(option[fields.text]) + '"'
  9944. : '',
  9945. maybeDisabled = (option[fields.disabled])
  9946. ? className.disabled+' '
  9947. : ''
  9948. ;
  9949. html += '<div class="'+ maybeDisabled + (option[fields.class] ? deQuote(option[fields.class]) : className.item)+'" data-value="' + deQuote(option[fields.value]) + '"' + maybeText + '>';
  9950. if(option[fields.image]) {
  9951. html += '<img class="'+(option[fields.imageClass] ? deQuote(option[fields.imageClass]) : className.image)+'" src="' + deQuote(option[fields.image]) + '">';
  9952. }
  9953. if(option[fields.icon]) {
  9954. html += '<i class="'+deQuote(option[fields.icon])+' '+(option[fields.iconClass] ? deQuote(option[fields.iconClass]) : className.icon)+'"></i>';
  9955. }
  9956. html += escape(option[fields.name] || '', preserveHTML);
  9957. html += '</div>';
  9958. } else if (itemType === 'header') {
  9959. var groupName = escape(option[fields.name] || '', preserveHTML),
  9960. groupIcon = option[fields.icon] ? deQuote(option[fields.icon]) : className.groupIcon
  9961. ;
  9962. if(groupName !== '' || groupIcon !== '') {
  9963. html += '<div class="' + (option[fields.class] ? deQuote(option[fields.class]) : className.header) + '">';
  9964. if (groupIcon !== '') {
  9965. html += '<i class="' + groupIcon + ' ' + (option[fields.iconClass] ? deQuote(option[fields.iconClass]) : className.icon) + '"></i>';
  9966. }
  9967. html += groupName;
  9968. html += '</div>';
  9969. }
  9970. if(option[fields.divider]){
  9971. html += '<div class="'+className.divider+'"></div>';
  9972. }
  9973. }
  9974. });
  9975. return html;
  9976. },
  9977. // generates label for multiselect
  9978. label: function(value, text, preserveHTML, className) {
  9979. var
  9980. escape = $.fn.dropdown.settings.templates.escape;
  9981. return escape(text,preserveHTML) + '<i class="'+className.delete+' icon"></i>';
  9982. },
  9983. // generates messages like "No results"
  9984. message: function(message) {
  9985. return message;
  9986. },
  9987. // generates user addition to selection menu
  9988. addition: function(choice) {
  9989. return choice;
  9990. }
  9991. };
  9992. })( jQuery, window, document );
  9993. /*!
  9994. * # Fomantic-UI - Embed
  9995. * http://github.com/fomantic/Fomantic-UI/
  9996. *
  9997. *
  9998. * Released under the MIT license
  9999. * http://opensource.org/licenses/MIT
  10000. *
  10001. */
  10002. ;(function ($, window, document, undefined) {
  10003. "use strict";
  10004. $.isFunction = $.isFunction || function(obj) {
  10005. return typeof obj === "function" && typeof obj.nodeType !== "number";
  10006. };
  10007. window = (typeof window != 'undefined' && window.Math == Math)
  10008. ? window
  10009. : (typeof self != 'undefined' && self.Math == Math)
  10010. ? self
  10011. : Function('return this')()
  10012. ;
  10013. $.fn.embed = function(parameters) {
  10014. var
  10015. $allModules = $(this),
  10016. moduleSelector = $allModules.selector || '',
  10017. time = new Date().getTime(),
  10018. performance = [],
  10019. query = arguments[0],
  10020. methodInvoked = (typeof query == 'string'),
  10021. queryArguments = [].slice.call(arguments, 1),
  10022. returnedValue
  10023. ;
  10024. $allModules
  10025. .each(function() {
  10026. var
  10027. settings = ( $.isPlainObject(parameters) )
  10028. ? $.extend(true, {}, $.fn.embed.settings, parameters)
  10029. : $.extend({}, $.fn.embed.settings),
  10030. selector = settings.selector,
  10031. className = settings.className,
  10032. sources = settings.sources,
  10033. error = settings.error,
  10034. metadata = settings.metadata,
  10035. namespace = settings.namespace,
  10036. templates = settings.templates,
  10037. eventNamespace = '.' + namespace,
  10038. moduleNamespace = 'module-' + namespace,
  10039. $module = $(this),
  10040. $placeholder = $module.find(selector.placeholder),
  10041. $icon = $module.find(selector.icon),
  10042. $embed = $module.find(selector.embed),
  10043. element = this,
  10044. instance = $module.data(moduleNamespace),
  10045. module
  10046. ;
  10047. module = {
  10048. initialize: function() {
  10049. module.debug('Initializing embed');
  10050. module.determine.autoplay();
  10051. module.create();
  10052. module.bind.events();
  10053. module.instantiate();
  10054. },
  10055. instantiate: function() {
  10056. module.verbose('Storing instance of module', module);
  10057. instance = module;
  10058. $module
  10059. .data(moduleNamespace, module)
  10060. ;
  10061. },
  10062. destroy: function() {
  10063. module.verbose('Destroying previous instance of embed');
  10064. module.reset();
  10065. $module
  10066. .removeData(moduleNamespace)
  10067. .off(eventNamespace)
  10068. ;
  10069. },
  10070. refresh: function() {
  10071. module.verbose('Refreshing selector cache');
  10072. $placeholder = $module.find(selector.placeholder);
  10073. $icon = $module.find(selector.icon);
  10074. $embed = $module.find(selector.embed);
  10075. },
  10076. bind: {
  10077. events: function() {
  10078. if( module.has.placeholder() ) {
  10079. module.debug('Adding placeholder events');
  10080. $module
  10081. .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
  10082. .on('click' + eventNamespace, selector.icon, module.createAndShow)
  10083. ;
  10084. }
  10085. }
  10086. },
  10087. create: function() {
  10088. var
  10089. placeholder = module.get.placeholder()
  10090. ;
  10091. if(placeholder) {
  10092. module.createPlaceholder();
  10093. }
  10094. else {
  10095. module.createAndShow();
  10096. }
  10097. },
  10098. createPlaceholder: function(placeholder) {
  10099. var
  10100. icon = module.get.icon(),
  10101. url = module.get.url(),
  10102. embed = module.generate.embed(url)
  10103. ;
  10104. placeholder = placeholder || module.get.placeholder();
  10105. $module.html( templates.placeholder(placeholder, icon) );
  10106. module.debug('Creating placeholder for embed', placeholder, icon);
  10107. },
  10108. createEmbed: function(url) {
  10109. module.refresh();
  10110. url = url || module.get.url();
  10111. $embed = $('<div/>')
  10112. .addClass(className.embed)
  10113. .html( module.generate.embed(url) )
  10114. .appendTo($module)
  10115. ;
  10116. settings.onCreate.call(element, url);
  10117. module.debug('Creating embed object', $embed);
  10118. },
  10119. changeEmbed: function(url) {
  10120. $embed
  10121. .html( module.generate.embed(url) )
  10122. ;
  10123. },
  10124. createAndShow: function() {
  10125. module.createEmbed();
  10126. module.show();
  10127. },
  10128. // sets new embed
  10129. change: function(source, id, url) {
  10130. module.debug('Changing video to ', source, id, url);
  10131. $module
  10132. .data(metadata.source, source)
  10133. .data(metadata.id, id)
  10134. ;
  10135. if(url) {
  10136. $module.data(metadata.url, url);
  10137. }
  10138. else {
  10139. $module.removeData(metadata.url);
  10140. }
  10141. if(module.has.embed()) {
  10142. module.changeEmbed();
  10143. }
  10144. else {
  10145. module.create();
  10146. }
  10147. },
  10148. // clears embed
  10149. reset: function() {
  10150. module.debug('Clearing embed and showing placeholder');
  10151. module.remove.data();
  10152. module.remove.active();
  10153. module.remove.embed();
  10154. module.showPlaceholder();
  10155. settings.onReset.call(element);
  10156. },
  10157. // shows current embed
  10158. show: function() {
  10159. module.debug('Showing embed');
  10160. module.set.active();
  10161. settings.onDisplay.call(element);
  10162. },
  10163. hide: function() {
  10164. module.debug('Hiding embed');
  10165. module.showPlaceholder();
  10166. },
  10167. showPlaceholder: function() {
  10168. module.debug('Showing placeholder image');
  10169. module.remove.active();
  10170. settings.onPlaceholderDisplay.call(element);
  10171. },
  10172. get: {
  10173. id: function() {
  10174. return settings.id || $module.data(metadata.id);
  10175. },
  10176. placeholder: function() {
  10177. return settings.placeholder || $module.data(metadata.placeholder);
  10178. },
  10179. icon: function() {
  10180. return (settings.icon)
  10181. ? settings.icon
  10182. : ($module.data(metadata.icon) !== undefined)
  10183. ? $module.data(metadata.icon)
  10184. : module.determine.icon()
  10185. ;
  10186. },
  10187. source: function(url) {
  10188. return (settings.source)
  10189. ? settings.source
  10190. : ($module.data(metadata.source) !== undefined)
  10191. ? $module.data(metadata.source)
  10192. : module.determine.source()
  10193. ;
  10194. },
  10195. type: function() {
  10196. var source = module.get.source();
  10197. return (sources[source] !== undefined)
  10198. ? sources[source].type
  10199. : false
  10200. ;
  10201. },
  10202. url: function() {
  10203. return (settings.url)
  10204. ? settings.url
  10205. : ($module.data(metadata.url) !== undefined)
  10206. ? $module.data(metadata.url)
  10207. : module.determine.url()
  10208. ;
  10209. }
  10210. },
  10211. determine: {
  10212. autoplay: function() {
  10213. if(module.should.autoplay()) {
  10214. settings.autoplay = true;
  10215. }
  10216. },
  10217. source: function(url) {
  10218. var
  10219. matchedSource = false
  10220. ;
  10221. url = url || module.get.url();
  10222. if(url) {
  10223. $.each(sources, function(name, source) {
  10224. if(url.search(source.domain) !== -1) {
  10225. matchedSource = name;
  10226. return false;
  10227. }
  10228. });
  10229. }
  10230. return matchedSource;
  10231. },
  10232. icon: function() {
  10233. var
  10234. source = module.get.source()
  10235. ;
  10236. return (sources[source] !== undefined)
  10237. ? sources[source].icon
  10238. : false
  10239. ;
  10240. },
  10241. url: function() {
  10242. var
  10243. id = settings.id || $module.data(metadata.id),
  10244. source = settings.source || $module.data(metadata.source),
  10245. url
  10246. ;
  10247. url = (sources[source] !== undefined)
  10248. ? sources[source].url.replace('{id}', id)
  10249. : false
  10250. ;
  10251. if(url) {
  10252. $module.data(metadata.url, url);
  10253. }
  10254. return url;
  10255. }
  10256. },
  10257. set: {
  10258. active: function() {
  10259. $module.addClass(className.active);
  10260. }
  10261. },
  10262. remove: {
  10263. data: function() {
  10264. $module
  10265. .removeData(metadata.id)
  10266. .removeData(metadata.icon)
  10267. .removeData(metadata.placeholder)
  10268. .removeData(metadata.source)
  10269. .removeData(metadata.url)
  10270. ;
  10271. },
  10272. active: function() {
  10273. $module.removeClass(className.active);
  10274. },
  10275. embed: function() {
  10276. $embed.empty();
  10277. }
  10278. },
  10279. encode: {
  10280. parameters: function(parameters) {
  10281. var
  10282. urlString = [],
  10283. index
  10284. ;
  10285. for (index in parameters) {
  10286. urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
  10287. }
  10288. return urlString.join('&amp;');
  10289. }
  10290. },
  10291. generate: {
  10292. embed: function(url) {
  10293. module.debug('Generating embed html');
  10294. var
  10295. source = module.get.source(),
  10296. html,
  10297. parameters
  10298. ;
  10299. url = module.get.url(url);
  10300. if(url) {
  10301. parameters = module.generate.parameters(source);
  10302. html = templates.iframe(url, parameters);
  10303. }
  10304. else {
  10305. module.error(error.noURL, $module);
  10306. }
  10307. return html;
  10308. },
  10309. parameters: function(source, extraParameters) {
  10310. var
  10311. parameters = (sources[source] && sources[source].parameters !== undefined)
  10312. ? sources[source].parameters(settings)
  10313. : {}
  10314. ;
  10315. extraParameters = extraParameters || settings.parameters;
  10316. if(extraParameters) {
  10317. parameters = $.extend({}, parameters, extraParameters);
  10318. }
  10319. parameters = settings.onEmbed(parameters);
  10320. return module.encode.parameters(parameters);
  10321. }
  10322. },
  10323. has: {
  10324. embed: function() {
  10325. return ($embed.length > 0);
  10326. },
  10327. placeholder: function() {
  10328. return settings.placeholder || $module.data(metadata.placeholder);
  10329. }
  10330. },
  10331. should: {
  10332. autoplay: function() {
  10333. return (settings.autoplay === 'auto')
  10334. ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
  10335. : settings.autoplay
  10336. ;
  10337. }
  10338. },
  10339. is: {
  10340. video: function() {
  10341. return module.get.type() == 'video';
  10342. }
  10343. },
  10344. setting: function(name, value) {
  10345. module.debug('Changing setting', name, value);
  10346. if( $.isPlainObject(name) ) {
  10347. $.extend(true, settings, name);
  10348. }
  10349. else if(value !== undefined) {
  10350. if($.isPlainObject(settings[name])) {
  10351. $.extend(true, settings[name], value);
  10352. }
  10353. else {
  10354. settings[name] = value;
  10355. }
  10356. }
  10357. else {
  10358. return settings[name];
  10359. }
  10360. },
  10361. internal: function(name, value) {
  10362. if( $.isPlainObject(name) ) {
  10363. $.extend(true, module, name);
  10364. }
  10365. else if(value !== undefined) {
  10366. module[name] = value;
  10367. }
  10368. else {
  10369. return module[name];
  10370. }
  10371. },
  10372. debug: function() {
  10373. if(!settings.silent && settings.debug) {
  10374. if(settings.performance) {
  10375. module.performance.log(arguments);
  10376. }
  10377. else {
  10378. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10379. module.debug.apply(console, arguments);
  10380. }
  10381. }
  10382. },
  10383. verbose: function() {
  10384. if(!settings.silent && settings.verbose && settings.debug) {
  10385. if(settings.performance) {
  10386. module.performance.log(arguments);
  10387. }
  10388. else {
  10389. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10390. module.verbose.apply(console, arguments);
  10391. }
  10392. }
  10393. },
  10394. error: function() {
  10395. if(!settings.silent) {
  10396. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  10397. module.error.apply(console, arguments);
  10398. }
  10399. },
  10400. performance: {
  10401. log: function(message) {
  10402. var
  10403. currentTime,
  10404. executionTime,
  10405. previousTime
  10406. ;
  10407. if(settings.performance) {
  10408. currentTime = new Date().getTime();
  10409. previousTime = time || currentTime;
  10410. executionTime = currentTime - previousTime;
  10411. time = currentTime;
  10412. performance.push({
  10413. 'Name' : message[0],
  10414. 'Arguments' : [].slice.call(message, 1) || '',
  10415. 'Element' : element,
  10416. 'Execution Time' : executionTime
  10417. });
  10418. }
  10419. clearTimeout(module.performance.timer);
  10420. module.performance.timer = setTimeout(module.performance.display, 500);
  10421. },
  10422. display: function() {
  10423. var
  10424. title = settings.name + ':',
  10425. totalTime = 0
  10426. ;
  10427. time = false;
  10428. clearTimeout(module.performance.timer);
  10429. $.each(performance, function(index, data) {
  10430. totalTime += data['Execution Time'];
  10431. });
  10432. title += ' ' + totalTime + 'ms';
  10433. if(moduleSelector) {
  10434. title += ' \'' + moduleSelector + '\'';
  10435. }
  10436. if($allModules.length > 1) {
  10437. title += ' ' + '(' + $allModules.length + ')';
  10438. }
  10439. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  10440. console.groupCollapsed(title);
  10441. if(console.table) {
  10442. console.table(performance);
  10443. }
  10444. else {
  10445. $.each(performance, function(index, data) {
  10446. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  10447. });
  10448. }
  10449. console.groupEnd();
  10450. }
  10451. performance = [];
  10452. }
  10453. },
  10454. invoke: function(query, passedArguments, context) {
  10455. var
  10456. object = instance,
  10457. maxDepth,
  10458. found,
  10459. response
  10460. ;
  10461. passedArguments = passedArguments || queryArguments;
  10462. context = element || context;
  10463. if(typeof query == 'string' && object !== undefined) {
  10464. query = query.split(/[\. ]/);
  10465. maxDepth = query.length - 1;
  10466. $.each(query, function(depth, value) {
  10467. var camelCaseValue = (depth != maxDepth)
  10468. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  10469. : query
  10470. ;
  10471. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  10472. object = object[camelCaseValue];
  10473. }
  10474. else if( object[camelCaseValue] !== undefined ) {
  10475. found = object[camelCaseValue];
  10476. return false;
  10477. }
  10478. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  10479. object = object[value];
  10480. }
  10481. else if( object[value] !== undefined ) {
  10482. found = object[value];
  10483. return false;
  10484. }
  10485. else {
  10486. module.error(error.method, query);
  10487. return false;
  10488. }
  10489. });
  10490. }
  10491. if ( $.isFunction( found ) ) {
  10492. response = found.apply(context, passedArguments);
  10493. }
  10494. else if(found !== undefined) {
  10495. response = found;
  10496. }
  10497. if(Array.isArray(returnedValue)) {
  10498. returnedValue.push(response);
  10499. }
  10500. else if(returnedValue !== undefined) {
  10501. returnedValue = [returnedValue, response];
  10502. }
  10503. else if(response !== undefined) {
  10504. returnedValue = response;
  10505. }
  10506. return found;
  10507. }
  10508. };
  10509. if(methodInvoked) {
  10510. if(instance === undefined) {
  10511. module.initialize();
  10512. }
  10513. module.invoke(query);
  10514. }
  10515. else {
  10516. if(instance !== undefined) {
  10517. instance.invoke('destroy');
  10518. }
  10519. module.initialize();
  10520. }
  10521. })
  10522. ;
  10523. return (returnedValue !== undefined)
  10524. ? returnedValue
  10525. : this
  10526. ;
  10527. };
  10528. $.fn.embed.settings = {
  10529. name : 'Embed',
  10530. namespace : 'embed',
  10531. silent : false,
  10532. debug : false,
  10533. verbose : false,
  10534. performance : true,
  10535. icon : false,
  10536. source : false,
  10537. url : false,
  10538. id : false,
  10539. // standard video settings
  10540. autoplay : 'auto',
  10541. color : '#444444',
  10542. hd : true,
  10543. brandedUI : false,
  10544. // additional parameters to include with the embed
  10545. parameters: false,
  10546. onDisplay : function() {},
  10547. onPlaceholderDisplay : function() {},
  10548. onReset : function() {},
  10549. onCreate : function(url) {},
  10550. onEmbed : function(parameters) {
  10551. return parameters;
  10552. },
  10553. metadata : {
  10554. id : 'id',
  10555. icon : 'icon',
  10556. placeholder : 'placeholder',
  10557. source : 'source',
  10558. url : 'url'
  10559. },
  10560. error : {
  10561. noURL : 'No URL specified',
  10562. method : 'The method you called is not defined'
  10563. },
  10564. className : {
  10565. active : 'active',
  10566. embed : 'embed'
  10567. },
  10568. selector : {
  10569. embed : '.embed',
  10570. placeholder : '.placeholder',
  10571. icon : '.icon'
  10572. },
  10573. sources: {
  10574. youtube: {
  10575. name : 'youtube',
  10576. type : 'video',
  10577. icon : 'video play',
  10578. domain : 'youtube.com',
  10579. url : '//www.youtube.com/embed/{id}',
  10580. parameters: function(settings) {
  10581. return {
  10582. autohide : !settings.brandedUI,
  10583. autoplay : settings.autoplay,
  10584. color : settings.color || undefined,
  10585. hq : settings.hd,
  10586. jsapi : settings.api,
  10587. modestbranding : !settings.brandedUI
  10588. };
  10589. }
  10590. },
  10591. vimeo: {
  10592. name : 'vimeo',
  10593. type : 'video',
  10594. icon : 'video play',
  10595. domain : 'vimeo.com',
  10596. url : '//player.vimeo.com/video/{id}',
  10597. parameters: function(settings) {
  10598. return {
  10599. api : settings.api,
  10600. autoplay : settings.autoplay,
  10601. byline : settings.brandedUI,
  10602. color : settings.color || undefined,
  10603. portrait : settings.brandedUI,
  10604. title : settings.brandedUI
  10605. };
  10606. }
  10607. }
  10608. },
  10609. templates: {
  10610. iframe : function(url, parameters) {
  10611. var src = url;
  10612. if (parameters) {
  10613. src += '?' + parameters;
  10614. }
  10615. return ''
  10616. + '<iframe src="' + src + '"'
  10617. + ' width="100%" height="100%"'
  10618. + ' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  10619. ;
  10620. },
  10621. placeholder : function(image, icon) {
  10622. var
  10623. html = ''
  10624. ;
  10625. if(icon) {
  10626. html += '<i class="' + icon + ' icon"></i>';
  10627. }
  10628. if(image) {
  10629. html += '<img class="placeholder" src="' + image + '">';
  10630. }
  10631. return html;
  10632. }
  10633. },
  10634. // NOT YET IMPLEMENTED
  10635. api : false,
  10636. onPause : function() {},
  10637. onPlay : function() {},
  10638. onStop : function() {}
  10639. };
  10640. })( jQuery, window, document );
  10641. /*!
  10642. * # Fomantic-UI - Modal
  10643. * http://github.com/fomantic/Fomantic-UI/
  10644. *
  10645. *
  10646. * Released under the MIT license
  10647. * http://opensource.org/licenses/MIT
  10648. *
  10649. */
  10650. ;(function ($, window, document, undefined) {
  10651. 'use strict';
  10652. $.isFunction = $.isFunction || function(obj) {
  10653. return typeof obj === "function" && typeof obj.nodeType !== "number";
  10654. };
  10655. window = (typeof window != 'undefined' && window.Math == Math)
  10656. ? window
  10657. : (typeof self != 'undefined' && self.Math == Math)
  10658. ? self
  10659. : Function('return this')()
  10660. ;
  10661. $.fn.modal = function(parameters) {
  10662. var
  10663. $allModules = $(this),
  10664. $window = $(window),
  10665. $document = $(document),
  10666. $body = $('body'),
  10667. moduleSelector = $allModules.selector || '',
  10668. time = new Date().getTime(),
  10669. performance = [],
  10670. query = arguments[0],
  10671. methodInvoked = (typeof query == 'string'),
  10672. queryArguments = [].slice.call(arguments, 1),
  10673. requestAnimationFrame = window.requestAnimationFrame
  10674. || window.mozRequestAnimationFrame
  10675. || window.webkitRequestAnimationFrame
  10676. || window.msRequestAnimationFrame
  10677. || function(callback) { setTimeout(callback, 0); },
  10678. returnedValue
  10679. ;
  10680. $allModules
  10681. .each(function() {
  10682. var
  10683. settings = ( $.isPlainObject(parameters) )
  10684. ? $.extend(true, {}, $.fn.modal.settings, parameters)
  10685. : $.extend({}, $.fn.modal.settings),
  10686. selector = settings.selector,
  10687. className = settings.className,
  10688. namespace = settings.namespace,
  10689. error = settings.error,
  10690. eventNamespace = '.' + namespace,
  10691. moduleNamespace = 'module-' + namespace,
  10692. $module = $(this),
  10693. $context = $(settings.context),
  10694. $close = $module.find(selector.close),
  10695. $allModals,
  10696. $otherModals,
  10697. $focusedElement,
  10698. $dimmable,
  10699. $dimmer,
  10700. element = this,
  10701. instance = $module.data(moduleNamespace),
  10702. ignoreRepeatedEvents = false,
  10703. initialMouseDownInModal,
  10704. initialMouseDownInScrollbar,
  10705. initialBodyMargin = '',
  10706. tempBodyMargin = '',
  10707. elementEventNamespace,
  10708. id,
  10709. observer,
  10710. module
  10711. ;
  10712. module = {
  10713. initialize: function() {
  10714. module.cache = {};
  10715. module.verbose('Initializing dimmer', $context);
  10716. module.create.id();
  10717. module.create.dimmer();
  10718. if ( settings.allowMultiple ) {
  10719. module.create.innerDimmer();
  10720. }
  10721. if (!settings.centered){
  10722. $module.addClass('top aligned');
  10723. }
  10724. module.refreshModals();
  10725. module.bind.events();
  10726. if(settings.observeChanges) {
  10727. module.observeChanges();
  10728. }
  10729. module.instantiate();
  10730. },
  10731. instantiate: function() {
  10732. module.verbose('Storing instance of modal');
  10733. instance = module;
  10734. $module
  10735. .data(moduleNamespace, instance)
  10736. ;
  10737. },
  10738. create: {
  10739. dimmer: function() {
  10740. var
  10741. defaultSettings = {
  10742. debug : settings.debug,
  10743. dimmerName : 'modals'
  10744. },
  10745. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  10746. ;
  10747. if($.fn.dimmer === undefined) {
  10748. module.error(error.dimmer);
  10749. return;
  10750. }
  10751. module.debug('Creating dimmer');
  10752. $dimmable = $context.dimmer(dimmerSettings);
  10753. if(settings.detachable) {
  10754. module.verbose('Modal is detachable, moving content into dimmer');
  10755. $dimmable.dimmer('add content', $module);
  10756. }
  10757. else {
  10758. module.set.undetached();
  10759. }
  10760. $dimmer = $dimmable.dimmer('get dimmer');
  10761. },
  10762. id: function() {
  10763. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  10764. elementEventNamespace = '.' + id;
  10765. module.verbose('Creating unique id for element', id);
  10766. },
  10767. innerDimmer: function() {
  10768. if ( $module.find(selector.dimmer).length == 0 ) {
  10769. $module.prepend('<div class="ui inverted dimmer"></div>');
  10770. }
  10771. }
  10772. },
  10773. destroy: function() {
  10774. if (observer) {
  10775. observer.disconnect();
  10776. }
  10777. module.verbose('Destroying previous modal');
  10778. $module
  10779. .removeData(moduleNamespace)
  10780. .off(eventNamespace)
  10781. ;
  10782. $window.off(elementEventNamespace);
  10783. $dimmer.off(elementEventNamespace);
  10784. $close.off(eventNamespace);
  10785. $context.dimmer('destroy');
  10786. },
  10787. observeChanges: function() {
  10788. if('MutationObserver' in window) {
  10789. observer = new MutationObserver(function(mutations) {
  10790. module.debug('DOM tree modified, refreshing');
  10791. module.refresh();
  10792. });
  10793. observer.observe(element, {
  10794. childList : true,
  10795. subtree : true
  10796. });
  10797. module.debug('Setting up mutation observer', observer);
  10798. }
  10799. },
  10800. refresh: function() {
  10801. module.remove.scrolling();
  10802. module.cacheSizes();
  10803. if(!module.can.useFlex()) {
  10804. module.set.modalOffset();
  10805. }
  10806. module.set.screenHeight();
  10807. module.set.type();
  10808. },
  10809. refreshModals: function() {
  10810. $otherModals = $module.siblings(selector.modal);
  10811. $allModals = $otherModals.add($module);
  10812. },
  10813. attachEvents: function(selector, event) {
  10814. var
  10815. $toggle = $(selector)
  10816. ;
  10817. event = $.isFunction(module[event])
  10818. ? module[event]
  10819. : module.toggle
  10820. ;
  10821. if($toggle.length > 0) {
  10822. module.debug('Attaching modal events to element', selector, event);
  10823. $toggle
  10824. .off(eventNamespace)
  10825. .on('click' + eventNamespace, event)
  10826. ;
  10827. }
  10828. else {
  10829. module.error(error.notFound, selector);
  10830. }
  10831. },
  10832. bind: {
  10833. events: function() {
  10834. module.verbose('Attaching events');
  10835. $module
  10836. .on('click' + eventNamespace, selector.close, module.event.close)
  10837. .on('click' + eventNamespace, selector.approve, module.event.approve)
  10838. .on('click' + eventNamespace, selector.deny, module.event.deny)
  10839. ;
  10840. $window
  10841. .on('resize' + elementEventNamespace, module.event.resize)
  10842. ;
  10843. },
  10844. scrollLock: function() {
  10845. // touch events default to passive, due to changes in chrome to optimize mobile perf
  10846. $dimmable.get(0).addEventListener('touchmove', module.event.preventScroll, { passive: false });
  10847. }
  10848. },
  10849. unbind: {
  10850. scrollLock: function() {
  10851. $dimmable.get(0).removeEventListener('touchmove', module.event.preventScroll, { passive: false });
  10852. }
  10853. },
  10854. get: {
  10855. id: function() {
  10856. return (Math.random().toString(16) + '000000000').substr(2, 8);
  10857. }
  10858. },
  10859. event: {
  10860. approve: function() {
  10861. if(ignoreRepeatedEvents || settings.onApprove.call(element, $(this)) === false) {
  10862. module.verbose('Approve callback returned false cancelling hide');
  10863. return;
  10864. }
  10865. ignoreRepeatedEvents = true;
  10866. module.hide(function() {
  10867. ignoreRepeatedEvents = false;
  10868. });
  10869. },
  10870. preventScroll: function(event) {
  10871. if(event.target.className.indexOf('dimmer') !== -1) {
  10872. event.preventDefault();
  10873. }
  10874. },
  10875. deny: function() {
  10876. if(ignoreRepeatedEvents || settings.onDeny.call(element, $(this)) === false) {
  10877. module.verbose('Deny callback returned false cancelling hide');
  10878. return;
  10879. }
  10880. ignoreRepeatedEvents = true;
  10881. module.hide(function() {
  10882. ignoreRepeatedEvents = false;
  10883. });
  10884. },
  10885. close: function() {
  10886. module.hide();
  10887. },
  10888. mousedown: function(event) {
  10889. var
  10890. $target = $(event.target),
  10891. isRtl = module.is.rtl();
  10892. ;
  10893. initialMouseDownInModal = ($target.closest(selector.modal).length > 0);
  10894. if(initialMouseDownInModal) {
  10895. module.verbose('Mouse down event registered inside the modal');
  10896. }
  10897. initialMouseDownInScrollbar = module.is.scrolling() && ((!isRtl && $(window).outerWidth() - settings.scrollbarWidth <= event.clientX) || (isRtl && settings.scrollbarWidth >= event.clientX));
  10898. if(initialMouseDownInScrollbar) {
  10899. module.verbose('Mouse down event registered inside the scrollbar');
  10900. }
  10901. },
  10902. mouseup: function(event) {
  10903. if(!settings.closable) {
  10904. module.verbose('Dimmer clicked but closable setting is disabled');
  10905. return;
  10906. }
  10907. if(initialMouseDownInModal) {
  10908. module.debug('Dimmer clicked but mouse down was initially registered inside the modal');
  10909. return;
  10910. }
  10911. if(initialMouseDownInScrollbar){
  10912. module.debug('Dimmer clicked but mouse down was initially registered inside the scrollbar');
  10913. return;
  10914. }
  10915. var
  10916. $target = $(event.target),
  10917. isInModal = ($target.closest(selector.modal).length > 0),
  10918. isInDOM = $.contains(document.documentElement, event.target)
  10919. ;
  10920. if(!isInModal && isInDOM && module.is.active() && $module.hasClass(className.front) ) {
  10921. module.debug('Dimmer clicked, hiding all modals');
  10922. if(settings.allowMultiple) {
  10923. if(!module.hideAll()) {
  10924. return;
  10925. }
  10926. }
  10927. else if(!module.hide()){
  10928. return;
  10929. }
  10930. module.remove.clickaway();
  10931. }
  10932. },
  10933. debounce: function(method, delay) {
  10934. clearTimeout(module.timer);
  10935. module.timer = setTimeout(method, delay);
  10936. },
  10937. keyboard: function(event) {
  10938. var
  10939. keyCode = event.which,
  10940. escapeKey = 27
  10941. ;
  10942. if(keyCode == escapeKey) {
  10943. if(settings.closable) {
  10944. module.debug('Escape key pressed hiding modal');
  10945. if ( $module.hasClass(className.front) ) {
  10946. module.hide();
  10947. }
  10948. }
  10949. else {
  10950. module.debug('Escape key pressed, but closable is set to false');
  10951. }
  10952. event.preventDefault();
  10953. }
  10954. },
  10955. resize: function() {
  10956. if( $dimmable.dimmer('is active') && ( module.is.animating() || module.is.active() ) ) {
  10957. requestAnimationFrame(module.refresh);
  10958. }
  10959. }
  10960. },
  10961. toggle: function() {
  10962. if( module.is.active() || module.is.animating() ) {
  10963. module.hide();
  10964. }
  10965. else {
  10966. module.show();
  10967. }
  10968. },
  10969. show: function(callback) {
  10970. callback = $.isFunction(callback)
  10971. ? callback
  10972. : function(){}
  10973. ;
  10974. module.refreshModals();
  10975. module.set.dimmerSettings();
  10976. module.set.dimmerStyles();
  10977. module.showModal(callback);
  10978. },
  10979. hide: function(callback) {
  10980. callback = $.isFunction(callback)
  10981. ? callback
  10982. : function(){}
  10983. ;
  10984. module.refreshModals();
  10985. return module.hideModal(callback);
  10986. },
  10987. showModal: function(callback) {
  10988. callback = $.isFunction(callback)
  10989. ? callback
  10990. : function(){}
  10991. ;
  10992. if( module.is.animating() || !module.is.active() ) {
  10993. module.showDimmer();
  10994. module.cacheSizes();
  10995. module.set.bodyMargin();
  10996. if(module.can.useFlex()) {
  10997. module.remove.legacy();
  10998. }
  10999. else {
  11000. module.set.legacy();
  11001. module.set.modalOffset();
  11002. module.debug('Using non-flex legacy modal positioning.');
  11003. }
  11004. module.set.screenHeight();
  11005. module.set.type();
  11006. module.set.clickaway();
  11007. if( !settings.allowMultiple && module.others.active() ) {
  11008. module.hideOthers(module.showModal);
  11009. }
  11010. else {
  11011. ignoreRepeatedEvents = false;
  11012. if( settings.allowMultiple ) {
  11013. if ( module.others.active() ) {
  11014. $otherModals.filter('.' + className.active).find(selector.dimmer).addClass('active');
  11015. }
  11016. if ( settings.detachable ) {
  11017. $module.detach().appendTo($dimmer);
  11018. }
  11019. }
  11020. settings.onShow.call(element);
  11021. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  11022. module.debug('Showing modal with css animations');
  11023. $module
  11024. .transition({
  11025. debug : settings.debug,
  11026. animation : settings.transition + ' in',
  11027. queue : settings.queue,
  11028. duration : settings.duration,
  11029. useFailSafe : true,
  11030. onComplete : function() {
  11031. settings.onVisible.apply(element);
  11032. if(settings.keyboardShortcuts) {
  11033. module.add.keyboardShortcuts();
  11034. }
  11035. module.save.focus();
  11036. module.set.active();
  11037. if(settings.autofocus) {
  11038. module.set.autofocus();
  11039. }
  11040. callback();
  11041. }
  11042. })
  11043. ;
  11044. }
  11045. else {
  11046. module.error(error.noTransition);
  11047. }
  11048. }
  11049. }
  11050. else {
  11051. module.debug('Modal is already visible');
  11052. }
  11053. },
  11054. hideModal: function(callback, keepDimmed, hideOthersToo) {
  11055. var
  11056. $previousModal = $otherModals.filter('.' + className.active).last()
  11057. ;
  11058. callback = $.isFunction(callback)
  11059. ? callback
  11060. : function(){}
  11061. ;
  11062. module.debug('Hiding modal');
  11063. if(settings.onHide.call(element, $(this)) === false) {
  11064. module.verbose('Hide callback returned false cancelling hide');
  11065. ignoreRepeatedEvents = false;
  11066. return false;
  11067. }
  11068. if( module.is.animating() || module.is.active() ) {
  11069. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  11070. module.remove.active();
  11071. $module
  11072. .transition({
  11073. debug : settings.debug,
  11074. animation : settings.transition + ' out',
  11075. queue : settings.queue,
  11076. duration : settings.duration,
  11077. useFailSafe : true,
  11078. onStart : function() {
  11079. if(!module.others.active() && !module.others.animating() && !keepDimmed) {
  11080. module.hideDimmer();
  11081. }
  11082. if( settings.keyboardShortcuts && !module.others.active() ) {
  11083. module.remove.keyboardShortcuts();
  11084. }
  11085. },
  11086. onComplete : function() {
  11087. module.unbind.scrollLock();
  11088. if ( settings.allowMultiple ) {
  11089. $previousModal.addClass(className.front);
  11090. $module.removeClass(className.front);
  11091. if ( hideOthersToo ) {
  11092. $allModals.find(selector.dimmer).removeClass('active');
  11093. }
  11094. else {
  11095. $previousModal.find(selector.dimmer).removeClass('active');
  11096. }
  11097. }
  11098. settings.onHidden.call(element);
  11099. module.remove.dimmerStyles();
  11100. module.restore.focus();
  11101. callback();
  11102. }
  11103. })
  11104. ;
  11105. }
  11106. else {
  11107. module.error(error.noTransition);
  11108. }
  11109. }
  11110. },
  11111. showDimmer: function() {
  11112. if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
  11113. module.save.bodyMargin();
  11114. module.debug('Showing dimmer');
  11115. $dimmable.dimmer('show');
  11116. }
  11117. else {
  11118. module.debug('Dimmer already visible');
  11119. }
  11120. },
  11121. hideDimmer: function() {
  11122. if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
  11123. module.unbind.scrollLock();
  11124. $dimmable.dimmer('hide', function() {
  11125. module.restore.bodyMargin();
  11126. module.remove.clickaway();
  11127. module.remove.screenHeight();
  11128. });
  11129. }
  11130. else {
  11131. module.debug('Dimmer is not visible cannot hide');
  11132. return;
  11133. }
  11134. },
  11135. hideAll: function(callback) {
  11136. var
  11137. $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
  11138. ;
  11139. callback = $.isFunction(callback)
  11140. ? callback
  11141. : function(){}
  11142. ;
  11143. if( $visibleModals.length > 0 ) {
  11144. module.debug('Hiding all visible modals');
  11145. var hideOk = true;
  11146. //check in reverse order trying to hide most top displayed modal first
  11147. $($visibleModals.get().reverse()).each(function(index,element){
  11148. if(hideOk){
  11149. hideOk = $(element).modal('hide modal', callback, false, true);
  11150. }
  11151. });
  11152. if(hideOk) {
  11153. module.hideDimmer();
  11154. }
  11155. return hideOk;
  11156. }
  11157. },
  11158. hideOthers: function(callback) {
  11159. var
  11160. $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
  11161. ;
  11162. callback = $.isFunction(callback)
  11163. ? callback
  11164. : function(){}
  11165. ;
  11166. if( $visibleModals.length > 0 ) {
  11167. module.debug('Hiding other modals', $otherModals);
  11168. $visibleModals
  11169. .modal('hide modal', callback, true)
  11170. ;
  11171. }
  11172. },
  11173. others: {
  11174. active: function() {
  11175. return ($otherModals.filter('.' + className.active).length > 0);
  11176. },
  11177. animating: function() {
  11178. return ($otherModals.filter('.' + className.animating).length > 0);
  11179. }
  11180. },
  11181. add: {
  11182. keyboardShortcuts: function() {
  11183. module.verbose('Adding keyboard shortcuts');
  11184. $document
  11185. .on('keyup' + eventNamespace, module.event.keyboard)
  11186. ;
  11187. }
  11188. },
  11189. save: {
  11190. focus: function() {
  11191. var
  11192. $activeElement = $(document.activeElement),
  11193. inCurrentModal = $activeElement.closest($module).length > 0
  11194. ;
  11195. if(!inCurrentModal) {
  11196. $focusedElement = $(document.activeElement).blur();
  11197. }
  11198. },
  11199. bodyMargin: function() {
  11200. initialBodyMargin = $body.css('margin-'+(module.can.leftBodyScrollbar() ? 'left':'right'));
  11201. var bodyMarginRightPixel = parseInt(initialBodyMargin.replace(/[^\d.]/g, '')),
  11202. bodyScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
  11203. tempBodyMargin = bodyMarginRightPixel + bodyScrollbarWidth;
  11204. }
  11205. },
  11206. restore: {
  11207. focus: function() {
  11208. if($focusedElement && $focusedElement.length > 0 && settings.restoreFocus) {
  11209. $focusedElement.focus();
  11210. }
  11211. },
  11212. bodyMargin: function() {
  11213. var position = module.can.leftBodyScrollbar() ? 'left':'right';
  11214. $body.css('margin-'+position, initialBodyMargin);
  11215. $body.find(selector.bodyFixed.replace('right',position)).css('padding-'+position, initialBodyMargin);
  11216. }
  11217. },
  11218. remove: {
  11219. active: function() {
  11220. $module.removeClass(className.active);
  11221. },
  11222. legacy: function() {
  11223. $module.removeClass(className.legacy);
  11224. },
  11225. clickaway: function() {
  11226. if (!settings.detachable) {
  11227. $module
  11228. .off('mousedown' + elementEventNamespace)
  11229. ;
  11230. }
  11231. $dimmer
  11232. .off('mousedown' + elementEventNamespace)
  11233. ;
  11234. $dimmer
  11235. .off('mouseup' + elementEventNamespace)
  11236. ;
  11237. },
  11238. dimmerStyles: function() {
  11239. $dimmer.removeClass(className.inverted);
  11240. $dimmable.removeClass(className.blurring);
  11241. },
  11242. bodyStyle: function() {
  11243. if($body.attr('style') === '') {
  11244. module.verbose('Removing style attribute');
  11245. $body.removeAttr('style');
  11246. }
  11247. },
  11248. screenHeight: function() {
  11249. module.debug('Removing page height');
  11250. $body
  11251. .css('height', '')
  11252. ;
  11253. },
  11254. keyboardShortcuts: function() {
  11255. module.verbose('Removing keyboard shortcuts');
  11256. $document
  11257. .off('keyup' + eventNamespace)
  11258. ;
  11259. },
  11260. scrolling: function() {
  11261. $dimmable.removeClass(className.scrolling);
  11262. $module.removeClass(className.scrolling);
  11263. }
  11264. },
  11265. cacheSizes: function() {
  11266. $module.addClass(className.loading);
  11267. var
  11268. scrollHeight = $module.prop('scrollHeight'),
  11269. modalWidth = $module.outerWidth(),
  11270. modalHeight = $module.outerHeight()
  11271. ;
  11272. if(module.cache.pageHeight === undefined || modalHeight !== 0) {
  11273. $.extend(module.cache, {
  11274. pageHeight : $(document).outerHeight(),
  11275. width : modalWidth,
  11276. height : modalHeight + settings.offset,
  11277. scrollHeight : scrollHeight + settings.offset,
  11278. contextHeight : (settings.context == 'body')
  11279. ? $(window).height()
  11280. : $dimmable.height(),
  11281. });
  11282. module.cache.topOffset = -(module.cache.height / 2);
  11283. }
  11284. $module.removeClass(className.loading);
  11285. module.debug('Caching modal and container sizes', module.cache);
  11286. },
  11287. can: {
  11288. leftBodyScrollbar: function(){
  11289. if(module.cache.leftBodyScrollbar === undefined) {
  11290. module.cache.leftBodyScrollbar = module.is.rtl() && ((module.is.iframe && !module.is.firefox()) || module.is.safari() || module.is.edge() || module.is.ie());
  11291. }
  11292. return module.cache.leftBodyScrollbar;
  11293. },
  11294. useFlex: function() {
  11295. if (settings.useFlex === 'auto') {
  11296. return settings.detachable && !module.is.ie();
  11297. }
  11298. if(settings.useFlex && module.is.ie()) {
  11299. module.debug('useFlex true is not supported in IE');
  11300. } else if(settings.useFlex && !settings.detachable) {
  11301. module.debug('useFlex true in combination with detachable false is not supported');
  11302. }
  11303. return settings.useFlex;
  11304. },
  11305. fit: function() {
  11306. var
  11307. contextHeight = module.cache.contextHeight,
  11308. verticalCenter = module.cache.contextHeight / 2,
  11309. topOffset = module.cache.topOffset,
  11310. scrollHeight = module.cache.scrollHeight,
  11311. height = module.cache.height,
  11312. paddingHeight = settings.padding,
  11313. startPosition = (verticalCenter + topOffset)
  11314. ;
  11315. return (scrollHeight > height)
  11316. ? (startPosition + scrollHeight + paddingHeight < contextHeight)
  11317. : (height + (paddingHeight * 2) < contextHeight)
  11318. ;
  11319. }
  11320. },
  11321. is: {
  11322. active: function() {
  11323. return $module.hasClass(className.active);
  11324. },
  11325. ie: function() {
  11326. if(module.cache.isIE === undefined) {
  11327. var
  11328. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  11329. isIE = ('ActiveXObject' in window)
  11330. ;
  11331. module.cache.isIE = (isIE11 || isIE);
  11332. }
  11333. return module.cache.isIE;
  11334. },
  11335. animating: function() {
  11336. return $module.transition('is supported')
  11337. ? $module.transition('is animating')
  11338. : $module.is(':visible')
  11339. ;
  11340. },
  11341. scrolling: function() {
  11342. return $dimmable.hasClass(className.scrolling);
  11343. },
  11344. modernBrowser: function() {
  11345. // appName for IE11 reports 'Netscape' can no longer use
  11346. return !(window.ActiveXObject || 'ActiveXObject' in window);
  11347. },
  11348. rtl: function() {
  11349. if(module.cache.isRTL === undefined) {
  11350. module.cache.isRTL = $body.attr('dir') === 'rtl' || $body.css('direction') === 'rtl';
  11351. }
  11352. return module.cache.isRTL;
  11353. },
  11354. safari: function() {
  11355. if(module.cache.isSafari === undefined) {
  11356. module.cache.isSafari = /constructor/i.test(window.HTMLElement) || !!window.ApplePaySession;
  11357. }
  11358. return module.cache.isSafari;
  11359. },
  11360. edge: function(){
  11361. if(module.cache.isEdge === undefined) {
  11362. module.cache.isEdge = !!window.setImmediate && !module.is.ie();
  11363. }
  11364. return module.cache.isEdge;
  11365. },
  11366. firefox: function(){
  11367. if(module.cache.isFirefox === undefined) {
  11368. module.cache.isFirefox = !!window.InstallTrigger;
  11369. }
  11370. return module.cache.isFirefox;
  11371. },
  11372. iframe: function() {
  11373. return !(self === top);
  11374. }
  11375. },
  11376. set: {
  11377. autofocus: function() {
  11378. var
  11379. $inputs = $module.find('[tabindex], :input').filter(':visible').filter(function() {
  11380. return $(this).closest('.disabled').length === 0;
  11381. }),
  11382. $autofocus = $inputs.filter('[autofocus]'),
  11383. $input = ($autofocus.length > 0)
  11384. ? $autofocus.first()
  11385. : $inputs.first()
  11386. ;
  11387. if($input.length > 0) {
  11388. $input.focus();
  11389. }
  11390. },
  11391. bodyMargin: function() {
  11392. var position = module.can.leftBodyScrollbar() ? 'left':'right';
  11393. if(settings.detachable || module.can.fit()) {
  11394. $body.css('margin-'+position, tempBodyMargin + 'px');
  11395. }
  11396. $body.find(selector.bodyFixed.replace('right',position)).css('padding-'+position, tempBodyMargin + 'px');
  11397. },
  11398. clickaway: function() {
  11399. if (!settings.detachable) {
  11400. $module
  11401. .on('mousedown' + elementEventNamespace, module.event.mousedown)
  11402. ;
  11403. }
  11404. $dimmer
  11405. .on('mousedown' + elementEventNamespace, module.event.mousedown)
  11406. ;
  11407. $dimmer
  11408. .on('mouseup' + elementEventNamespace, module.event.mouseup)
  11409. ;
  11410. },
  11411. dimmerSettings: function() {
  11412. if($.fn.dimmer === undefined) {
  11413. module.error(error.dimmer);
  11414. return;
  11415. }
  11416. var
  11417. defaultSettings = {
  11418. debug : settings.debug,
  11419. dimmerName : 'modals',
  11420. closable : 'auto',
  11421. useFlex : module.can.useFlex(),
  11422. duration : {
  11423. show : settings.duration,
  11424. hide : settings.duration
  11425. }
  11426. },
  11427. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  11428. ;
  11429. if(settings.inverted) {
  11430. dimmerSettings.variation = (dimmerSettings.variation !== undefined)
  11431. ? dimmerSettings.variation + ' inverted'
  11432. : 'inverted'
  11433. ;
  11434. }
  11435. $context.dimmer('setting', dimmerSettings);
  11436. },
  11437. dimmerStyles: function() {
  11438. if(settings.inverted) {
  11439. $dimmer.addClass(className.inverted);
  11440. }
  11441. else {
  11442. $dimmer.removeClass(className.inverted);
  11443. }
  11444. if(settings.blurring) {
  11445. $dimmable.addClass(className.blurring);
  11446. }
  11447. else {
  11448. $dimmable.removeClass(className.blurring);
  11449. }
  11450. },
  11451. modalOffset: function() {
  11452. if (!settings.detachable) {
  11453. var canFit = module.can.fit();
  11454. $module
  11455. .css({
  11456. top: (!$module.hasClass('aligned') && canFit)
  11457. ? $(document).scrollTop() + (module.cache.contextHeight - module.cache.height) / 2
  11458. : !canFit || $module.hasClass('top')
  11459. ? $(document).scrollTop() + settings.padding
  11460. : $(document).scrollTop() + (module.cache.contextHeight - module.cache.height - settings.padding),
  11461. marginLeft: -(module.cache.width / 2)
  11462. })
  11463. ;
  11464. } else {
  11465. $module
  11466. .css({
  11467. marginTop: (!$module.hasClass('aligned') && module.can.fit())
  11468. ? -(module.cache.height / 2)
  11469. : settings.padding / 2,
  11470. marginLeft: -(module.cache.width / 2)
  11471. })
  11472. ;
  11473. }
  11474. module.verbose('Setting modal offset for legacy mode');
  11475. },
  11476. screenHeight: function() {
  11477. if( module.can.fit() ) {
  11478. $body.css('height', '');
  11479. }
  11480. else if(!$module.hasClass('bottom')) {
  11481. module.debug('Modal is taller than page content, resizing page height');
  11482. $body
  11483. .css('height', module.cache.height + (settings.padding * 2) )
  11484. ;
  11485. }
  11486. },
  11487. active: function() {
  11488. $module.addClass(className.active + ' ' + className.front);
  11489. $otherModals.filter('.' + className.active).removeClass(className.front);
  11490. },
  11491. scrolling: function() {
  11492. $dimmable.addClass(className.scrolling);
  11493. $module.addClass(className.scrolling);
  11494. module.unbind.scrollLock();
  11495. },
  11496. legacy: function() {
  11497. $module.addClass(className.legacy);
  11498. },
  11499. type: function() {
  11500. if(module.can.fit()) {
  11501. module.verbose('Modal fits on screen');
  11502. if(!module.others.active() && !module.others.animating()) {
  11503. module.remove.scrolling();
  11504. module.bind.scrollLock();
  11505. }
  11506. }
  11507. else if (!$module.hasClass('bottom')){
  11508. module.verbose('Modal cannot fit on screen setting to scrolling');
  11509. module.set.scrolling();
  11510. } else {
  11511. module.verbose('Bottom aligned modal not fitting on screen is unsupported for scrolling');
  11512. }
  11513. },
  11514. undetached: function() {
  11515. $dimmable.addClass(className.undetached);
  11516. }
  11517. },
  11518. setting: function(name, value) {
  11519. module.debug('Changing setting', name, value);
  11520. if( $.isPlainObject(name) ) {
  11521. $.extend(true, settings, name);
  11522. }
  11523. else if(value !== undefined) {
  11524. if($.isPlainObject(settings[name])) {
  11525. $.extend(true, settings[name], value);
  11526. }
  11527. else {
  11528. settings[name] = value;
  11529. }
  11530. }
  11531. else {
  11532. return settings[name];
  11533. }
  11534. },
  11535. internal: function(name, value) {
  11536. if( $.isPlainObject(name) ) {
  11537. $.extend(true, module, name);
  11538. }
  11539. else if(value !== undefined) {
  11540. module[name] = value;
  11541. }
  11542. else {
  11543. return module[name];
  11544. }
  11545. },
  11546. debug: function() {
  11547. if(!settings.silent && settings.debug) {
  11548. if(settings.performance) {
  11549. module.performance.log(arguments);
  11550. }
  11551. else {
  11552. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11553. module.debug.apply(console, arguments);
  11554. }
  11555. }
  11556. },
  11557. verbose: function() {
  11558. if(!settings.silent && settings.verbose && settings.debug) {
  11559. if(settings.performance) {
  11560. module.performance.log(arguments);
  11561. }
  11562. else {
  11563. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11564. module.verbose.apply(console, arguments);
  11565. }
  11566. }
  11567. },
  11568. error: function() {
  11569. if(!settings.silent) {
  11570. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  11571. module.error.apply(console, arguments);
  11572. }
  11573. },
  11574. performance: {
  11575. log: function(message) {
  11576. var
  11577. currentTime,
  11578. executionTime,
  11579. previousTime
  11580. ;
  11581. if(settings.performance) {
  11582. currentTime = new Date().getTime();
  11583. previousTime = time || currentTime;
  11584. executionTime = currentTime - previousTime;
  11585. time = currentTime;
  11586. performance.push({
  11587. 'Name' : message[0],
  11588. 'Arguments' : [].slice.call(message, 1) || '',
  11589. 'Element' : element,
  11590. 'Execution Time' : executionTime
  11591. });
  11592. }
  11593. clearTimeout(module.performance.timer);
  11594. module.performance.timer = setTimeout(module.performance.display, 500);
  11595. },
  11596. display: function() {
  11597. var
  11598. title = settings.name + ':',
  11599. totalTime = 0
  11600. ;
  11601. time = false;
  11602. clearTimeout(module.performance.timer);
  11603. $.each(performance, function(index, data) {
  11604. totalTime += data['Execution Time'];
  11605. });
  11606. title += ' ' + totalTime + 'ms';
  11607. if(moduleSelector) {
  11608. title += ' \'' + moduleSelector + '\'';
  11609. }
  11610. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  11611. console.groupCollapsed(title);
  11612. if(console.table) {
  11613. console.table(performance);
  11614. }
  11615. else {
  11616. $.each(performance, function(index, data) {
  11617. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  11618. });
  11619. }
  11620. console.groupEnd();
  11621. }
  11622. performance = [];
  11623. }
  11624. },
  11625. invoke: function(query, passedArguments, context) {
  11626. var
  11627. object = instance,
  11628. maxDepth,
  11629. found,
  11630. response
  11631. ;
  11632. passedArguments = passedArguments || queryArguments;
  11633. context = element || context;
  11634. if(typeof query == 'string' && object !== undefined) {
  11635. query = query.split(/[\. ]/);
  11636. maxDepth = query.length - 1;
  11637. $.each(query, function(depth, value) {
  11638. var camelCaseValue = (depth != maxDepth)
  11639. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  11640. : query
  11641. ;
  11642. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  11643. object = object[camelCaseValue];
  11644. }
  11645. else if( object[camelCaseValue] !== undefined ) {
  11646. found = object[camelCaseValue];
  11647. return false;
  11648. }
  11649. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  11650. object = object[value];
  11651. }
  11652. else if( object[value] !== undefined ) {
  11653. found = object[value];
  11654. return false;
  11655. }
  11656. else {
  11657. return false;
  11658. }
  11659. });
  11660. }
  11661. if ( $.isFunction( found ) ) {
  11662. response = found.apply(context, passedArguments);
  11663. }
  11664. else if(found !== undefined) {
  11665. response = found;
  11666. }
  11667. if(Array.isArray(returnedValue)) {
  11668. returnedValue.push(response);
  11669. }
  11670. else if(returnedValue !== undefined) {
  11671. returnedValue = [returnedValue, response];
  11672. }
  11673. else if(response !== undefined) {
  11674. returnedValue = response;
  11675. }
  11676. return found;
  11677. }
  11678. };
  11679. if(methodInvoked) {
  11680. if(instance === undefined) {
  11681. module.initialize();
  11682. }
  11683. module.invoke(query);
  11684. }
  11685. else {
  11686. if(instance !== undefined) {
  11687. instance.invoke('destroy');
  11688. }
  11689. module.initialize();
  11690. }
  11691. })
  11692. ;
  11693. return (returnedValue !== undefined)
  11694. ? returnedValue
  11695. : this
  11696. ;
  11697. };
  11698. $.fn.modal.settings = {
  11699. name : 'Modal',
  11700. namespace : 'modal',
  11701. useFlex : 'auto',
  11702. offset : 0,
  11703. silent : false,
  11704. debug : false,
  11705. verbose : false,
  11706. performance : true,
  11707. observeChanges : false,
  11708. allowMultiple : false,
  11709. detachable : true,
  11710. closable : true,
  11711. autofocus : true,
  11712. restoreFocus : true,
  11713. inverted : false,
  11714. blurring : false,
  11715. centered : true,
  11716. dimmerSettings : {
  11717. closable : false,
  11718. useCSS : true
  11719. },
  11720. // whether to use keyboard shortcuts
  11721. keyboardShortcuts: true,
  11722. context : 'body',
  11723. queue : false,
  11724. duration : 500,
  11725. transition : 'scale',
  11726. // padding with edge of page
  11727. padding : 50,
  11728. scrollbarWidth: 10,
  11729. // called before show animation
  11730. onShow : function(){},
  11731. // called after show animation
  11732. onVisible : function(){},
  11733. // called before hide animation
  11734. onHide : function(){ return true; },
  11735. // called after hide animation
  11736. onHidden : function(){},
  11737. // called after approve selector match
  11738. onApprove : function(){ return true; },
  11739. // called after deny selector match
  11740. onDeny : function(){ return true; },
  11741. selector : {
  11742. close : '> .close',
  11743. approve : '.actions .positive, .actions .approve, .actions .ok',
  11744. deny : '.actions .negative, .actions .deny, .actions .cancel',
  11745. modal : '.ui.modal',
  11746. dimmer : '> .ui.dimmer',
  11747. bodyFixed: '> .ui.fixed.menu, > .ui.right.toast-container, > .ui.right.sidebar'
  11748. },
  11749. error : {
  11750. dimmer : 'UI Dimmer, a required component is not included in this page',
  11751. method : 'The method you called is not defined.',
  11752. notFound : 'The element you specified could not be found'
  11753. },
  11754. className : {
  11755. active : 'active',
  11756. animating : 'animating',
  11757. blurring : 'blurring',
  11758. inverted : 'inverted',
  11759. legacy : 'legacy',
  11760. loading : 'loading',
  11761. scrolling : 'scrolling',
  11762. undetached : 'undetached',
  11763. front : 'front'
  11764. }
  11765. };
  11766. })( jQuery, window, document );
  11767. /*!
  11768. * # Fomantic-UI - Nag
  11769. * http://github.com/fomantic/Fomantic-UI/
  11770. *
  11771. *
  11772. * Released under the MIT license
  11773. * http://opensource.org/licenses/MIT
  11774. *
  11775. */
  11776. ;(function ($, window, document, undefined) {
  11777. 'use strict';
  11778. $.isFunction = $.isFunction || function(obj) {
  11779. return typeof obj === "function" && typeof obj.nodeType !== "number";
  11780. };
  11781. window = (typeof window != 'undefined' && window.Math == Math)
  11782. ? window
  11783. : (typeof self != 'undefined' && self.Math == Math)
  11784. ? self
  11785. : Function('return this')()
  11786. ;
  11787. $.fn.nag = function(parameters) {
  11788. var
  11789. $allModules = $(this),
  11790. moduleSelector = $allModules.selector || '',
  11791. time = new Date().getTime(),
  11792. performance = [],
  11793. query = arguments[0],
  11794. methodInvoked = (typeof query == 'string'),
  11795. queryArguments = [].slice.call(arguments, 1),
  11796. returnedValue
  11797. ;
  11798. $allModules
  11799. .each(function() {
  11800. var
  11801. settings = ( $.isPlainObject(parameters) )
  11802. ? $.extend(true, {}, $.fn.nag.settings, parameters)
  11803. : $.extend({}, $.fn.nag.settings),
  11804. selector = settings.selector,
  11805. error = settings.error,
  11806. namespace = settings.namespace,
  11807. eventNamespace = '.' + namespace,
  11808. moduleNamespace = namespace + '-module',
  11809. $module = $(this),
  11810. $context = (settings.context)
  11811. ? $(settings.context)
  11812. : $('body'),
  11813. element = this,
  11814. instance = $module.data(moduleNamespace),
  11815. module
  11816. ;
  11817. module = {
  11818. initialize: function() {
  11819. module.verbose('Initializing element');
  11820. $module
  11821. .on('click' + eventNamespace, selector.close, module.dismiss)
  11822. .data(moduleNamespace, module)
  11823. ;
  11824. if(settings.detachable && $module.parent()[0] !== $context[0]) {
  11825. $module
  11826. .detach()
  11827. .prependTo($context)
  11828. ;
  11829. }
  11830. if(settings.displayTime > 0) {
  11831. setTimeout(module.hide, settings.displayTime);
  11832. }
  11833. module.show();
  11834. },
  11835. destroy: function() {
  11836. module.verbose('Destroying instance');
  11837. $module
  11838. .removeData(moduleNamespace)
  11839. .off(eventNamespace)
  11840. ;
  11841. },
  11842. show: function() {
  11843. if( module.should.show() && !$module.is(':visible') ) {
  11844. module.debug('Showing nag', settings.animation.show);
  11845. if(settings.animation.show == 'fade') {
  11846. $module
  11847. .fadeIn(settings.duration, settings.easing)
  11848. ;
  11849. }
  11850. else {
  11851. $module
  11852. .slideDown(settings.duration, settings.easing)
  11853. ;
  11854. }
  11855. }
  11856. },
  11857. hide: function() {
  11858. module.debug('Showing nag', settings.animation.hide);
  11859. if(settings.animation.show == 'fade') {
  11860. $module
  11861. .fadeIn(settings.duration, settings.easing)
  11862. ;
  11863. }
  11864. else {
  11865. $module
  11866. .slideUp(settings.duration, settings.easing)
  11867. ;
  11868. }
  11869. },
  11870. onHide: function() {
  11871. module.debug('Removing nag', settings.animation.hide);
  11872. $module.remove();
  11873. if (settings.onHide) {
  11874. settings.onHide();
  11875. }
  11876. },
  11877. dismiss: function(event) {
  11878. if(settings.storageMethod) {
  11879. module.storage.set(settings.key, settings.value);
  11880. }
  11881. module.hide();
  11882. event.stopImmediatePropagation();
  11883. event.preventDefault();
  11884. },
  11885. should: {
  11886. show: function() {
  11887. if(settings.persist) {
  11888. module.debug('Persistent nag is set, can show nag');
  11889. return true;
  11890. }
  11891. if( module.storage.get(settings.key) != settings.value.toString() ) {
  11892. module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
  11893. return true;
  11894. }
  11895. module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
  11896. return false;
  11897. }
  11898. },
  11899. get: {
  11900. storageOptions: function() {
  11901. var
  11902. options = {}
  11903. ;
  11904. if(settings.expires) {
  11905. options.expires = settings.expires;
  11906. }
  11907. if(settings.domain) {
  11908. options.domain = settings.domain;
  11909. }
  11910. if(settings.path) {
  11911. options.path = settings.path;
  11912. }
  11913. return options;
  11914. }
  11915. },
  11916. clear: function() {
  11917. module.storage.remove(settings.key);
  11918. },
  11919. storage: {
  11920. set: function(key, value) {
  11921. var
  11922. options = module.get.storageOptions()
  11923. ;
  11924. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  11925. window.localStorage.setItem(key, value);
  11926. module.debug('Value stored using local storage', key, value);
  11927. }
  11928. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  11929. window.sessionStorage.setItem(key, value);
  11930. module.debug('Value stored using session storage', key, value);
  11931. }
  11932. else if($.cookie !== undefined) {
  11933. $.cookie(key, value, options);
  11934. module.debug('Value stored using cookie', key, value, options);
  11935. }
  11936. else {
  11937. module.error(error.noCookieStorage);
  11938. return;
  11939. }
  11940. },
  11941. get: function(key, value) {
  11942. var
  11943. storedValue
  11944. ;
  11945. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  11946. storedValue = window.localStorage.getItem(key);
  11947. }
  11948. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  11949. storedValue = window.sessionStorage.getItem(key);
  11950. }
  11951. // get by cookie
  11952. else if($.cookie !== undefined) {
  11953. storedValue = $.cookie(key);
  11954. }
  11955. else {
  11956. module.error(error.noCookieStorage);
  11957. }
  11958. if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
  11959. storedValue = undefined;
  11960. }
  11961. return storedValue;
  11962. },
  11963. remove: function(key) {
  11964. var
  11965. options = module.get.storageOptions()
  11966. ;
  11967. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  11968. window.localStorage.removeItem(key);
  11969. }
  11970. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  11971. window.sessionStorage.removeItem(key);
  11972. }
  11973. // store by cookie
  11974. else if($.cookie !== undefined) {
  11975. $.removeCookie(key, options);
  11976. }
  11977. else {
  11978. module.error(error.noStorage);
  11979. }
  11980. }
  11981. },
  11982. setting: function(name, value) {
  11983. module.debug('Changing setting', name, value);
  11984. if( $.isPlainObject(name) ) {
  11985. $.extend(true, settings, name);
  11986. }
  11987. else if(value !== undefined) {
  11988. if($.isPlainObject(settings[name])) {
  11989. $.extend(true, settings[name], value);
  11990. }
  11991. else {
  11992. settings[name] = value;
  11993. }
  11994. }
  11995. else {
  11996. return settings[name];
  11997. }
  11998. },
  11999. internal: function(name, value) {
  12000. if( $.isPlainObject(name) ) {
  12001. $.extend(true, module, name);
  12002. }
  12003. else if(value !== undefined) {
  12004. module[name] = value;
  12005. }
  12006. else {
  12007. return module[name];
  12008. }
  12009. },
  12010. debug: function() {
  12011. if(!settings.silent && settings.debug) {
  12012. if(settings.performance) {
  12013. module.performance.log(arguments);
  12014. }
  12015. else {
  12016. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12017. module.debug.apply(console, arguments);
  12018. }
  12019. }
  12020. },
  12021. verbose: function() {
  12022. if(!settings.silent && settings.verbose && settings.debug) {
  12023. if(settings.performance) {
  12024. module.performance.log(arguments);
  12025. }
  12026. else {
  12027. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12028. module.verbose.apply(console, arguments);
  12029. }
  12030. }
  12031. },
  12032. error: function() {
  12033. if(!settings.silent) {
  12034. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  12035. module.error.apply(console, arguments);
  12036. }
  12037. },
  12038. performance: {
  12039. log: function(message) {
  12040. var
  12041. currentTime,
  12042. executionTime,
  12043. previousTime
  12044. ;
  12045. if(settings.performance) {
  12046. currentTime = new Date().getTime();
  12047. previousTime = time || currentTime;
  12048. executionTime = currentTime - previousTime;
  12049. time = currentTime;
  12050. performance.push({
  12051. 'Name' : message[0],
  12052. 'Arguments' : [].slice.call(message, 1) || '',
  12053. 'Element' : element,
  12054. 'Execution Time' : executionTime
  12055. });
  12056. }
  12057. clearTimeout(module.performance.timer);
  12058. module.performance.timer = setTimeout(module.performance.display, 500);
  12059. },
  12060. display: function() {
  12061. var
  12062. title = settings.name + ':',
  12063. totalTime = 0
  12064. ;
  12065. time = false;
  12066. clearTimeout(module.performance.timer);
  12067. $.each(performance, function(index, data) {
  12068. totalTime += data['Execution Time'];
  12069. });
  12070. title += ' ' + totalTime + 'ms';
  12071. if(moduleSelector) {
  12072. title += ' \'' + moduleSelector + '\'';
  12073. }
  12074. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  12075. console.groupCollapsed(title);
  12076. if(console.table) {
  12077. console.table(performance);
  12078. }
  12079. else {
  12080. $.each(performance, function(index, data) {
  12081. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  12082. });
  12083. }
  12084. console.groupEnd();
  12085. }
  12086. performance = [];
  12087. }
  12088. },
  12089. invoke: function(query, passedArguments, context) {
  12090. var
  12091. object = instance,
  12092. maxDepth,
  12093. found,
  12094. response
  12095. ;
  12096. passedArguments = passedArguments || queryArguments;
  12097. context = element || context;
  12098. if(typeof query == 'string' && object !== undefined) {
  12099. query = query.split(/[\. ]/);
  12100. maxDepth = query.length - 1;
  12101. $.each(query, function(depth, value) {
  12102. var camelCaseValue = (depth != maxDepth)
  12103. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  12104. : query
  12105. ;
  12106. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  12107. object = object[camelCaseValue];
  12108. }
  12109. else if( object[camelCaseValue] !== undefined ) {
  12110. found = object[camelCaseValue];
  12111. return false;
  12112. }
  12113. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  12114. object = object[value];
  12115. }
  12116. else if( object[value] !== undefined ) {
  12117. found = object[value];
  12118. return false;
  12119. }
  12120. else {
  12121. module.error(error.method, query);
  12122. return false;
  12123. }
  12124. });
  12125. }
  12126. if ( $.isFunction( found ) ) {
  12127. response = found.apply(context, passedArguments);
  12128. }
  12129. else if(found !== undefined) {
  12130. response = found;
  12131. }
  12132. if(Array.isArray(returnedValue)) {
  12133. returnedValue.push(response);
  12134. }
  12135. else if(returnedValue !== undefined) {
  12136. returnedValue = [returnedValue, response];
  12137. }
  12138. else if(response !== undefined) {
  12139. returnedValue = response;
  12140. }
  12141. return found;
  12142. }
  12143. };
  12144. if(methodInvoked) {
  12145. if(instance === undefined) {
  12146. module.initialize();
  12147. }
  12148. module.invoke(query);
  12149. }
  12150. else {
  12151. if(instance !== undefined) {
  12152. instance.invoke('destroy');
  12153. }
  12154. module.initialize();
  12155. }
  12156. })
  12157. ;
  12158. return (returnedValue !== undefined)
  12159. ? returnedValue
  12160. : this
  12161. ;
  12162. };
  12163. $.fn.nag.settings = {
  12164. name : 'Nag',
  12165. silent : false,
  12166. debug : false,
  12167. verbose : false,
  12168. performance : true,
  12169. namespace : 'Nag',
  12170. // allows cookie to be overridden
  12171. persist : false,
  12172. // set to zero to require manually dismissal, otherwise hides on its own
  12173. displayTime : 0,
  12174. animation : {
  12175. show : 'slide',
  12176. hide : 'slide'
  12177. },
  12178. context : false,
  12179. detachable : false,
  12180. expires : 30,
  12181. domain : false,
  12182. path : '/',
  12183. // type of storage to use
  12184. storageMethod : 'cookie',
  12185. // value to store in dismissed localstorage/cookie
  12186. key : 'nag',
  12187. value : 'dismiss',
  12188. error: {
  12189. noCookieStorage : '$.cookie is not included. A storage solution is required.',
  12190. noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
  12191. method : 'The method you called is not defined.'
  12192. },
  12193. className : {
  12194. bottom : 'bottom',
  12195. fixed : 'fixed'
  12196. },
  12197. selector : {
  12198. close : '.close.icon'
  12199. },
  12200. speed : 500,
  12201. easing : 'easeOutQuad',
  12202. onHide: function() {}
  12203. };
  12204. // Adds easing
  12205. $.extend( $.easing, {
  12206. easeOutQuad: function (x, t, b, c, d) {
  12207. return -c *(t/=d)*(t-2) + b;
  12208. }
  12209. });
  12210. })( jQuery, window, document );
  12211. /*!
  12212. * # Fomantic-UI - Popup
  12213. * http://github.com/fomantic/Fomantic-UI/
  12214. *
  12215. *
  12216. * Released under the MIT license
  12217. * http://opensource.org/licenses/MIT
  12218. *
  12219. */
  12220. ;(function ($, window, document, undefined) {
  12221. 'use strict';
  12222. $.isFunction = $.isFunction || function(obj) {
  12223. return typeof obj === "function" && typeof obj.nodeType !== "number";
  12224. };
  12225. window = (typeof window != 'undefined' && window.Math == Math)
  12226. ? window
  12227. : (typeof self != 'undefined' && self.Math == Math)
  12228. ? self
  12229. : Function('return this')()
  12230. ;
  12231. $.fn.popup = function(parameters) {
  12232. var
  12233. $allModules = $(this),
  12234. $document = $(document),
  12235. $window = $(window),
  12236. $body = $('body'),
  12237. moduleSelector = $allModules.selector || '',
  12238. clickEvent = ('ontouchstart' in document.documentElement)
  12239. ? 'touchstart'
  12240. : 'click',
  12241. time = new Date().getTime(),
  12242. performance = [],
  12243. query = arguments[0],
  12244. methodInvoked = (typeof query == 'string'),
  12245. queryArguments = [].slice.call(arguments, 1),
  12246. returnedValue
  12247. ;
  12248. $allModules
  12249. .each(function() {
  12250. var
  12251. settings = ( $.isPlainObject(parameters) )
  12252. ? $.extend(true, {}, $.fn.popup.settings, parameters)
  12253. : $.extend({}, $.fn.popup.settings),
  12254. selector = settings.selector,
  12255. className = settings.className,
  12256. error = settings.error,
  12257. metadata = settings.metadata,
  12258. namespace = settings.namespace,
  12259. eventNamespace = '.' + settings.namespace,
  12260. moduleNamespace = 'module-' + namespace,
  12261. $module = $(this),
  12262. $context = $(settings.context),
  12263. $scrollContext = $(settings.scrollContext),
  12264. $boundary = $(settings.boundary),
  12265. $target = (settings.target)
  12266. ? $(settings.target)
  12267. : $module,
  12268. $popup,
  12269. $offsetParent,
  12270. searchDepth = 0,
  12271. triedPositions = false,
  12272. openedWithTouch = false,
  12273. element = this,
  12274. instance = $module.data(moduleNamespace),
  12275. documentObserver,
  12276. elementNamespace,
  12277. id,
  12278. module
  12279. ;
  12280. module = {
  12281. // binds events
  12282. initialize: function() {
  12283. module.debug('Initializing', $module);
  12284. module.createID();
  12285. module.bind.events();
  12286. if(!module.exists() && settings.preserve) {
  12287. module.create();
  12288. }
  12289. if(settings.observeChanges) {
  12290. module.observeChanges();
  12291. }
  12292. module.instantiate();
  12293. },
  12294. instantiate: function() {
  12295. module.verbose('Storing instance', module);
  12296. instance = module;
  12297. $module
  12298. .data(moduleNamespace, instance)
  12299. ;
  12300. },
  12301. observeChanges: function() {
  12302. if('MutationObserver' in window) {
  12303. documentObserver = new MutationObserver(module.event.documentChanged);
  12304. documentObserver.observe(document, {
  12305. childList : true,
  12306. subtree : true
  12307. });
  12308. module.debug('Setting up mutation observer', documentObserver);
  12309. }
  12310. },
  12311. refresh: function() {
  12312. if(settings.popup) {
  12313. $popup = $(settings.popup).eq(0);
  12314. }
  12315. else {
  12316. if(settings.inline) {
  12317. $popup = $target.nextAll(selector.popup).eq(0);
  12318. settings.popup = $popup;
  12319. }
  12320. }
  12321. if(settings.popup) {
  12322. $popup.addClass(className.loading);
  12323. $offsetParent = module.get.offsetParent();
  12324. $popup.removeClass(className.loading);
  12325. if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
  12326. module.debug('Moving popup to the same offset parent as target');
  12327. $popup
  12328. .detach()
  12329. .appendTo($offsetParent)
  12330. ;
  12331. }
  12332. }
  12333. else {
  12334. $offsetParent = (settings.inline)
  12335. ? module.get.offsetParent($target)
  12336. : module.has.popup()
  12337. ? module.get.offsetParent($popup)
  12338. : $body
  12339. ;
  12340. }
  12341. if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
  12342. module.debug('Setting page as offset parent');
  12343. $offsetParent = $body;
  12344. }
  12345. if( module.get.variation() ) {
  12346. module.set.variation();
  12347. }
  12348. },
  12349. reposition: function() {
  12350. module.refresh();
  12351. module.set.position();
  12352. },
  12353. destroy: function() {
  12354. module.debug('Destroying previous module');
  12355. if(documentObserver) {
  12356. documentObserver.disconnect();
  12357. }
  12358. // remove element only if was created dynamically
  12359. if($popup && !settings.preserve) {
  12360. module.removePopup();
  12361. }
  12362. // clear all timeouts
  12363. clearTimeout(module.hideTimer);
  12364. clearTimeout(module.showTimer);
  12365. // remove events
  12366. module.unbind.close();
  12367. module.unbind.events();
  12368. $module
  12369. .removeData(moduleNamespace)
  12370. ;
  12371. },
  12372. event: {
  12373. start: function(event) {
  12374. var
  12375. delay = ($.isPlainObject(settings.delay))
  12376. ? settings.delay.show
  12377. : settings.delay
  12378. ;
  12379. clearTimeout(module.hideTimer);
  12380. if(!openedWithTouch || (openedWithTouch && settings.addTouchEvents) ) {
  12381. module.showTimer = setTimeout(module.show, delay);
  12382. }
  12383. },
  12384. end: function() {
  12385. var
  12386. delay = ($.isPlainObject(settings.delay))
  12387. ? settings.delay.hide
  12388. : settings.delay
  12389. ;
  12390. clearTimeout(module.showTimer);
  12391. module.hideTimer = setTimeout(module.hide, delay);
  12392. },
  12393. touchstart: function(event) {
  12394. openedWithTouch = true;
  12395. if(settings.addTouchEvents) {
  12396. module.show();
  12397. }
  12398. },
  12399. resize: function() {
  12400. if( module.is.visible() ) {
  12401. module.set.position();
  12402. }
  12403. },
  12404. documentChanged: function(mutations) {
  12405. [].forEach.call(mutations, function(mutation) {
  12406. if(mutation.removedNodes) {
  12407. [].forEach.call(mutation.removedNodes, function(node) {
  12408. if(node == element || $(node).find(element).length > 0) {
  12409. module.debug('Element removed from DOM, tearing down events');
  12410. module.destroy();
  12411. }
  12412. });
  12413. }
  12414. });
  12415. },
  12416. hideGracefully: function(event) {
  12417. var
  12418. $target = $(event.target),
  12419. isInDOM = $.contains(document.documentElement, event.target),
  12420. inPopup = ($target.closest(selector.popup).length > 0)
  12421. ;
  12422. // don't close on clicks inside popup
  12423. if(event && !inPopup && isInDOM) {
  12424. module.debug('Click occurred outside popup hiding popup');
  12425. module.hide();
  12426. }
  12427. else {
  12428. module.debug('Click was inside popup, keeping popup open');
  12429. }
  12430. }
  12431. },
  12432. // generates popup html from metadata
  12433. create: function() {
  12434. var
  12435. html = module.get.html(),
  12436. title = module.get.title(),
  12437. content = module.get.content()
  12438. ;
  12439. if(html || content || title) {
  12440. module.debug('Creating pop-up html');
  12441. if(!html) {
  12442. html = settings.templates.popup({
  12443. title : title,
  12444. content : content
  12445. });
  12446. }
  12447. $popup = $('<div/>')
  12448. .addClass(className.popup)
  12449. .data(metadata.activator, $module)
  12450. .html(html)
  12451. ;
  12452. if(settings.inline) {
  12453. module.verbose('Inserting popup element inline', $popup);
  12454. $popup
  12455. .insertAfter($module)
  12456. ;
  12457. }
  12458. else {
  12459. module.verbose('Appending popup element to body', $popup);
  12460. $popup
  12461. .appendTo( $context )
  12462. ;
  12463. }
  12464. module.refresh();
  12465. module.set.variation();
  12466. if(settings.hoverable) {
  12467. module.bind.popup();
  12468. }
  12469. settings.onCreate.call($popup, element);
  12470. }
  12471. else if(settings.popup) {
  12472. $(settings.popup).data(metadata.activator, $module);
  12473. module.verbose('Used popup specified in settings');
  12474. module.refresh();
  12475. if(settings.hoverable) {
  12476. module.bind.popup();
  12477. }
  12478. }
  12479. else if($target.next(selector.popup).length !== 0) {
  12480. module.verbose('Pre-existing popup found');
  12481. settings.inline = true;
  12482. settings.popup = $target.next(selector.popup).data(metadata.activator, $module);
  12483. module.refresh();
  12484. if(settings.hoverable) {
  12485. module.bind.popup();
  12486. }
  12487. }
  12488. else {
  12489. module.debug('No content specified skipping display', element);
  12490. }
  12491. },
  12492. createID: function() {
  12493. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  12494. elementNamespace = '.' + id;
  12495. module.verbose('Creating unique id for element', id);
  12496. },
  12497. // determines popup state
  12498. toggle: function() {
  12499. module.debug('Toggling pop-up');
  12500. if( module.is.hidden() ) {
  12501. module.debug('Popup is hidden, showing pop-up');
  12502. module.unbind.close();
  12503. module.show();
  12504. }
  12505. else {
  12506. module.debug('Popup is visible, hiding pop-up');
  12507. module.hide();
  12508. }
  12509. },
  12510. show: function(callback) {
  12511. callback = callback || function(){};
  12512. module.debug('Showing pop-up', settings.transition);
  12513. if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
  12514. if( !module.exists() ) {
  12515. module.create();
  12516. }
  12517. if(settings.onShow.call($popup, element) === false) {
  12518. module.debug('onShow callback returned false, cancelling popup animation');
  12519. return;
  12520. }
  12521. else if(!settings.preserve && !settings.popup) {
  12522. module.refresh();
  12523. }
  12524. if( $popup && module.set.position() ) {
  12525. module.save.conditions();
  12526. if(settings.exclusive) {
  12527. module.hideAll();
  12528. }
  12529. module.animate.show(callback);
  12530. }
  12531. }
  12532. },
  12533. hide: function(callback) {
  12534. callback = callback || function(){};
  12535. if( module.is.visible() || module.is.animating() ) {
  12536. if(settings.onHide.call($popup, element) === false) {
  12537. module.debug('onHide callback returned false, cancelling popup animation');
  12538. return;
  12539. }
  12540. module.remove.visible();
  12541. module.unbind.close();
  12542. module.restore.conditions();
  12543. module.animate.hide(callback);
  12544. }
  12545. },
  12546. hideAll: function() {
  12547. $(selector.popup)
  12548. .filter('.' + className.popupVisible)
  12549. .each(function() {
  12550. $(this)
  12551. .data(metadata.activator)
  12552. .popup('hide')
  12553. ;
  12554. })
  12555. ;
  12556. },
  12557. exists: function() {
  12558. if(!$popup) {
  12559. return false;
  12560. }
  12561. if(settings.inline || settings.popup) {
  12562. return ( module.has.popup() );
  12563. }
  12564. else {
  12565. return ( $popup.closest($context).length >= 1 )
  12566. ? true
  12567. : false
  12568. ;
  12569. }
  12570. },
  12571. removePopup: function() {
  12572. if( module.has.popup() && !settings.popup) {
  12573. module.debug('Removing popup', $popup);
  12574. $popup.remove();
  12575. $popup = undefined;
  12576. settings.onRemove.call($popup, element);
  12577. }
  12578. },
  12579. save: {
  12580. conditions: function() {
  12581. module.cache = {
  12582. title: $module.attr('title')
  12583. };
  12584. if (module.cache.title) {
  12585. $module.removeAttr('title');
  12586. }
  12587. module.verbose('Saving original attributes', module.cache.title);
  12588. }
  12589. },
  12590. restore: {
  12591. conditions: function() {
  12592. if(module.cache && module.cache.title) {
  12593. $module.attr('title', module.cache.title);
  12594. module.verbose('Restoring original attributes', module.cache.title);
  12595. }
  12596. return true;
  12597. }
  12598. },
  12599. supports: {
  12600. svg: function() {
  12601. return (typeof SVGGraphicsElement !== 'undefined');
  12602. }
  12603. },
  12604. animate: {
  12605. show: function(callback) {
  12606. callback = $.isFunction(callback) ? callback : function(){};
  12607. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  12608. module.set.visible();
  12609. $popup
  12610. .transition({
  12611. animation : settings.transition + ' in',
  12612. queue : false,
  12613. debug : settings.debug,
  12614. verbose : settings.verbose,
  12615. duration : settings.duration,
  12616. onComplete : function() {
  12617. module.bind.close();
  12618. callback.call($popup, element);
  12619. settings.onVisible.call($popup, element);
  12620. }
  12621. })
  12622. ;
  12623. }
  12624. else {
  12625. module.error(error.noTransition);
  12626. }
  12627. },
  12628. hide: function(callback) {
  12629. callback = $.isFunction(callback) ? callback : function(){};
  12630. module.debug('Hiding pop-up');
  12631. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  12632. $popup
  12633. .transition({
  12634. animation : settings.transition + ' out',
  12635. queue : false,
  12636. duration : settings.duration,
  12637. debug : settings.debug,
  12638. verbose : settings.verbose,
  12639. onComplete : function() {
  12640. module.reset();
  12641. callback.call($popup, element);
  12642. settings.onHidden.call($popup, element);
  12643. }
  12644. })
  12645. ;
  12646. }
  12647. else {
  12648. module.error(error.noTransition);
  12649. }
  12650. }
  12651. },
  12652. change: {
  12653. content: function(html) {
  12654. $popup.html(html);
  12655. }
  12656. },
  12657. get: {
  12658. html: function() {
  12659. $module.removeData(metadata.html);
  12660. return $module.data(metadata.html) || settings.html;
  12661. },
  12662. title: function() {
  12663. $module.removeData(metadata.title);
  12664. return $module.data(metadata.title) || settings.title;
  12665. },
  12666. content: function() {
  12667. $module.removeData(metadata.content);
  12668. return $module.data(metadata.content) || settings.content || $module.attr('title');
  12669. },
  12670. variation: function() {
  12671. $module.removeData(metadata.variation);
  12672. return $module.data(metadata.variation) || settings.variation;
  12673. },
  12674. popup: function() {
  12675. return $popup;
  12676. },
  12677. popupOffset: function() {
  12678. return $popup.offset();
  12679. },
  12680. calculations: function() {
  12681. var
  12682. $popupOffsetParent = module.get.offsetParent($popup),
  12683. targetElement = $target[0],
  12684. isWindow = ($boundary[0] == window),
  12685. targetPosition = (settings.inline || (settings.popup && settings.movePopup))
  12686. ? $target.position()
  12687. : $target.offset(),
  12688. screenPosition = (isWindow)
  12689. ? { top: 0, left: 0 }
  12690. : $boundary.offset(),
  12691. calculations = {},
  12692. scroll = (isWindow)
  12693. ? { top: $window.scrollTop(), left: $window.scrollLeft() }
  12694. : { top: 0, left: 0},
  12695. screen
  12696. ;
  12697. calculations = {
  12698. // element which is launching popup
  12699. target : {
  12700. element : $target[0],
  12701. width : $target.outerWidth(),
  12702. height : $target.outerHeight(),
  12703. top : targetPosition.top,
  12704. left : targetPosition.left,
  12705. margin : {}
  12706. },
  12707. // popup itself
  12708. popup : {
  12709. width : $popup.outerWidth(),
  12710. height : $popup.outerHeight()
  12711. },
  12712. // offset container (or 3d context)
  12713. parent : {
  12714. width : $offsetParent.outerWidth(),
  12715. height : $offsetParent.outerHeight()
  12716. },
  12717. // screen boundaries
  12718. screen : {
  12719. top : screenPosition.top,
  12720. left : screenPosition.left,
  12721. scroll: {
  12722. top : scroll.top,
  12723. left : scroll.left
  12724. },
  12725. width : $boundary.width(),
  12726. height : $boundary.height()
  12727. }
  12728. };
  12729. // if popup offset context is not same as target, then adjust calculations
  12730. if($popupOffsetParent.get(0) !== $offsetParent.get(0)) {
  12731. var
  12732. popupOffset = $popupOffsetParent.offset()
  12733. ;
  12734. calculations.target.top -= popupOffset.top;
  12735. calculations.target.left -= popupOffset.left;
  12736. calculations.parent.width = $popupOffsetParent.outerWidth();
  12737. calculations.parent.height = $popupOffsetParent.outerHeight();
  12738. }
  12739. // add in container calcs if fluid
  12740. if( settings.setFluidWidth && module.is.fluid() ) {
  12741. calculations.container = {
  12742. width: $popup.parent().outerWidth()
  12743. };
  12744. calculations.popup.width = calculations.container.width;
  12745. }
  12746. // add in margins if inline
  12747. calculations.target.margin.top = (settings.inline)
  12748. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
  12749. : 0
  12750. ;
  12751. calculations.target.margin.left = (settings.inline)
  12752. ? module.is.rtl()
  12753. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
  12754. : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
  12755. : 0
  12756. ;
  12757. // calculate screen boundaries
  12758. screen = calculations.screen;
  12759. calculations.boundary = {
  12760. top : screen.top + screen.scroll.top,
  12761. bottom : screen.top + screen.scroll.top + screen.height,
  12762. left : screen.left + screen.scroll.left,
  12763. right : screen.left + screen.scroll.left + screen.width
  12764. };
  12765. return calculations;
  12766. },
  12767. id: function() {
  12768. return id;
  12769. },
  12770. startEvent: function() {
  12771. if(settings.on == 'hover') {
  12772. return 'mouseenter';
  12773. }
  12774. else if(settings.on == 'focus') {
  12775. return 'focus';
  12776. }
  12777. return false;
  12778. },
  12779. scrollEvent: function() {
  12780. return 'scroll';
  12781. },
  12782. endEvent: function() {
  12783. if(settings.on == 'hover') {
  12784. return 'mouseleave';
  12785. }
  12786. else if(settings.on == 'focus') {
  12787. return 'blur';
  12788. }
  12789. return false;
  12790. },
  12791. distanceFromBoundary: function(offset, calculations) {
  12792. var
  12793. distanceFromBoundary = {},
  12794. popup,
  12795. boundary
  12796. ;
  12797. calculations = calculations || module.get.calculations();
  12798. // shorthand
  12799. popup = calculations.popup;
  12800. boundary = calculations.boundary;
  12801. if(offset) {
  12802. distanceFromBoundary = {
  12803. top : (offset.top - boundary.top),
  12804. left : (offset.left - boundary.left),
  12805. right : (boundary.right - (offset.left + popup.width) ),
  12806. bottom : (boundary.bottom - (offset.top + popup.height) )
  12807. };
  12808. module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
  12809. }
  12810. return distanceFromBoundary;
  12811. },
  12812. offsetParent: function($element) {
  12813. var
  12814. element = ($element !== undefined)
  12815. ? $element[0]
  12816. : $target[0],
  12817. parentNode = element.parentNode,
  12818. $node = $(parentNode)
  12819. ;
  12820. if(parentNode) {
  12821. var
  12822. is2D = ($node.css('transform') === 'none'),
  12823. isStatic = ($node.css('position') === 'static'),
  12824. isBody = $node.is('body')
  12825. ;
  12826. while(parentNode && !isBody && isStatic && is2D) {
  12827. parentNode = parentNode.parentNode;
  12828. $node = $(parentNode);
  12829. is2D = ($node.css('transform') === 'none');
  12830. isStatic = ($node.css('position') === 'static');
  12831. isBody = $node.is('body');
  12832. }
  12833. }
  12834. return ($node && $node.length > 0)
  12835. ? $node
  12836. : $()
  12837. ;
  12838. },
  12839. positions: function() {
  12840. return {
  12841. 'top left' : false,
  12842. 'top center' : false,
  12843. 'top right' : false,
  12844. 'bottom left' : false,
  12845. 'bottom center' : false,
  12846. 'bottom right' : false,
  12847. 'left center' : false,
  12848. 'right center' : false
  12849. };
  12850. },
  12851. nextPosition: function(position) {
  12852. var
  12853. positions = position.split(' '),
  12854. verticalPosition = positions[0],
  12855. horizontalPosition = positions[1],
  12856. opposite = {
  12857. top : 'bottom',
  12858. bottom : 'top',
  12859. left : 'right',
  12860. right : 'left'
  12861. },
  12862. adjacent = {
  12863. left : 'center',
  12864. center : 'right',
  12865. right : 'left'
  12866. },
  12867. backup = {
  12868. 'top left' : 'top center',
  12869. 'top center' : 'top right',
  12870. 'top right' : 'right center',
  12871. 'right center' : 'bottom right',
  12872. 'bottom right' : 'bottom center',
  12873. 'bottom center' : 'bottom left',
  12874. 'bottom left' : 'left center',
  12875. 'left center' : 'top left'
  12876. },
  12877. adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
  12878. oppositeTried = false,
  12879. adjacentTried = false,
  12880. nextPosition = false
  12881. ;
  12882. if(!triedPositions) {
  12883. module.verbose('All available positions available');
  12884. triedPositions = module.get.positions();
  12885. }
  12886. module.debug('Recording last position tried', position);
  12887. triedPositions[position] = true;
  12888. if(settings.prefer === 'opposite') {
  12889. nextPosition = [opposite[verticalPosition], horizontalPosition];
  12890. nextPosition = nextPosition.join(' ');
  12891. oppositeTried = (triedPositions[nextPosition] === true);
  12892. module.debug('Trying opposite strategy', nextPosition);
  12893. }
  12894. if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
  12895. nextPosition = [verticalPosition, adjacent[horizontalPosition]];
  12896. nextPosition = nextPosition.join(' ');
  12897. adjacentTried = (triedPositions[nextPosition] === true);
  12898. module.debug('Trying adjacent strategy', nextPosition);
  12899. }
  12900. if(adjacentTried || oppositeTried) {
  12901. module.debug('Using backup position', nextPosition);
  12902. nextPosition = backup[position];
  12903. }
  12904. return nextPosition;
  12905. }
  12906. },
  12907. set: {
  12908. position: function(position, calculations) {
  12909. // exit conditions
  12910. if($target.length === 0 || $popup.length === 0) {
  12911. module.error(error.notFound);
  12912. return;
  12913. }
  12914. var
  12915. offset,
  12916. distanceAway,
  12917. target,
  12918. popup,
  12919. parent,
  12920. positioning,
  12921. popupOffset,
  12922. distanceFromBoundary
  12923. ;
  12924. calculations = calculations || module.get.calculations();
  12925. position = position || $module.data(metadata.position) || settings.position;
  12926. offset = $module.data(metadata.offset) || settings.offset;
  12927. distanceAway = settings.distanceAway;
  12928. // shorthand
  12929. target = calculations.target;
  12930. popup = calculations.popup;
  12931. parent = calculations.parent;
  12932. if(module.should.centerArrow(calculations)) {
  12933. module.verbose('Adjusting offset to center arrow on small target element');
  12934. if(position == 'top left' || position == 'bottom left') {
  12935. offset += (target.width / 2);
  12936. offset -= settings.arrowPixelsFromEdge;
  12937. }
  12938. if(position == 'top right' || position == 'bottom right') {
  12939. offset -= (target.width / 2);
  12940. offset += settings.arrowPixelsFromEdge;
  12941. }
  12942. }
  12943. if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) {
  12944. module.debug('Popup target is hidden, no action taken');
  12945. return false;
  12946. }
  12947. if(settings.inline) {
  12948. module.debug('Adding margin to calculation', target.margin);
  12949. if(position == 'left center' || position == 'right center') {
  12950. offset += target.margin.top;
  12951. distanceAway += -target.margin.left;
  12952. }
  12953. else if (position == 'top left' || position == 'top center' || position == 'top right') {
  12954. offset += target.margin.left;
  12955. distanceAway -= target.margin.top;
  12956. }
  12957. else {
  12958. offset += target.margin.left;
  12959. distanceAway += target.margin.top;
  12960. }
  12961. }
  12962. module.debug('Determining popup position from calculations', position, calculations);
  12963. if (module.is.rtl()) {
  12964. position = position.replace(/left|right/g, function (match) {
  12965. return (match == 'left')
  12966. ? 'right'
  12967. : 'left'
  12968. ;
  12969. });
  12970. module.debug('RTL: Popup position updated', position);
  12971. }
  12972. // if last attempt use specified last resort position
  12973. if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
  12974. position = settings.lastResort;
  12975. }
  12976. switch (position) {
  12977. case 'top left':
  12978. positioning = {
  12979. top : 'auto',
  12980. bottom : parent.height - target.top + distanceAway,
  12981. left : target.left + offset,
  12982. right : 'auto'
  12983. };
  12984. break;
  12985. case 'top center':
  12986. positioning = {
  12987. bottom : parent.height - target.top + distanceAway,
  12988. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  12989. top : 'auto',
  12990. right : 'auto'
  12991. };
  12992. break;
  12993. case 'top right':
  12994. positioning = {
  12995. bottom : parent.height - target.top + distanceAway,
  12996. right : parent.width - target.left - target.width - offset,
  12997. top : 'auto',
  12998. left : 'auto'
  12999. };
  13000. break;
  13001. case 'left center':
  13002. positioning = {
  13003. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  13004. right : parent.width - target.left + distanceAway,
  13005. left : 'auto',
  13006. bottom : 'auto'
  13007. };
  13008. break;
  13009. case 'right center':
  13010. positioning = {
  13011. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  13012. left : target.left + target.width + distanceAway,
  13013. bottom : 'auto',
  13014. right : 'auto'
  13015. };
  13016. break;
  13017. case 'bottom left':
  13018. positioning = {
  13019. top : target.top + target.height + distanceAway,
  13020. left : target.left + offset,
  13021. bottom : 'auto',
  13022. right : 'auto'
  13023. };
  13024. break;
  13025. case 'bottom center':
  13026. positioning = {
  13027. top : target.top + target.height + distanceAway,
  13028. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  13029. bottom : 'auto',
  13030. right : 'auto'
  13031. };
  13032. break;
  13033. case 'bottom right':
  13034. positioning = {
  13035. top : target.top + target.height + distanceAway,
  13036. right : parent.width - target.left - target.width - offset,
  13037. left : 'auto',
  13038. bottom : 'auto'
  13039. };
  13040. break;
  13041. }
  13042. if(positioning === undefined) {
  13043. module.error(error.invalidPosition, position);
  13044. }
  13045. module.debug('Calculated popup positioning values', positioning);
  13046. // tentatively place on stage
  13047. $popup
  13048. .css(positioning)
  13049. .removeClass(className.position)
  13050. .addClass(position)
  13051. .addClass(className.loading)
  13052. ;
  13053. popupOffset = module.get.popupOffset();
  13054. // see if any boundaries are surpassed with this tentative position
  13055. distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
  13056. if(!settings.forcePosition && module.is.offstage(distanceFromBoundary, position) ) {
  13057. module.debug('Position is outside viewport', position);
  13058. if(searchDepth < settings.maxSearchDepth) {
  13059. searchDepth++;
  13060. position = module.get.nextPosition(position);
  13061. module.debug('Trying new position', position);
  13062. return ($popup)
  13063. ? module.set.position(position, calculations)
  13064. : false
  13065. ;
  13066. }
  13067. else {
  13068. if(settings.lastResort) {
  13069. module.debug('No position found, showing with last position');
  13070. }
  13071. else {
  13072. module.debug('Popup could not find a position to display', $popup);
  13073. module.error(error.cannotPlace, element);
  13074. module.remove.attempts();
  13075. module.remove.loading();
  13076. module.reset();
  13077. settings.onUnplaceable.call($popup, element);
  13078. return false;
  13079. }
  13080. }
  13081. }
  13082. module.debug('Position is on stage', position);
  13083. module.remove.attempts();
  13084. module.remove.loading();
  13085. if( settings.setFluidWidth && module.is.fluid() ) {
  13086. module.set.fluidWidth(calculations);
  13087. }
  13088. return true;
  13089. },
  13090. fluidWidth: function(calculations) {
  13091. calculations = calculations || module.get.calculations();
  13092. module.debug('Automatically setting element width to parent width', calculations.parent.width);
  13093. $popup.css('width', calculations.container.width);
  13094. },
  13095. variation: function(variation) {
  13096. variation = variation || module.get.variation();
  13097. if(variation && module.has.popup() ) {
  13098. module.verbose('Adding variation to popup', variation);
  13099. $popup.addClass(variation);
  13100. }
  13101. },
  13102. visible: function() {
  13103. $module.addClass(className.visible);
  13104. }
  13105. },
  13106. remove: {
  13107. loading: function() {
  13108. $popup.removeClass(className.loading);
  13109. },
  13110. variation: function(variation) {
  13111. variation = variation || module.get.variation();
  13112. if(variation) {
  13113. module.verbose('Removing variation', variation);
  13114. $popup.removeClass(variation);
  13115. }
  13116. },
  13117. visible: function() {
  13118. $module.removeClass(className.visible);
  13119. },
  13120. attempts: function() {
  13121. module.verbose('Resetting all searched positions');
  13122. searchDepth = 0;
  13123. triedPositions = false;
  13124. }
  13125. },
  13126. bind: {
  13127. events: function() {
  13128. module.debug('Binding popup events to module');
  13129. if(settings.on == 'click') {
  13130. $module
  13131. .on(clickEvent + eventNamespace, module.toggle)
  13132. ;
  13133. }
  13134. if(settings.on == 'hover') {
  13135. $module
  13136. .on('touchstart' + eventNamespace, module.event.touchstart)
  13137. ;
  13138. }
  13139. if( module.get.startEvent() ) {
  13140. $module
  13141. .on(module.get.startEvent() + eventNamespace, module.event.start)
  13142. .on(module.get.endEvent() + eventNamespace, module.event.end)
  13143. ;
  13144. }
  13145. if(settings.target) {
  13146. module.debug('Target set to element', $target);
  13147. }
  13148. $window.on('resize' + elementNamespace, module.event.resize);
  13149. },
  13150. popup: function() {
  13151. module.verbose('Allowing hover events on popup to prevent closing');
  13152. if( $popup && module.has.popup() ) {
  13153. $popup
  13154. .on('mouseenter' + eventNamespace, module.event.start)
  13155. .on('mouseleave' + eventNamespace, module.event.end)
  13156. ;
  13157. }
  13158. },
  13159. close: function() {
  13160. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  13161. module.bind.closeOnScroll();
  13162. }
  13163. if(module.is.closable()) {
  13164. module.bind.clickaway();
  13165. }
  13166. else if(settings.on == 'hover' && openedWithTouch) {
  13167. module.bind.touchClose();
  13168. }
  13169. },
  13170. closeOnScroll: function() {
  13171. module.verbose('Binding scroll close event to document');
  13172. $scrollContext
  13173. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  13174. ;
  13175. },
  13176. touchClose: function() {
  13177. module.verbose('Binding popup touchclose event to document');
  13178. $document
  13179. .on('touchstart' + elementNamespace, function(event) {
  13180. module.verbose('Touched away from popup');
  13181. module.event.hideGracefully.call(element, event);
  13182. })
  13183. ;
  13184. },
  13185. clickaway: function() {
  13186. module.verbose('Binding popup close event to document');
  13187. $document
  13188. .on(clickEvent + elementNamespace, function(event) {
  13189. module.verbose('Clicked away from popup');
  13190. module.event.hideGracefully.call(element, event);
  13191. })
  13192. ;
  13193. }
  13194. },
  13195. unbind: {
  13196. events: function() {
  13197. $window
  13198. .off(elementNamespace)
  13199. ;
  13200. $module
  13201. .off(eventNamespace)
  13202. ;
  13203. },
  13204. close: function() {
  13205. $document
  13206. .off(elementNamespace)
  13207. ;
  13208. $scrollContext
  13209. .off(elementNamespace)
  13210. ;
  13211. },
  13212. },
  13213. has: {
  13214. popup: function() {
  13215. return ($popup && $popup.length > 0);
  13216. }
  13217. },
  13218. should: {
  13219. centerArrow: function(calculations) {
  13220. return !module.is.basic() && calculations.target.width <= (settings.arrowPixelsFromEdge * 2);
  13221. },
  13222. },
  13223. is: {
  13224. closable: function() {
  13225. if(settings.closable == 'auto') {
  13226. if(settings.on == 'hover') {
  13227. return false;
  13228. }
  13229. return true;
  13230. }
  13231. return settings.closable;
  13232. },
  13233. offstage: function(distanceFromBoundary, position) {
  13234. var
  13235. offstage = []
  13236. ;
  13237. // return boundaries that have been surpassed
  13238. $.each(distanceFromBoundary, function(direction, distance) {
  13239. if(distance < -settings.jitter) {
  13240. module.debug('Position exceeds allowable distance from edge', direction, distance, position);
  13241. offstage.push(direction);
  13242. }
  13243. });
  13244. if(offstage.length > 0) {
  13245. return true;
  13246. }
  13247. else {
  13248. return false;
  13249. }
  13250. },
  13251. svg: function(element) {
  13252. return module.supports.svg() && (element instanceof SVGGraphicsElement);
  13253. },
  13254. basic: function() {
  13255. return $module.hasClass(className.basic);
  13256. },
  13257. active: function() {
  13258. return $module.hasClass(className.active);
  13259. },
  13260. animating: function() {
  13261. return ($popup !== undefined && $popup.hasClass(className.animating) );
  13262. },
  13263. fluid: function() {
  13264. return ($popup !== undefined && $popup.hasClass(className.fluid));
  13265. },
  13266. visible: function() {
  13267. return ($popup !== undefined && $popup.hasClass(className.popupVisible));
  13268. },
  13269. dropdown: function() {
  13270. return $module.hasClass(className.dropdown);
  13271. },
  13272. hidden: function() {
  13273. return !module.is.visible();
  13274. },
  13275. rtl: function () {
  13276. return $module.attr('dir') === 'rtl' || $module.css('direction') === 'rtl';
  13277. }
  13278. },
  13279. reset: function() {
  13280. module.remove.visible();
  13281. if(settings.preserve) {
  13282. if($.fn.transition !== undefined) {
  13283. $popup
  13284. .transition('remove transition')
  13285. ;
  13286. }
  13287. }
  13288. else {
  13289. module.removePopup();
  13290. }
  13291. },
  13292. setting: function(name, value) {
  13293. if( $.isPlainObject(name) ) {
  13294. $.extend(true, settings, name);
  13295. }
  13296. else if(value !== undefined) {
  13297. settings[name] = value;
  13298. }
  13299. else {
  13300. return settings[name];
  13301. }
  13302. },
  13303. internal: function(name, value) {
  13304. if( $.isPlainObject(name) ) {
  13305. $.extend(true, module, name);
  13306. }
  13307. else if(value !== undefined) {
  13308. module[name] = value;
  13309. }
  13310. else {
  13311. return module[name];
  13312. }
  13313. },
  13314. debug: function() {
  13315. if(!settings.silent && settings.debug) {
  13316. if(settings.performance) {
  13317. module.performance.log(arguments);
  13318. }
  13319. else {
  13320. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13321. module.debug.apply(console, arguments);
  13322. }
  13323. }
  13324. },
  13325. verbose: function() {
  13326. if(!settings.silent && settings.verbose && settings.debug) {
  13327. if(settings.performance) {
  13328. module.performance.log(arguments);
  13329. }
  13330. else {
  13331. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13332. module.verbose.apply(console, arguments);
  13333. }
  13334. }
  13335. },
  13336. error: function() {
  13337. if(!settings.silent) {
  13338. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  13339. module.error.apply(console, arguments);
  13340. }
  13341. },
  13342. performance: {
  13343. log: function(message) {
  13344. var
  13345. currentTime,
  13346. executionTime,
  13347. previousTime
  13348. ;
  13349. if(settings.performance) {
  13350. currentTime = new Date().getTime();
  13351. previousTime = time || currentTime;
  13352. executionTime = currentTime - previousTime;
  13353. time = currentTime;
  13354. performance.push({
  13355. 'Name' : message[0],
  13356. 'Arguments' : [].slice.call(message, 1) || '',
  13357. 'Element' : element,
  13358. 'Execution Time' : executionTime
  13359. });
  13360. }
  13361. clearTimeout(module.performance.timer);
  13362. module.performance.timer = setTimeout(module.performance.display, 500);
  13363. },
  13364. display: function() {
  13365. var
  13366. title = settings.name + ':',
  13367. totalTime = 0
  13368. ;
  13369. time = false;
  13370. clearTimeout(module.performance.timer);
  13371. $.each(performance, function(index, data) {
  13372. totalTime += data['Execution Time'];
  13373. });
  13374. title += ' ' + totalTime + 'ms';
  13375. if(moduleSelector) {
  13376. title += ' \'' + moduleSelector + '\'';
  13377. }
  13378. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  13379. console.groupCollapsed(title);
  13380. if(console.table) {
  13381. console.table(performance);
  13382. }
  13383. else {
  13384. $.each(performance, function(index, data) {
  13385. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  13386. });
  13387. }
  13388. console.groupEnd();
  13389. }
  13390. performance = [];
  13391. }
  13392. },
  13393. invoke: function(query, passedArguments, context) {
  13394. var
  13395. object = instance,
  13396. maxDepth,
  13397. found,
  13398. response
  13399. ;
  13400. passedArguments = passedArguments || queryArguments;
  13401. context = element || context;
  13402. if(typeof query == 'string' && object !== undefined) {
  13403. query = query.split(/[\. ]/);
  13404. maxDepth = query.length - 1;
  13405. $.each(query, function(depth, value) {
  13406. var camelCaseValue = (depth != maxDepth)
  13407. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  13408. : query
  13409. ;
  13410. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  13411. object = object[camelCaseValue];
  13412. }
  13413. else if( object[camelCaseValue] !== undefined ) {
  13414. found = object[camelCaseValue];
  13415. return false;
  13416. }
  13417. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  13418. object = object[value];
  13419. }
  13420. else if( object[value] !== undefined ) {
  13421. found = object[value];
  13422. return false;
  13423. }
  13424. else {
  13425. return false;
  13426. }
  13427. });
  13428. }
  13429. if ( $.isFunction( found ) ) {
  13430. response = found.apply(context, passedArguments);
  13431. }
  13432. else if(found !== undefined) {
  13433. response = found;
  13434. }
  13435. if(Array.isArray(returnedValue)) {
  13436. returnedValue.push(response);
  13437. }
  13438. else if(returnedValue !== undefined) {
  13439. returnedValue = [returnedValue, response];
  13440. }
  13441. else if(response !== undefined) {
  13442. returnedValue = response;
  13443. }
  13444. return found;
  13445. }
  13446. };
  13447. if(methodInvoked) {
  13448. if(instance === undefined) {
  13449. module.initialize();
  13450. }
  13451. module.invoke(query);
  13452. }
  13453. else {
  13454. if(instance !== undefined) {
  13455. instance.invoke('destroy');
  13456. }
  13457. module.initialize();
  13458. }
  13459. })
  13460. ;
  13461. return (returnedValue !== undefined)
  13462. ? returnedValue
  13463. : this
  13464. ;
  13465. };
  13466. $.fn.popup.settings = {
  13467. name : 'Popup',
  13468. // module settings
  13469. silent : false,
  13470. debug : false,
  13471. verbose : false,
  13472. performance : true,
  13473. namespace : 'popup',
  13474. // whether it should use dom mutation observers
  13475. observeChanges : true,
  13476. // callback only when element added to dom
  13477. onCreate : function(){},
  13478. // callback before element removed from dom
  13479. onRemove : function(){},
  13480. // callback before show animation
  13481. onShow : function(){},
  13482. // callback after show animation
  13483. onVisible : function(){},
  13484. // callback before hide animation
  13485. onHide : function(){},
  13486. // callback when popup cannot be positioned in visible screen
  13487. onUnplaceable : function(){},
  13488. // callback after hide animation
  13489. onHidden : function(){},
  13490. // when to show popup
  13491. on : 'hover',
  13492. // element to use to determine if popup is out of boundary
  13493. boundary : window,
  13494. // whether to add touchstart events when using hover
  13495. addTouchEvents : true,
  13496. // default position relative to element
  13497. position : 'top left',
  13498. // if given position should be used regardless if popup fits
  13499. forcePosition : false,
  13500. // name of variation to use
  13501. variation : '',
  13502. // whether popup should be moved to context
  13503. movePopup : true,
  13504. // element which popup should be relative to
  13505. target : false,
  13506. // jq selector or element that should be used as popup
  13507. popup : false,
  13508. // popup should remain inline next to activator
  13509. inline : false,
  13510. // popup should be removed from page on hide
  13511. preserve : false,
  13512. // popup should not close when being hovered on
  13513. hoverable : false,
  13514. // explicitly set content
  13515. content : false,
  13516. // explicitly set html
  13517. html : false,
  13518. // explicitly set title
  13519. title : false,
  13520. // whether automatically close on clickaway when on click
  13521. closable : true,
  13522. // automatically hide on scroll
  13523. hideOnScroll : 'auto',
  13524. // hide other popups on show
  13525. exclusive : false,
  13526. // context to attach popups
  13527. context : 'body',
  13528. // context for binding scroll events
  13529. scrollContext : window,
  13530. // position to prefer when calculating new position
  13531. prefer : 'opposite',
  13532. // specify position to appear even if it doesn't fit
  13533. lastResort : false,
  13534. // number of pixels from edge of popup to pointing arrow center (used from centering)
  13535. arrowPixelsFromEdge: 20,
  13536. // delay used to prevent accidental refiring of animations due to user error
  13537. delay : {
  13538. show : 50,
  13539. hide : 70
  13540. },
  13541. // whether fluid variation should assign width explicitly
  13542. setFluidWidth : true,
  13543. // transition settings
  13544. duration : 200,
  13545. transition : 'scale',
  13546. // distance away from activating element in px
  13547. distanceAway : 0,
  13548. // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
  13549. jitter : 2,
  13550. // offset on aligning axis from calculated position
  13551. offset : 0,
  13552. // maximum times to look for a position before failing (9 positions total)
  13553. maxSearchDepth : 15,
  13554. error: {
  13555. invalidPosition : 'The position you specified is not a valid position',
  13556. cannotPlace : 'Popup does not fit within the boundaries of the viewport',
  13557. method : 'The method you called is not defined.',
  13558. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  13559. notFound : 'The target or popup you specified does not exist on the page'
  13560. },
  13561. metadata: {
  13562. activator : 'activator',
  13563. content : 'content',
  13564. html : 'html',
  13565. offset : 'offset',
  13566. position : 'position',
  13567. title : 'title',
  13568. variation : 'variation'
  13569. },
  13570. className : {
  13571. active : 'active',
  13572. basic : 'basic',
  13573. animating : 'animating',
  13574. dropdown : 'dropdown',
  13575. fluid : 'fluid',
  13576. loading : 'loading',
  13577. popup : 'ui popup',
  13578. position : 'top left center bottom right',
  13579. visible : 'visible',
  13580. popupVisible : 'visible'
  13581. },
  13582. selector : {
  13583. popup : '.ui.popup'
  13584. },
  13585. templates: {
  13586. escape: function(string) {
  13587. var
  13588. badChars = /[<>"'`]/g,
  13589. shouldEscape = /[&<>"'`]/,
  13590. escape = {
  13591. "<": "&lt;",
  13592. ">": "&gt;",
  13593. '"': "&quot;",
  13594. "'": "&#x27;",
  13595. "`": "&#x60;"
  13596. },
  13597. escapedChar = function(chr) {
  13598. return escape[chr];
  13599. }
  13600. ;
  13601. if(shouldEscape.test(string)) {
  13602. string = string.replace(/&(?![a-z0-9#]{1,6};)/, "&amp;");
  13603. return string.replace(badChars, escapedChar);
  13604. }
  13605. return string;
  13606. },
  13607. popup: function(text) {
  13608. var
  13609. html = '',
  13610. escape = $.fn.popup.settings.templates.escape
  13611. ;
  13612. if(typeof text !== undefined) {
  13613. if(typeof text.title !== undefined && text.title) {
  13614. text.title = escape(text.title);
  13615. html += '<div class="header">' + text.title + '</div>';
  13616. }
  13617. if(typeof text.content !== undefined && text.content) {
  13618. text.content = escape(text.content);
  13619. html += '<div class="content">' + text.content + '</div>';
  13620. }
  13621. }
  13622. return html;
  13623. }
  13624. }
  13625. };
  13626. })( jQuery, window, document );
  13627. /*!
  13628. * # Fomantic-UI - Progress
  13629. * http://github.com/fomantic/Fomantic-UI/
  13630. *
  13631. *
  13632. * Released under the MIT license
  13633. * http://opensource.org/licenses/MIT
  13634. *
  13635. */
  13636. ;(function ($, window, document, undefined) {
  13637. 'use strict';
  13638. $.isFunction = $.isFunction || function(obj) {
  13639. return typeof obj === "function" && typeof obj.nodeType !== "number";
  13640. };
  13641. window = (typeof window != 'undefined' && window.Math == Math)
  13642. ? window
  13643. : (typeof self != 'undefined' && self.Math == Math)
  13644. ? self
  13645. : Function('return this')()
  13646. ;
  13647. $.fn.progress = function(parameters) {
  13648. var
  13649. $allModules = $(this),
  13650. moduleSelector = $allModules.selector || '',
  13651. time = new Date().getTime(),
  13652. performance = [],
  13653. query = arguments[0],
  13654. methodInvoked = (typeof query == 'string'),
  13655. queryArguments = [].slice.call(arguments, 1),
  13656. returnedValue
  13657. ;
  13658. $allModules
  13659. .each(function() {
  13660. var
  13661. settings = ( $.isPlainObject(parameters) )
  13662. ? $.extend(true, {}, $.fn.progress.settings, parameters)
  13663. : $.extend({}, $.fn.progress.settings),
  13664. className = settings.className,
  13665. metadata = settings.metadata,
  13666. namespace = settings.namespace,
  13667. selector = settings.selector,
  13668. error = settings.error,
  13669. eventNamespace = '.' + namespace,
  13670. moduleNamespace = 'module-' + namespace,
  13671. $module = $(this),
  13672. $bars = $(this).find(selector.bar),
  13673. $progresses = $(this).find(selector.progress),
  13674. $label = $(this).find(selector.label),
  13675. element = this,
  13676. instance = $module.data(moduleNamespace),
  13677. animating = false,
  13678. transitionEnd,
  13679. module
  13680. ;
  13681. module = {
  13682. helper: {
  13683. sum: function (nums) {
  13684. return Array.isArray(nums) ? nums.reduce(function (left, right) {
  13685. return left + Number(right);
  13686. }, 0) : 0;
  13687. },
  13688. /**
  13689. * Derive precision for multiple progress with total and values.
  13690. *
  13691. * This helper dervices a precision that is sufficiently large to show minimum value of multiple progress.
  13692. *
  13693. * Example1
  13694. * - total: 1122
  13695. * - values: [325, 111, 74, 612]
  13696. * - min ratio: 74/1122 = 0.0659...
  13697. * - required precision: 100
  13698. *
  13699. * Example2
  13700. * - total: 10541
  13701. * - values: [3235, 1111, 74, 6121]
  13702. * - min ratio: 74/10541 = 0.0070...
  13703. * - required precision: 1000
  13704. *
  13705. * @param min A minimum value within multiple values
  13706. * @param total A total amount of multiple values
  13707. * @returns {number} A precison. Could be 1, 10, 100, ... 1e+10.
  13708. */
  13709. derivePrecision: function(min, total) {
  13710. var precisionPower = 0
  13711. var precision = 1;
  13712. var ratio = min / total;
  13713. while (precisionPower < 10) {
  13714. ratio = ratio * precision;
  13715. if (ratio > 1) {
  13716. break;
  13717. }
  13718. precision = Math.pow(10, precisionPower++);
  13719. }
  13720. return precision;
  13721. },
  13722. forceArray: function (element) {
  13723. return Array.isArray(element)
  13724. ? element
  13725. : !isNaN(element)
  13726. ? [element]
  13727. : typeof element == 'string'
  13728. ? element.split(',')
  13729. : []
  13730. ;
  13731. }
  13732. },
  13733. initialize: function() {
  13734. module.set.duration();
  13735. module.set.transitionEvent();
  13736. module.debug(element);
  13737. module.read.metadata();
  13738. module.read.settings();
  13739. module.instantiate();
  13740. },
  13741. instantiate: function() {
  13742. module.verbose('Storing instance of progress', module);
  13743. instance = module;
  13744. $module
  13745. .data(moduleNamespace, module)
  13746. ;
  13747. },
  13748. destroy: function() {
  13749. module.verbose('Destroying previous progress for', $module);
  13750. clearInterval(instance.interval);
  13751. module.remove.state();
  13752. $module.removeData(moduleNamespace);
  13753. instance = undefined;
  13754. },
  13755. reset: function() {
  13756. module.remove.nextValue();
  13757. module.update.progress(0);
  13758. },
  13759. complete: function(keepState) {
  13760. if(module.percent === undefined || module.percent < 100) {
  13761. module.remove.progressPoll();
  13762. if(keepState !== true){
  13763. module.set.percent(100);
  13764. }
  13765. }
  13766. },
  13767. read: {
  13768. metadata: function() {
  13769. var
  13770. data = {
  13771. percent : module.helper.forceArray($module.data(metadata.percent)),
  13772. total : $module.data(metadata.total),
  13773. value : module.helper.forceArray($module.data(metadata.value))
  13774. }
  13775. ;
  13776. if(data.total) {
  13777. module.debug('Total value set from metadata', data.total);
  13778. module.set.total(data.total);
  13779. }
  13780. if(data.value.length > 0) {
  13781. module.debug('Current value set from metadata', data.value);
  13782. module.set.value(data.value);
  13783. module.set.progress(data.value);
  13784. }
  13785. if(data.percent.length > 0) {
  13786. module.debug('Current percent value set from metadata', data.percent);
  13787. module.set.percent(data.percent);
  13788. }
  13789. },
  13790. settings: function() {
  13791. if(settings.total !== false) {
  13792. module.debug('Current total set in settings', settings.total);
  13793. module.set.total(settings.total);
  13794. }
  13795. if(settings.value !== false) {
  13796. module.debug('Current value set in settings', settings.value);
  13797. module.set.value(settings.value);
  13798. module.set.progress(module.value);
  13799. }
  13800. if(settings.percent !== false) {
  13801. module.debug('Current percent set in settings', settings.percent);
  13802. module.set.percent(settings.percent);
  13803. }
  13804. }
  13805. },
  13806. bind: {
  13807. transitionEnd: function(callback) {
  13808. var
  13809. transitionEnd = module.get.transitionEnd()
  13810. ;
  13811. $bars
  13812. .one(transitionEnd + eventNamespace, function(event) {
  13813. clearTimeout(module.failSafeTimer);
  13814. callback.call(this, event);
  13815. })
  13816. ;
  13817. module.failSafeTimer = setTimeout(function() {
  13818. $bars.triggerHandler(transitionEnd);
  13819. }, settings.duration + settings.failSafeDelay);
  13820. module.verbose('Adding fail safe timer', module.timer);
  13821. }
  13822. },
  13823. increment: function(incrementValue) {
  13824. var
  13825. startValue,
  13826. newValue
  13827. ;
  13828. if( module.has.total() ) {
  13829. startValue = module.get.value();
  13830. incrementValue = incrementValue || 1;
  13831. }
  13832. else {
  13833. startValue = module.get.percent();
  13834. incrementValue = incrementValue || module.get.randomValue();
  13835. }
  13836. newValue = startValue + incrementValue;
  13837. module.debug('Incrementing percentage by', startValue, newValue, incrementValue);
  13838. newValue = module.get.normalizedValue(newValue);
  13839. module.set.progress(newValue);
  13840. },
  13841. decrement: function(decrementValue) {
  13842. var
  13843. total = module.get.total(),
  13844. startValue,
  13845. newValue
  13846. ;
  13847. if(total) {
  13848. startValue = module.get.value();
  13849. decrementValue = decrementValue || 1;
  13850. newValue = startValue - decrementValue;
  13851. module.debug('Decrementing value by', decrementValue, startValue);
  13852. }
  13853. else {
  13854. startValue = module.get.percent();
  13855. decrementValue = decrementValue || module.get.randomValue();
  13856. newValue = startValue - decrementValue;
  13857. module.debug('Decrementing percentage by', decrementValue, startValue);
  13858. }
  13859. newValue = module.get.normalizedValue(newValue);
  13860. module.set.progress(newValue);
  13861. },
  13862. has: {
  13863. progressPoll: function() {
  13864. return module.progressPoll;
  13865. },
  13866. total: function() {
  13867. return (module.get.total() !== false);
  13868. }
  13869. },
  13870. get: {
  13871. text: function(templateText, index) {
  13872. var
  13873. index_ = index || 0,
  13874. value = module.get.value(index_),
  13875. total = module.total || 0,
  13876. percent = (animating)
  13877. ? module.get.displayPercent(index_)
  13878. : module.get.percent(index_),
  13879. left = (module.total > 0)
  13880. ? (total - value)
  13881. : (100 - percent)
  13882. ;
  13883. templateText = templateText || '';
  13884. templateText = templateText
  13885. .replace('{value}', value)
  13886. .replace('{total}', total)
  13887. .replace('{left}', left)
  13888. .replace('{percent}', percent)
  13889. .replace('{bar}', settings.text.bars[index_] || '')
  13890. ;
  13891. module.verbose('Adding variables to progress bar text', templateText);
  13892. return templateText;
  13893. },
  13894. normalizedValue: function(value) {
  13895. if(value < 0) {
  13896. module.debug('Value cannot decrement below 0');
  13897. return 0;
  13898. }
  13899. if(module.has.total()) {
  13900. if(value > module.total) {
  13901. module.debug('Value cannot increment above total', module.total);
  13902. return module.total;
  13903. }
  13904. }
  13905. else if(value > 100 ) {
  13906. module.debug('Value cannot increment above 100 percent');
  13907. return 100;
  13908. }
  13909. return value;
  13910. },
  13911. updateInterval: function() {
  13912. if(settings.updateInterval == 'auto') {
  13913. return settings.duration;
  13914. }
  13915. return settings.updateInterval;
  13916. },
  13917. randomValue: function() {
  13918. module.debug('Generating random increment percentage');
  13919. return Math.floor((Math.random() * settings.random.max) + settings.random.min);
  13920. },
  13921. numericValue: function(value) {
  13922. return (typeof value === 'string')
  13923. ? (value.replace(/[^\d.]/g, '') !== '')
  13924. ? +(value.replace(/[^\d.]/g, ''))
  13925. : false
  13926. : value
  13927. ;
  13928. },
  13929. transitionEnd: function() {
  13930. var
  13931. element = document.createElement('element'),
  13932. transitions = {
  13933. 'transition' :'transitionend',
  13934. 'OTransition' :'oTransitionEnd',
  13935. 'MozTransition' :'transitionend',
  13936. 'WebkitTransition' :'webkitTransitionEnd'
  13937. },
  13938. transition
  13939. ;
  13940. for(transition in transitions){
  13941. if( element.style[transition] !== undefined ){
  13942. return transitions[transition];
  13943. }
  13944. }
  13945. },
  13946. // gets current displayed percentage (if animating values this is the intermediary value)
  13947. displayPercent: function(index) {
  13948. var
  13949. $bar = $($bars[index]),
  13950. barWidth = $bar.width(),
  13951. totalWidth = $module.width(),
  13952. minDisplay = parseInt($bar.css('min-width'), 10),
  13953. displayPercent = (barWidth > minDisplay)
  13954. ? (barWidth / totalWidth * 100)
  13955. : module.percent
  13956. ;
  13957. return (settings.precision > 0)
  13958. ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
  13959. : Math.round(displayPercent)
  13960. ;
  13961. },
  13962. percent: function(index) {
  13963. return module.percent && module.percent[index || 0] || 0;
  13964. },
  13965. value: function(index) {
  13966. return module.nextValue || module.value && module.value[index || 0] || 0;
  13967. },
  13968. total: function() {
  13969. return module.total || false;
  13970. }
  13971. },
  13972. create: {
  13973. progressPoll: function() {
  13974. module.progressPoll = setTimeout(function() {
  13975. module.update.toNextValue();
  13976. module.remove.progressPoll();
  13977. }, module.get.updateInterval());
  13978. },
  13979. },
  13980. is: {
  13981. complete: function() {
  13982. return module.is.success() || module.is.warning() || module.is.error();
  13983. },
  13984. success: function() {
  13985. return $module.hasClass(className.success);
  13986. },
  13987. warning: function() {
  13988. return $module.hasClass(className.warning);
  13989. },
  13990. error: function() {
  13991. return $module.hasClass(className.error);
  13992. },
  13993. active: function() {
  13994. return $module.hasClass(className.active);
  13995. },
  13996. visible: function() {
  13997. return $module.is(':visible');
  13998. }
  13999. },
  14000. remove: {
  14001. progressPoll: function() {
  14002. module.verbose('Removing progress poll timer');
  14003. if(module.progressPoll) {
  14004. clearTimeout(module.progressPoll);
  14005. delete module.progressPoll;
  14006. }
  14007. },
  14008. nextValue: function() {
  14009. module.verbose('Removing progress value stored for next update');
  14010. delete module.nextValue;
  14011. },
  14012. state: function() {
  14013. module.verbose('Removing stored state');
  14014. delete module.total;
  14015. delete module.percent;
  14016. delete module.value;
  14017. },
  14018. active: function() {
  14019. module.verbose('Removing active state');
  14020. $module.removeClass(className.active);
  14021. },
  14022. success: function() {
  14023. module.verbose('Removing success state');
  14024. $module.removeClass(className.success);
  14025. },
  14026. warning: function() {
  14027. module.verbose('Removing warning state');
  14028. $module.removeClass(className.warning);
  14029. },
  14030. error: function() {
  14031. module.verbose('Removing error state');
  14032. $module.removeClass(className.error);
  14033. }
  14034. },
  14035. set: {
  14036. barWidth: function(values) {
  14037. module.debug("set bar width with ", values);
  14038. values = module.helper.forceArray(values);
  14039. var firstNonZeroIndex = -1;
  14040. var lastNonZeroIndex = -1;
  14041. var valuesSum = module.helper.sum(values);
  14042. var barCounts = $bars.length;
  14043. var isMultiple = barCounts > 1;
  14044. var percents = values.map(function(value, index) {
  14045. var allZero = (index === barCounts - 1 && valuesSum === 0);
  14046. var $bar = $($bars[index]);
  14047. if (value === 0 && isMultiple && !allZero) {
  14048. $bar.css('display', 'none');
  14049. } else {
  14050. if (isMultiple && allZero) {
  14051. $bar.css('background', 'transparent');
  14052. }
  14053. if (firstNonZeroIndex == -1) {
  14054. firstNonZeroIndex = index;
  14055. }
  14056. lastNonZeroIndex = index;
  14057. $bar.css({
  14058. display: 'block',
  14059. width: value + '%'
  14060. });
  14061. }
  14062. return parseFloat(value);
  14063. });
  14064. values.forEach(function(_, index) {
  14065. var $bar = $($bars[index]);
  14066. $bar.css({
  14067. borderTopLeftRadius: index == firstNonZeroIndex ? '' : 0,
  14068. borderBottomLeftRadius: index == firstNonZeroIndex ? '' : 0,
  14069. borderTopRightRadius: index == lastNonZeroIndex ? '' : 0,
  14070. borderBottomRightRadius: index == lastNonZeroIndex ? '' : 0
  14071. });
  14072. });
  14073. $module
  14074. .attr('data-percent', percents)
  14075. ;
  14076. },
  14077. duration: function(duration) {
  14078. duration = duration || settings.duration;
  14079. duration = (typeof duration == 'number')
  14080. ? duration + 'ms'
  14081. : duration
  14082. ;
  14083. module.verbose('Setting progress bar transition duration', duration);
  14084. $bars
  14085. .css({
  14086. 'transition-duration': duration
  14087. })
  14088. ;
  14089. },
  14090. percent: function(percents) {
  14091. percents = module.helper.forceArray(percents).map(function(percent) {
  14092. return (typeof percent == 'string')
  14093. ? +(percent.replace('%', ''))
  14094. : percent
  14095. ;
  14096. });
  14097. var hasTotal = module.has.total();
  14098. var totalPecent = module.helper.sum(percents);
  14099. var isMultpleValues = percents.length > 1 && hasTotal;
  14100. var sumTotal = module.helper.sum(module.helper.forceArray(module.value));
  14101. if (isMultpleValues && sumTotal > module.total) {
  14102. // Sum values instead of pecents to avoid precision issues when summing floats
  14103. module.error(error.sumExceedsTotal, sumTotal, module.total);
  14104. } else if (!isMultpleValues && totalPecent > 100) {
  14105. // Sum before rouding since sum of rounded may have error though sum of actual is fine
  14106. module.error(error.tooHigh, totalPecent);
  14107. } else if (totalPecent < 0) {
  14108. module.error(error.tooLow, totalPecent);
  14109. } else {
  14110. var autoPrecision = settings.precision > 0
  14111. ? settings.precision
  14112. : isMultpleValues
  14113. ? module.helper.derivePrecision(Math.min.apply(null, module.value), module.total)
  14114. : undefined;
  14115. // round display percentage
  14116. var roundedPercents = percents.map(function (percent) {
  14117. return (autoPrecision > 0)
  14118. ? Math.round(percent * (10 * autoPrecision)) / (10 * autoPrecision)
  14119. : Math.round(percent)
  14120. ;
  14121. });
  14122. module.percent = roundedPercents;
  14123. if (!hasTotal) {
  14124. module.value = roundedPercents.map(function (percent) {
  14125. return (autoPrecision > 0)
  14126. ? Math.round((percent / 100) * module.total * (10 * autoPrecision)) / (10 * autoPrecision)
  14127. : Math.round((percent / 100) * module.total * 10) / 10
  14128. ;
  14129. });
  14130. if (settings.limitValues) {
  14131. module.value = module.value.map(function (value) {
  14132. return (value > 100)
  14133. ? 100
  14134. : (module.value < 0)
  14135. ? 0
  14136. : module.value;
  14137. });
  14138. }
  14139. }
  14140. module.set.barWidth(percents);
  14141. module.set.labelInterval();
  14142. module.set.labels();
  14143. }
  14144. settings.onChange.call(element, percents, module.value, module.total);
  14145. },
  14146. labelInterval: function() {
  14147. var
  14148. animationCallback = function() {
  14149. module.verbose('Bar finished animating, removing continuous label updates');
  14150. clearInterval(module.interval);
  14151. animating = false;
  14152. module.set.labels();
  14153. }
  14154. ;
  14155. clearInterval(module.interval);
  14156. module.bind.transitionEnd(animationCallback);
  14157. animating = true;
  14158. module.interval = setInterval(function() {
  14159. var
  14160. isInDOM = $.contains(document.documentElement, element)
  14161. ;
  14162. if(!isInDOM) {
  14163. clearInterval(module.interval);
  14164. animating = false;
  14165. }
  14166. module.set.labels();
  14167. }, settings.framerate);
  14168. },
  14169. labels: function() {
  14170. module.verbose('Setting both bar progress and outer label text');
  14171. module.set.barLabel();
  14172. module.set.state();
  14173. },
  14174. label: function(text) {
  14175. text = text || '';
  14176. if(text) {
  14177. text = module.get.text(text);
  14178. module.verbose('Setting label to text', text);
  14179. $label.text(text);
  14180. }
  14181. },
  14182. state: function(percent) {
  14183. percent = (percent !== undefined)
  14184. ? percent
  14185. : module.helper.sum(module.percent)
  14186. ;
  14187. if(percent === 100) {
  14188. if(settings.autoSuccess && $bars.length === 1 && !(module.is.warning() || module.is.error() || module.is.success())) {
  14189. module.set.success();
  14190. module.debug('Automatically triggering success at 100%');
  14191. }
  14192. else {
  14193. module.verbose('Reached 100% removing active state');
  14194. module.remove.active();
  14195. module.remove.progressPoll();
  14196. }
  14197. }
  14198. else if(percent > 0) {
  14199. module.verbose('Adjusting active progress bar label', percent);
  14200. module.set.active();
  14201. }
  14202. else {
  14203. module.remove.active();
  14204. module.set.label(settings.text.active);
  14205. }
  14206. },
  14207. barLabel: function(text) {
  14208. $progresses.map(function(index, element){
  14209. var $progress = $(element);
  14210. if (text !== undefined) {
  14211. $progress.text( module.get.text(text, index) );
  14212. }
  14213. else if (settings.label == 'ratio' && module.total) {
  14214. module.verbose('Adding ratio to bar label');
  14215. $progress.text( module.get.text(settings.text.ratio, index) );
  14216. }
  14217. else if (settings.label == 'percent') {
  14218. module.verbose('Adding percentage to bar label');
  14219. $progress.text( module.get.text(settings.text.percent, index) );
  14220. }
  14221. });
  14222. },
  14223. active: function(text) {
  14224. text = text || settings.text.active;
  14225. module.debug('Setting active state');
  14226. if(settings.showActivity && !module.is.active() ) {
  14227. $module.addClass(className.active);
  14228. }
  14229. module.remove.warning();
  14230. module.remove.error();
  14231. module.remove.success();
  14232. text = settings.onLabelUpdate('active', text, module.value, module.total);
  14233. if(text) {
  14234. module.set.label(text);
  14235. }
  14236. module.bind.transitionEnd(function() {
  14237. settings.onActive.call(element, module.value, module.total);
  14238. });
  14239. },
  14240. success : function(text, keepState) {
  14241. text = text || settings.text.success || settings.text.active;
  14242. module.debug('Setting success state');
  14243. $module.addClass(className.success);
  14244. module.remove.active();
  14245. module.remove.warning();
  14246. module.remove.error();
  14247. module.complete(keepState);
  14248. if(settings.text.success) {
  14249. text = settings.onLabelUpdate('success', text, module.value, module.total);
  14250. module.set.label(text);
  14251. }
  14252. else {
  14253. text = settings.onLabelUpdate('active', text, module.value, module.total);
  14254. module.set.label(text);
  14255. }
  14256. module.bind.transitionEnd(function() {
  14257. settings.onSuccess.call(element, module.total);
  14258. });
  14259. },
  14260. warning : function(text, keepState) {
  14261. text = text || settings.text.warning;
  14262. module.debug('Setting warning state');
  14263. $module.addClass(className.warning);
  14264. module.remove.active();
  14265. module.remove.success();
  14266. module.remove.error();
  14267. module.complete(keepState);
  14268. text = settings.onLabelUpdate('warning', text, module.value, module.total);
  14269. if(text) {
  14270. module.set.label(text);
  14271. }
  14272. module.bind.transitionEnd(function() {
  14273. settings.onWarning.call(element, module.value, module.total);
  14274. });
  14275. },
  14276. error : function(text, keepState) {
  14277. text = text || settings.text.error;
  14278. module.debug('Setting error state');
  14279. $module.addClass(className.error);
  14280. module.remove.active();
  14281. module.remove.success();
  14282. module.remove.warning();
  14283. module.complete(keepState);
  14284. text = settings.onLabelUpdate('error', text, module.value, module.total);
  14285. if(text) {
  14286. module.set.label(text);
  14287. }
  14288. module.bind.transitionEnd(function() {
  14289. settings.onError.call(element, module.value, module.total);
  14290. });
  14291. },
  14292. transitionEvent: function() {
  14293. transitionEnd = module.get.transitionEnd();
  14294. },
  14295. total: function(totalValue) {
  14296. module.total = totalValue;
  14297. },
  14298. value: function(value) {
  14299. module.value = module.helper.forceArray(value);
  14300. },
  14301. progress: function(value) {
  14302. if(!module.has.progressPoll()) {
  14303. module.debug('First update in progress update interval, immediately updating', value);
  14304. module.update.progress(value);
  14305. module.create.progressPoll();
  14306. }
  14307. else {
  14308. module.debug('Updated within interval, setting next update to use new value', value);
  14309. module.set.nextValue(value);
  14310. }
  14311. },
  14312. nextValue: function(value) {
  14313. module.nextValue = value;
  14314. }
  14315. },
  14316. update: {
  14317. toNextValue: function() {
  14318. var
  14319. nextValue = module.nextValue
  14320. ;
  14321. if(nextValue) {
  14322. module.debug('Update interval complete using last updated value', nextValue);
  14323. module.update.progress(nextValue);
  14324. module.remove.nextValue();
  14325. }
  14326. },
  14327. progress: function(values) {
  14328. var hasTotal = module.has.total();
  14329. if (hasTotal) {
  14330. module.set.value(values);
  14331. }
  14332. var percentCompletes = module.helper.forceArray(values).map(function(value) {
  14333. var
  14334. percentComplete
  14335. ;
  14336. value = module.get.numericValue(value);
  14337. if (value === false) {
  14338. module.error(error.nonNumeric, value);
  14339. }
  14340. value = module.get.normalizedValue(value);
  14341. if (hasTotal) {
  14342. percentComplete = (value / module.total) * 100;
  14343. module.debug('Calculating percent complete from total', percentComplete);
  14344. }
  14345. else {
  14346. percentComplete = value;
  14347. module.debug('Setting value to exact percentage value', percentComplete);
  14348. }
  14349. return percentComplete;
  14350. });
  14351. module.set.percent( percentCompletes );
  14352. }
  14353. },
  14354. setting: function(name, value) {
  14355. module.debug('Changing setting', name, value);
  14356. if( $.isPlainObject(name) ) {
  14357. $.extend(true, settings, name);
  14358. }
  14359. else if(value !== undefined) {
  14360. if($.isPlainObject(settings[name])) {
  14361. $.extend(true, settings[name], value);
  14362. }
  14363. else {
  14364. settings[name] = value;
  14365. }
  14366. }
  14367. else {
  14368. return settings[name];
  14369. }
  14370. },
  14371. internal: function(name, value) {
  14372. if( $.isPlainObject(name) ) {
  14373. $.extend(true, module, name);
  14374. }
  14375. else if(value !== undefined) {
  14376. module[name] = value;
  14377. }
  14378. else {
  14379. return module[name];
  14380. }
  14381. },
  14382. debug: function() {
  14383. if(!settings.silent && settings.debug) {
  14384. if(settings.performance) {
  14385. module.performance.log(arguments);
  14386. }
  14387. else {
  14388. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14389. module.debug.apply(console, arguments);
  14390. }
  14391. }
  14392. },
  14393. verbose: function() {
  14394. if(!settings.silent && settings.verbose && settings.debug) {
  14395. if(settings.performance) {
  14396. module.performance.log(arguments);
  14397. }
  14398. else {
  14399. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14400. module.verbose.apply(console, arguments);
  14401. }
  14402. }
  14403. },
  14404. error: function() {
  14405. if(!settings.silent) {
  14406. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  14407. module.error.apply(console, arguments);
  14408. }
  14409. },
  14410. performance: {
  14411. log: function(message) {
  14412. var
  14413. currentTime,
  14414. executionTime,
  14415. previousTime
  14416. ;
  14417. if(settings.performance) {
  14418. currentTime = new Date().getTime();
  14419. previousTime = time || currentTime;
  14420. executionTime = currentTime - previousTime;
  14421. time = currentTime;
  14422. performance.push({
  14423. 'Name' : message[0],
  14424. 'Arguments' : [].slice.call(message, 1) || '',
  14425. 'Element' : element,
  14426. 'Execution Time' : executionTime
  14427. });
  14428. }
  14429. clearTimeout(module.performance.timer);
  14430. module.performance.timer = setTimeout(module.performance.display, 500);
  14431. },
  14432. display: function() {
  14433. var
  14434. title = settings.name + ':',
  14435. totalTime = 0
  14436. ;
  14437. time = false;
  14438. clearTimeout(module.performance.timer);
  14439. $.each(performance, function(index, data) {
  14440. totalTime += data['Execution Time'];
  14441. });
  14442. title += ' ' + totalTime + 'ms';
  14443. if(moduleSelector) {
  14444. title += ' \'' + moduleSelector + '\'';
  14445. }
  14446. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  14447. console.groupCollapsed(title);
  14448. if(console.table) {
  14449. console.table(performance);
  14450. }
  14451. else {
  14452. $.each(performance, function(index, data) {
  14453. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  14454. });
  14455. }
  14456. console.groupEnd();
  14457. }
  14458. performance = [];
  14459. }
  14460. },
  14461. invoke: function(query, passedArguments, context) {
  14462. var
  14463. object = instance,
  14464. maxDepth,
  14465. found,
  14466. response
  14467. ;
  14468. passedArguments = passedArguments || queryArguments;
  14469. context = element || context;
  14470. if(typeof query == 'string' && object !== undefined) {
  14471. query = query.split(/[\. ]/);
  14472. maxDepth = query.length - 1;
  14473. $.each(query, function(depth, value) {
  14474. var camelCaseValue = (depth != maxDepth)
  14475. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  14476. : query
  14477. ;
  14478. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  14479. object = object[camelCaseValue];
  14480. }
  14481. else if( object[camelCaseValue] !== undefined ) {
  14482. found = object[camelCaseValue];
  14483. return false;
  14484. }
  14485. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  14486. object = object[value];
  14487. }
  14488. else if( object[value] !== undefined ) {
  14489. found = object[value];
  14490. return false;
  14491. }
  14492. else {
  14493. module.error(error.method, query);
  14494. return false;
  14495. }
  14496. });
  14497. }
  14498. if ( $.isFunction( found ) ) {
  14499. response = found.apply(context, passedArguments);
  14500. }
  14501. else if(found !== undefined) {
  14502. response = found;
  14503. }
  14504. if(Array.isArray(returnedValue)) {
  14505. returnedValue.push(response);
  14506. }
  14507. else if(returnedValue !== undefined) {
  14508. returnedValue = [returnedValue, response];
  14509. }
  14510. else if(response !== undefined) {
  14511. returnedValue = response;
  14512. }
  14513. return found;
  14514. }
  14515. };
  14516. if(methodInvoked) {
  14517. if(instance === undefined) {
  14518. module.initialize();
  14519. }
  14520. module.invoke(query);
  14521. }
  14522. else {
  14523. if(instance !== undefined) {
  14524. instance.invoke('destroy');
  14525. }
  14526. module.initialize();
  14527. }
  14528. })
  14529. ;
  14530. return (returnedValue !== undefined)
  14531. ? returnedValue
  14532. : this
  14533. ;
  14534. };
  14535. $.fn.progress.settings = {
  14536. name : 'Progress',
  14537. namespace : 'progress',
  14538. silent : false,
  14539. debug : false,
  14540. verbose : false,
  14541. performance : true,
  14542. random : {
  14543. min : 2,
  14544. max : 5
  14545. },
  14546. duration : 300,
  14547. updateInterval : 'auto',
  14548. autoSuccess : true,
  14549. showActivity : true,
  14550. limitValues : true,
  14551. label : 'percent',
  14552. precision : 0,
  14553. framerate : (1000 / 30), /// 30 fps
  14554. percent : false,
  14555. total : false,
  14556. value : false,
  14557. // delay in ms for fail safe animation callback
  14558. failSafeDelay : 100,
  14559. onLabelUpdate : function(state, text, value, total){
  14560. return text;
  14561. },
  14562. onChange : function(percent, value, total){},
  14563. onSuccess : function(total){},
  14564. onActive : function(value, total){},
  14565. onError : function(value, total){},
  14566. onWarning : function(value, total){},
  14567. error : {
  14568. method : 'The method you called is not defined.',
  14569. nonNumeric : 'Progress value is non numeric',
  14570. tooHigh : 'Value specified is above 100%',
  14571. tooLow : 'Value specified is below 0%',
  14572. sumExceedsTotal : 'Sum of multple values exceed total',
  14573. },
  14574. regExp: {
  14575. variable: /\{\$*[A-z0-9]+\}/g
  14576. },
  14577. metadata: {
  14578. percent : 'percent',
  14579. total : 'total',
  14580. value : 'value'
  14581. },
  14582. selector : {
  14583. bar : '> .bar',
  14584. label : '> .label',
  14585. progress : '.bar > .progress'
  14586. },
  14587. text : {
  14588. active : false,
  14589. error : false,
  14590. success : false,
  14591. warning : false,
  14592. percent : '{percent}%',
  14593. ratio : '{value} of {total}',
  14594. bars : ['']
  14595. },
  14596. className : {
  14597. active : 'active',
  14598. error : 'error',
  14599. success : 'success',
  14600. warning : 'warning'
  14601. }
  14602. };
  14603. })( jQuery, window, document );
  14604. /*!
  14605. * # Fomantic-UI - Slider
  14606. * http://github.com/fomantic/Fomantic-UI/
  14607. *
  14608. *
  14609. * Released under the MIT license
  14610. * http://opensource.org/licenses/MIT
  14611. *
  14612. */
  14613. ;(function ( $, window, document, undefined ) {
  14614. "use strict";
  14615. window = (typeof window != 'undefined' && window.Math == Math)
  14616. ? window
  14617. : (typeof self != 'undefined' && self.Math == Math)
  14618. ? self
  14619. : Function('return this')()
  14620. ;
  14621. $.fn.slider = function(parameters) {
  14622. var
  14623. $allModules = $(this),
  14624. $window = $(window),
  14625. moduleSelector = $allModules.selector || '',
  14626. time = new Date().getTime(),
  14627. performance = [],
  14628. query = arguments[0],
  14629. methodInvoked = (typeof query == 'string'),
  14630. queryArguments = [].slice.call(arguments, 1),
  14631. alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
  14632. SINGLE_STEP = 1,
  14633. BIG_STEP = 2,
  14634. NO_STEP = 0,
  14635. SINGLE_BACKSTEP = -1,
  14636. BIG_BACKSTEP = -2,
  14637. // Used to manage document bound events.
  14638. // Use this so that we can distinguish between which document events are bound to which range.
  14639. currentRange = 0,
  14640. returnedValue
  14641. ;
  14642. $allModules
  14643. .each(function() {
  14644. var
  14645. settings = ( $.isPlainObject(parameters) )
  14646. ? $.extend(true, {}, $.fn.slider.settings, parameters)
  14647. : $.extend({}, $.fn.slider.settings),
  14648. className = settings.className,
  14649. metadata = settings.metadata,
  14650. namespace = settings.namespace,
  14651. error = settings.error,
  14652. keys = settings.keys,
  14653. interpretLabel = settings.interpretLabel,
  14654. isHover = false,
  14655. eventNamespace = '.' + namespace,
  14656. moduleNamespace = 'module-' + namespace,
  14657. $module = $(this),
  14658. $currThumb,
  14659. $thumb,
  14660. $secondThumb,
  14661. $track,
  14662. $trackFill,
  14663. $labels,
  14664. element = this,
  14665. instance = $module.data(moduleNamespace),
  14666. documentEventID,
  14667. value,
  14668. position,
  14669. secondPos,
  14670. offset,
  14671. precision,
  14672. isTouch,
  14673. gapRatio = 1,
  14674. initialPosition,
  14675. initialLoad,
  14676. module
  14677. ;
  14678. module = {
  14679. initialize: function() {
  14680. module.debug('Initializing slider', settings);
  14681. initialLoad = true;
  14682. currentRange += 1;
  14683. documentEventID = currentRange;
  14684. isTouch = module.setup.testOutTouch();
  14685. module.setup.layout();
  14686. module.setup.labels();
  14687. if(!module.is.disabled()) {
  14688. module.bind.events();
  14689. }
  14690. module.read.metadata();
  14691. module.read.settings();
  14692. initialLoad = false;
  14693. module.instantiate();
  14694. },
  14695. instantiate: function() {
  14696. module.verbose('Storing instance of slider', module);
  14697. instance = module;
  14698. $module
  14699. .data(moduleNamespace, module)
  14700. ;
  14701. },
  14702. destroy: function() {
  14703. module.verbose('Destroying previous slider for', $module);
  14704. clearInterval(instance.interval);
  14705. module.unbind.events();
  14706. module.unbind.slidingEvents();
  14707. $module.removeData(moduleNamespace);
  14708. instance = undefined;
  14709. },
  14710. setup: {
  14711. layout: function() {
  14712. if( $module.attr('tabindex') === undefined) {
  14713. $module.attr('tabindex', 0);
  14714. }
  14715. if($module.find('.inner').length == 0) {
  14716. $module.append("<div class='inner'>"
  14717. + "<div class='track'></div>"
  14718. + "<div class='track-fill'></div>"
  14719. + "<div class='thumb'></div>"
  14720. + "</div>");
  14721. }
  14722. precision = module.get.precision();
  14723. $thumb = $module.find('.thumb:not(.second)');
  14724. $currThumb = $thumb;
  14725. if(module.is.range()) {
  14726. if($module.find('.thumb.second').length == 0) {
  14727. $module.find('.inner').append("<div class='thumb second'></div>");
  14728. }
  14729. $secondThumb = $module.find('.thumb.second');
  14730. }
  14731. $track = $module.find('.track');
  14732. $trackFill = $module.find('.track-fill');
  14733. offset = $thumb.width() / 2;
  14734. },
  14735. labels: function() {
  14736. if(module.is.labeled()) {
  14737. $labels = $module.find('.labels:not(.auto)');
  14738. if($labels.length != 0) {
  14739. module.setup.customLabel();
  14740. } else {
  14741. module.setup.autoLabel();
  14742. }
  14743. if (settings.showLabelTicks) {
  14744. $module.addClass(className.ticked)
  14745. }
  14746. }
  14747. },
  14748. testOutTouch: function() {
  14749. try {
  14750. document.createEvent('TouchEvent');
  14751. return true;
  14752. } catch (e) {
  14753. return false;
  14754. }
  14755. },
  14756. customLabel: function() {
  14757. var
  14758. $children = $labels.find('.label'),
  14759. numChildren = $children.length,
  14760. min = module.get.min(),
  14761. max = module.get.max(),
  14762. ratio
  14763. ;
  14764. $children.each(function(index) {
  14765. var
  14766. $child = $(this),
  14767. attrValue = $child.attr('data-value')
  14768. ;
  14769. if(attrValue) {
  14770. attrValue = attrValue > max ? max : attrValue < min ? min : attrValue;
  14771. ratio = (attrValue - min) / (max - min);
  14772. } else {
  14773. ratio = (index + 1) / (numChildren + 1);
  14774. }
  14775. module.update.labelPosition(ratio, $(this));
  14776. });
  14777. },
  14778. autoLabel: function() {
  14779. if(module.get.step() != 0) {
  14780. $labels = $module.find('.labels');
  14781. if($labels.length != 0) {
  14782. $labels.empty();
  14783. }
  14784. else {
  14785. $labels = $module.append('<ul class="auto labels"></ul>').find('.labels');
  14786. }
  14787. for(var i = 0, len = module.get.numLabels(); i <= len; i++) {
  14788. var
  14789. labelText = module.get.label(i),
  14790. $label = (labelText !== "")
  14791. ? !(i % module.get.gapRatio())
  14792. ? $('<li class="label">' + labelText + '</li>')
  14793. : $('<li class="halftick label"></li>')
  14794. : null,
  14795. ratio = i / len
  14796. ;
  14797. if($label) {
  14798. module.update.labelPosition(ratio, $label);
  14799. $labels.append($label);
  14800. }
  14801. }
  14802. }
  14803. }
  14804. },
  14805. bind: {
  14806. events: function() {
  14807. module.bind.globalKeyboardEvents();
  14808. module.bind.keyboardEvents();
  14809. module.bind.mouseEvents();
  14810. if(module.is.touch()) {
  14811. module.bind.touchEvents();
  14812. }
  14813. if (settings.autoAdjustLabels) {
  14814. module.bind.windowEvents();
  14815. }
  14816. },
  14817. keyboardEvents: function() {
  14818. module.verbose('Binding keyboard events');
  14819. $module.on('keydown' + eventNamespace, module.event.keydown);
  14820. },
  14821. globalKeyboardEvents: function() {
  14822. $(document).on('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
  14823. },
  14824. mouseEvents: function() {
  14825. module.verbose('Binding mouse events');
  14826. $module.find('.track, .thumb, .inner').on('mousedown' + eventNamespace, function(event) {
  14827. event.stopImmediatePropagation();
  14828. event.preventDefault();
  14829. module.event.down(event);
  14830. });
  14831. $module.on('mousedown' + eventNamespace, module.event.down);
  14832. $module.on('mouseenter' + eventNamespace, function(event) {
  14833. isHover = true;
  14834. });
  14835. $module.on('mouseleave' + eventNamespace, function(event) {
  14836. isHover = false;
  14837. });
  14838. },
  14839. touchEvents: function() {
  14840. module.verbose('Binding touch events');
  14841. $module.find('.track, .thumb, .inner').on('touchstart' + eventNamespace, function(event) {
  14842. event.stopImmediatePropagation();
  14843. event.preventDefault();
  14844. module.event.down(event);
  14845. });
  14846. $module.on('touchstart' + eventNamespace, module.event.down);
  14847. },
  14848. slidingEvents: function() {
  14849. // these don't need the identifier because we only ever want one of them to be registered with document
  14850. module.verbose('Binding page wide events while handle is being draged');
  14851. if(module.is.touch()) {
  14852. $(document).on('touchmove' + eventNamespace, module.event.move);
  14853. $(document).on('touchend' + eventNamespace, module.event.up);
  14854. }
  14855. else {
  14856. $(document).on('mousemove' + eventNamespace, module.event.move);
  14857. $(document).on('mouseup' + eventNamespace, module.event.up);
  14858. }
  14859. },
  14860. windowEvents: function() {
  14861. $window.on('resize' + eventNamespace, module.event.resize);
  14862. }
  14863. },
  14864. unbind: {
  14865. events: function() {
  14866. $module.find('.track, .thumb, .inner').off('mousedown' + eventNamespace);
  14867. $module.find('.track, .thumb, .inner').off('touchstart' + eventNamespace);
  14868. $module.off('mousedown' + eventNamespace);
  14869. $module.off('mouseenter' + eventNamespace);
  14870. $module.off('mouseleave' + eventNamespace);
  14871. $module.off('touchstart' + eventNamespace);
  14872. $module.off('keydown' + eventNamespace);
  14873. $module.off('focusout' + eventNamespace);
  14874. $(document).off('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
  14875. $window.off('resize' + eventNamespace);
  14876. },
  14877. slidingEvents: function() {
  14878. if(module.is.touch()) {
  14879. $(document).off('touchmove' + eventNamespace);
  14880. $(document).off('touchend' + eventNamespace);
  14881. } else {
  14882. $(document).off('mousemove' + eventNamespace);
  14883. $(document).off('mouseup' + eventNamespace);
  14884. }
  14885. },
  14886. },
  14887. event: {
  14888. down: function(event) {
  14889. event.preventDefault();
  14890. if(module.is.range()) {
  14891. var
  14892. eventPos = module.determine.eventPos(event),
  14893. newPos = module.determine.pos(eventPos)
  14894. ;
  14895. // Special handling if range mode and both thumbs have the same value
  14896. if(settings.preventCrossover && module.is.range() && module.thumbVal === module.secondThumbVal) {
  14897. initialPosition = newPos;
  14898. $currThumb = undefined;
  14899. } else {
  14900. $currThumb = module.determine.closestThumb(newPos);
  14901. }
  14902. }
  14903. if(!module.is.disabled()) {
  14904. module.bind.slidingEvents();
  14905. }
  14906. },
  14907. move: function(event) {
  14908. event.preventDefault();
  14909. var value = module.determine.valueFromEvent(event);
  14910. if($currThumb === undefined) {
  14911. var
  14912. eventPos = module.determine.eventPos(event),
  14913. newPos = module.determine.pos(eventPos)
  14914. ;
  14915. $currThumb = initialPosition > newPos ? $thumb : $secondThumb;
  14916. }
  14917. if(module.get.step() == 0 || module.is.smooth()) {
  14918. var
  14919. thumbVal = module.thumbVal,
  14920. secondThumbVal = module.secondThumbVal,
  14921. thumbSmoothVal = module.determine.smoothValueFromEvent(event)
  14922. ;
  14923. if(!$currThumb.hasClass('second')) {
  14924. if(settings.preventCrossover && module.is.range()) {
  14925. value = Math.min(secondThumbVal, value);
  14926. thumbSmoothVal = Math.min(secondThumbVal, thumbSmoothVal);
  14927. }
  14928. thumbVal = value;
  14929. } else {
  14930. if(settings.preventCrossover && module.is.range()) {
  14931. value = Math.max(thumbVal, value);
  14932. thumbSmoothVal = Math.max(thumbVal, thumbSmoothVal);
  14933. }
  14934. secondThumbVal = value;
  14935. }
  14936. value = Math.abs(thumbVal - (secondThumbVal || 0));
  14937. module.update.position(thumbSmoothVal);
  14938. settings.onMove.call(element, value, thumbVal, secondThumbVal);
  14939. } else {
  14940. module.update.value(value, function(value, thumbVal, secondThumbVal) {
  14941. settings.onMove.call(element, value, thumbVal, secondThumbVal);
  14942. });
  14943. }
  14944. },
  14945. up: function(event) {
  14946. event.preventDefault();
  14947. var value = module.determine.valueFromEvent(event);
  14948. module.set.value(value);
  14949. module.unbind.slidingEvents();
  14950. },
  14951. keydown: function(event, first) {
  14952. if(settings.preventCrossover && module.is.range() && module.thumbVal === module.secondThumbVal) {
  14953. $currThumb = undefined;
  14954. }
  14955. if(module.is.focused()) {
  14956. $(document).trigger(event);
  14957. }
  14958. if(first || module.is.focused()) {
  14959. var step = module.determine.keyMovement(event);
  14960. if(step != NO_STEP) {
  14961. event.preventDefault();
  14962. switch(step) {
  14963. case SINGLE_STEP:
  14964. module.takeStep();
  14965. break;
  14966. case BIG_STEP:
  14967. module.takeStep(module.get.multiplier());
  14968. break;
  14969. case SINGLE_BACKSTEP:
  14970. module.backStep();
  14971. break;
  14972. case BIG_BACKSTEP:
  14973. module.backStep(module.get.multiplier());
  14974. break;
  14975. }
  14976. }
  14977. }
  14978. },
  14979. activateFocus: function(event) {
  14980. if(!module.is.focused() && module.is.hover() && module.determine.keyMovement(event) != NO_STEP) {
  14981. event.preventDefault();
  14982. module.event.keydown(event, true);
  14983. $module.focus();
  14984. }
  14985. },
  14986. resize: function(_event) {
  14987. // To avoid a useless performance cost, we only call the label refresh when its necessary
  14988. if (gapRatio != module.get.gapRatio()) {
  14989. module.setup.labels();
  14990. gapRatio = module.get.gapRatio();
  14991. }
  14992. }
  14993. },
  14994. resync: function() {
  14995. module.verbose('Resyncing thumb position based on value');
  14996. if(module.is.range()) {
  14997. module.update.position(module.secondThumbVal, $secondThumb);
  14998. }
  14999. module.update.position(module.thumbVal, $thumb);
  15000. module.setup.labels();
  15001. },
  15002. takeStep: function(multiplier) {
  15003. var
  15004. multiplier = multiplier != undefined ? multiplier : 1,
  15005. step = module.get.step(),
  15006. currValue = module.get.currentThumbValue()
  15007. ;
  15008. module.verbose('Taking a step');
  15009. if(step > 0) {
  15010. module.set.value(currValue + step * multiplier);
  15011. } else if (step == 0){
  15012. var
  15013. precision = module.get.precision(),
  15014. newValue = currValue + (multiplier/precision)
  15015. ;
  15016. module.set.value(Math.round(newValue * precision) / precision);
  15017. }
  15018. },
  15019. backStep: function(multiplier) {
  15020. var
  15021. multiplier = multiplier != undefined ? multiplier : 1,
  15022. step = module.get.step(),
  15023. currValue = module.get.currentThumbValue()
  15024. ;
  15025. module.verbose('Going back a step');
  15026. if(step > 0) {
  15027. module.set.value(currValue - step * multiplier);
  15028. } else if (step == 0) {
  15029. var
  15030. precision = module.get.precision(),
  15031. newValue = currValue - (multiplier/precision)
  15032. ;
  15033. module.set.value(Math.round(newValue * precision) / precision);
  15034. }
  15035. },
  15036. is: {
  15037. range: function() {
  15038. return $module.hasClass(settings.className.range);
  15039. },
  15040. hover: function() {
  15041. return isHover;
  15042. },
  15043. focused: function() {
  15044. return $module.is(':focus');
  15045. },
  15046. disabled: function() {
  15047. return $module.hasClass(settings.className.disabled);
  15048. },
  15049. labeled: function() {
  15050. return $module.hasClass(settings.className.labeled);
  15051. },
  15052. reversed: function() {
  15053. return $module.hasClass(settings.className.reversed);
  15054. },
  15055. vertical: function() {
  15056. return $module.hasClass(settings.className.vertical);
  15057. },
  15058. smooth: function() {
  15059. return settings.smooth || $module.hasClass(settings.className.smooth);
  15060. },
  15061. touch: function() {
  15062. return isTouch;
  15063. }
  15064. },
  15065. get: {
  15066. trackOffset: function() {
  15067. if (module.is.vertical()) {
  15068. return $track.offset().top;
  15069. } else {
  15070. return $track.offset().left;
  15071. }
  15072. },
  15073. trackLength: function() {
  15074. if (module.is.vertical()) {
  15075. return $track.height();
  15076. } else {
  15077. return $track.width();
  15078. }
  15079. },
  15080. trackLeft: function() {
  15081. if (module.is.vertical()) {
  15082. return $track.position().top;
  15083. } else {
  15084. return $track.position().left;
  15085. }
  15086. },
  15087. trackStartPos: function() {
  15088. return module.is.reversed() ? module.get.trackLeft() + module.get.trackLength() : module.get.trackLeft();
  15089. },
  15090. trackEndPos: function() {
  15091. return module.is.reversed() ? module.get.trackLeft() : module.get.trackLeft() + module.get.trackLength();
  15092. },
  15093. trackStartMargin: function () {
  15094. var margin;
  15095. if (module.is.vertical()) {
  15096. margin = module.is.reversed() ? $module.css('padding-bottom') : $module.css('padding-top');
  15097. } else {
  15098. margin = module.is.reversed() ? $module.css('padding-right') : $module.css('padding-left');
  15099. }
  15100. return margin || '0px';
  15101. },
  15102. trackEndMargin: function () {
  15103. var margin;
  15104. if (module.is.vertical()) {
  15105. margin = module.is.reversed() ? $module.css('padding-top') : $module.css('padding-bottom');
  15106. } else {
  15107. margin = module.is.reversed() ? $module.css('padding-left') : $module.css('padding-right');
  15108. }
  15109. return margin || '0px';
  15110. },
  15111. precision: function() {
  15112. var
  15113. decimalPlaces,
  15114. step = module.get.step()
  15115. ;
  15116. if(step != 0) {
  15117. var split = String(step).split('.');
  15118. if(split.length == 2) {
  15119. decimalPlaces = split[1].length;
  15120. } else {
  15121. decimalPlaces = 0;
  15122. }
  15123. } else {
  15124. decimalPlaces = settings.decimalPlaces;
  15125. }
  15126. var precision = Math.pow(10, decimalPlaces);
  15127. module.debug('Precision determined', precision);
  15128. return precision;
  15129. },
  15130. min: function() {
  15131. return settings.min;
  15132. },
  15133. max: function() {
  15134. var step = module.get.step(),
  15135. min = module.get.min(),
  15136. quotient = step === 0 ? 0 : Math.floor((settings.max - min) / step),
  15137. remainder = step === 0 ? 0 : (settings.max - min) % step;
  15138. return remainder === 0 ? settings.max : min + quotient * step;
  15139. },
  15140. step: function() {
  15141. return settings.step;
  15142. },
  15143. numLabels: function() {
  15144. var value = Math.round((module.get.max() - module.get.min()) / module.get.step());
  15145. module.debug('Determined that there should be ' + value + ' labels');
  15146. return value;
  15147. },
  15148. labelType: function() {
  15149. return settings.labelType;
  15150. },
  15151. label: function(value) {
  15152. if(interpretLabel) {
  15153. return interpretLabel(value);
  15154. }
  15155. switch (settings.labelType) {
  15156. case settings.labelTypes.number:
  15157. return Math.round(((value * module.get.step()) + module.get.min()) * precision ) / precision;
  15158. case settings.labelTypes.letter:
  15159. return alphabet[(value) % 26];
  15160. default:
  15161. return value;
  15162. }
  15163. },
  15164. value: function() {
  15165. return value;
  15166. },
  15167. currentThumbValue: function() {
  15168. return $currThumb !== undefined && $currThumb.hasClass('second') ? module.secondThumbVal : module.thumbVal;
  15169. },
  15170. thumbValue: function(which) {
  15171. switch(which) {
  15172. case 'second':
  15173. if(module.is.range()) {
  15174. return module.secondThumbVal;
  15175. }
  15176. else {
  15177. module.error(error.notrange);
  15178. break;
  15179. }
  15180. case 'first':
  15181. default:
  15182. return module.thumbVal;
  15183. }
  15184. },
  15185. multiplier: function() {
  15186. return settings.pageMultiplier;
  15187. },
  15188. thumbPosition: function(which) {
  15189. switch(which) {
  15190. case 'second':
  15191. if(module.is.range()) {
  15192. return secondPos;
  15193. }
  15194. else {
  15195. module.error(error.notrange);
  15196. break;
  15197. }
  15198. case 'first':
  15199. default:
  15200. return position;
  15201. }
  15202. },
  15203. gapRatio: function() {
  15204. var gapRatio = 1;
  15205. if( settings.autoAdjustLabels ) {
  15206. var
  15207. numLabels = module.get.numLabels(),
  15208. trackLength = module.get.trackLength(),
  15209. gapCounter = 1
  15210. ;
  15211. // While the distance between two labels is too short,
  15212. // we divide the number of labels at each iteration
  15213. // and apply only if the modulo of the operation is an odd number.
  15214. if(trackLength>0){
  15215. while ((trackLength / numLabels) * gapCounter < settings.labelDistance) {
  15216. if( !(numLabels % gapCounter) ) {
  15217. gapRatio = gapCounter;
  15218. }
  15219. gapCounter += 1;
  15220. }
  15221. }
  15222. }
  15223. return gapRatio;
  15224. }
  15225. },
  15226. determine: {
  15227. pos: function(pagePos) {
  15228. return module.is.reversed()
  15229. ?
  15230. module.get.trackStartPos() - pagePos + module.get.trackOffset()
  15231. :
  15232. pagePos - module.get.trackOffset() - module.get.trackStartPos()
  15233. ;
  15234. },
  15235. closestThumb: function(eventPos) {
  15236. var
  15237. thumbPos = parseFloat(module.determine.thumbPos($thumb)),
  15238. thumbDelta = Math.abs(eventPos - thumbPos),
  15239. secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
  15240. secondThumbDelta = Math.abs(eventPos - secondThumbPos)
  15241. ;
  15242. if(thumbDelta === secondThumbDelta && module.get.thumbValue() === module.get.min()) {
  15243. return $secondThumb;
  15244. }
  15245. return thumbDelta <= secondThumbDelta ? $thumb : $secondThumb;
  15246. },
  15247. closestThumbPos: function(eventPos) {
  15248. var
  15249. thumbPos = parseFloat(module.determine.thumbPos($thumb)),
  15250. thumbDelta = Math.abs(eventPos - thumbPos),
  15251. secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
  15252. secondThumbDelta = Math.abs(eventPos - secondThumbPos)
  15253. ;
  15254. return thumbDelta <= secondThumbDelta ? thumbPos : secondThumbPos;
  15255. },
  15256. thumbPos: function($element) {
  15257. var pos =
  15258. module.is.vertical()
  15259. ?
  15260. module.is.reversed() ? $element.css('bottom') : $element.css('top')
  15261. :
  15262. module.is.reversed() ? $element.css('right') : $element.css('left')
  15263. ;
  15264. return pos;
  15265. },
  15266. positionFromValue: function(value) {
  15267. var
  15268. min = module.get.min(),
  15269. max = module.get.max(),
  15270. value = value > max ? max : value < min ? min : value,
  15271. trackLength = module.get.trackLength(),
  15272. ratio = (value - min) / (max - min),
  15273. position = Math.round(ratio * trackLength)
  15274. ;
  15275. module.verbose('Determined position: ' + position + ' from value: ' + value);
  15276. return position;
  15277. },
  15278. positionFromRatio: function(ratio) {
  15279. var
  15280. trackLength = module.get.trackLength(),
  15281. step = module.get.step(),
  15282. position = Math.round(ratio * trackLength),
  15283. adjustedPos = (step == 0) ? position : Math.round(position / step) * step
  15284. ;
  15285. return adjustedPos;
  15286. },
  15287. valueFromEvent: function(event) {
  15288. var
  15289. eventPos = module.determine.eventPos(event),
  15290. newPos = module.determine.pos(eventPos),
  15291. value
  15292. ;
  15293. if(eventPos < module.get.trackOffset()) {
  15294. value = module.is.reversed() ? module.get.max() : module.get.min();
  15295. } else if(eventPos > module.get.trackOffset() + module.get.trackLength()) {
  15296. value = module.is.reversed() ? module.get.min() : module.get.max();
  15297. } else {
  15298. value = module.determine.value(newPos);
  15299. }
  15300. return value;
  15301. },
  15302. smoothValueFromEvent: function(event) {
  15303. var
  15304. min = module.get.min(),
  15305. max = module.get.max(),
  15306. trackLength = module.get.trackLength(),
  15307. eventPos = module.determine.eventPos(event),
  15308. newPos = eventPos - module.get.trackOffset(),
  15309. ratio,
  15310. value
  15311. ;
  15312. newPos = newPos < 0 ? 0 : newPos > trackLength ? trackLength : newPos;
  15313. ratio = newPos / trackLength;
  15314. if (module.is.reversed()) {
  15315. ratio = 1 - ratio;
  15316. }
  15317. value = ratio * (max - min) + min;
  15318. return value;
  15319. },
  15320. eventPos: function(event) {
  15321. if(module.is.touch()) {
  15322. var
  15323. touchEvent = event.changedTouches ? event : event.originalEvent,
  15324. touches = touchEvent.changedTouches[0] ? touchEvent.changedTouches : touchEvent.touches,
  15325. touchY = touches[0].pageY,
  15326. touchX = touches[0].pageX
  15327. ;
  15328. return module.is.vertical() ? touchY : touchX;
  15329. }
  15330. var
  15331. clickY = event.pageY || event.originalEvent.pageY,
  15332. clickX = event.pageX || event.originalEvent.pageX
  15333. ;
  15334. return module.is.vertical() ? clickY : clickX;
  15335. },
  15336. value: function(position) {
  15337. var
  15338. startPos = module.is.reversed() ? module.get.trackEndPos() : module.get.trackStartPos(),
  15339. endPos = module.is.reversed() ? module.get.trackStartPos() : module.get.trackEndPos(),
  15340. ratio = (position - startPos) / (endPos - startPos),
  15341. range = module.get.max() - module.get.min(),
  15342. step = module.get.step(),
  15343. value = (ratio * range),
  15344. difference = (step == 0) ? value : Math.round(value / step) * step
  15345. ;
  15346. module.verbose('Determined value based upon position: ' + position + ' as: ' + value);
  15347. if(value != difference) {
  15348. module.verbose('Rounding value to closest step: ' + difference);
  15349. }
  15350. // Use precision to avoid ugly Javascript floating point rounding issues
  15351. // (like 35 * .01 = 0.35000000000000003)
  15352. difference = Math.round(difference * precision) / precision;
  15353. module.verbose('Cutting off additional decimal places');
  15354. return difference + module.get.min();
  15355. },
  15356. keyMovement: function(event) {
  15357. var
  15358. key = event.which,
  15359. downArrow =
  15360. module.is.vertical()
  15361. ?
  15362. module.is.reversed() ? keys.downArrow : keys.upArrow
  15363. :
  15364. keys.downArrow
  15365. ,
  15366. upArrow =
  15367. module.is.vertical()
  15368. ?
  15369. module.is.reversed() ? keys.upArrow : keys.downArrow
  15370. :
  15371. keys.upArrow
  15372. ,
  15373. leftArrow =
  15374. !module.is.vertical()
  15375. ?
  15376. module.is.reversed() ? keys.rightArrow : keys.leftArrow
  15377. :
  15378. keys.leftArrow
  15379. ,
  15380. rightArrow =
  15381. !module.is.vertical()
  15382. ?
  15383. module.is.reversed() ? keys.leftArrow : keys.rightArrow
  15384. :
  15385. keys.rightArrow
  15386. ;
  15387. if(key == downArrow || key == leftArrow) {
  15388. return SINGLE_BACKSTEP;
  15389. } else if(key == upArrow || key == rightArrow) {
  15390. return SINGLE_STEP;
  15391. } else if (key == keys.pageDown) {
  15392. return BIG_BACKSTEP;
  15393. } else if (key == keys.pageUp) {
  15394. return BIG_STEP;
  15395. } else {
  15396. return NO_STEP;
  15397. }
  15398. }
  15399. },
  15400. handleNewValuePosition: function(val) {
  15401. var
  15402. min = module.get.min(),
  15403. max = module.get.max(),
  15404. newPos
  15405. ;
  15406. if (val <= min) {
  15407. val = min;
  15408. } else if (val >= max) {
  15409. val = max;
  15410. }
  15411. newPos = module.determine.positionFromValue(val);
  15412. return newPos;
  15413. },
  15414. set: {
  15415. value: function(newValue) {
  15416. module.update.value(newValue, function(value, thumbVal, secondThumbVal) {
  15417. if (!initialLoad || settings.fireOnInit){
  15418. settings.onChange.call(element, value, thumbVal, secondThumbVal);
  15419. settings.onMove.call(element, value, thumbVal, secondThumbVal);
  15420. }
  15421. });
  15422. },
  15423. rangeValue: function(first, second) {
  15424. if(module.is.range()) {
  15425. var
  15426. min = module.get.min(),
  15427. max = module.get.max()
  15428. ;
  15429. if (first <= min) {
  15430. first = min;
  15431. } else if(first >= max){
  15432. first = max;
  15433. }
  15434. if (second <= min) {
  15435. second = min;
  15436. } else if(second >= max){
  15437. second = max;
  15438. }
  15439. module.thumbVal = first;
  15440. module.secondThumbVal = second;
  15441. value = Math.abs(module.thumbVal - module.secondThumbVal);
  15442. module.update.position(module.thumbVal, $thumb);
  15443. module.update.position(module.secondThumbVal, $secondThumb);
  15444. if (!initialLoad || settings.fireOnInit) {
  15445. settings.onChange.call(element, value, module.thumbVal, module.secondThumbVal);
  15446. settings.onMove.call(element, value, module.thumbVal, module.secondThumbVal);
  15447. }
  15448. } else {
  15449. module.error(error.notrange);
  15450. }
  15451. },
  15452. position: function(position, which) {
  15453. var thumbVal = module.determine.value(position);
  15454. switch (which) {
  15455. case 'second':
  15456. module.secondThumbVal = thumbVal;
  15457. module.update.position(thumbVal, $secondThumb);
  15458. break;
  15459. default:
  15460. module.thumbVal = thumbVal;
  15461. module.update.position(thumbVal, $thumb);
  15462. }
  15463. value = Math.abs(module.thumbVal - (module.secondThumbVal || 0));
  15464. module.set.value(value);
  15465. }
  15466. },
  15467. update: {
  15468. value: function(newValue, callback) {
  15469. var
  15470. min = module.get.min(),
  15471. max = module.get.max()
  15472. ;
  15473. if (newValue <= min) {
  15474. newValue = min;
  15475. } else if(newValue >= max){
  15476. newValue = max;
  15477. }
  15478. if(!module.is.range()) {
  15479. value = newValue;
  15480. module.thumbVal = value;
  15481. } else {
  15482. if($currThumb === undefined) {
  15483. $currThumb = newValue <= module.get.currentThumbValue() ? $thumb : $secondThumb;
  15484. }
  15485. if(!$currThumb.hasClass('second')) {
  15486. if(settings.preventCrossover && module.is.range()) {
  15487. newValue = Math.min(module.secondThumbVal, newValue);
  15488. }
  15489. module.thumbVal = newValue;
  15490. } else {
  15491. if(settings.preventCrossover && module.is.range()) {
  15492. newValue = Math.max(module.thumbVal, newValue);
  15493. }
  15494. module.secondThumbVal = newValue;
  15495. }
  15496. value = Math.abs(module.thumbVal - module.secondThumbVal);
  15497. }
  15498. module.update.position(newValue);
  15499. module.debug('Setting slider value to ' + value);
  15500. if(typeof callback === 'function') {
  15501. callback(value, module.thumbVal, module.secondThumbVal);
  15502. }
  15503. },
  15504. position: function(newValue, $element) {
  15505. var
  15506. newPos = module.handleNewValuePosition(newValue),
  15507. $targetThumb = $element != undefined ? $element : $currThumb,
  15508. thumbVal = module.thumbVal || module.get.min(),
  15509. secondThumbVal = module.secondThumbVal || module.get.min()
  15510. ;
  15511. if(module.is.range()) {
  15512. if(!$targetThumb.hasClass('second')) {
  15513. position = newPos;
  15514. thumbVal = newValue;
  15515. } else {
  15516. secondPos = newPos;
  15517. secondThumbVal = newValue;
  15518. }
  15519. } else {
  15520. position = newPos;
  15521. thumbVal = newValue;
  15522. }
  15523. var
  15524. trackPosValue,
  15525. thumbPosValue,
  15526. min = module.get.min(),
  15527. max = module.get.max(),
  15528. thumbPosPercent = 100 * (newValue - min) / (max - min),
  15529. trackStartPosPercent = 100 * (Math.min(thumbVal, secondThumbVal) - min) / (max - min),
  15530. trackEndPosPercent = 100 * (1 - (Math.max(thumbVal, secondThumbVal) - min) / (max - min))
  15531. ;
  15532. if (module.is.vertical()) {
  15533. if (module.is.reversed()) {
  15534. thumbPosValue = {bottom: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', top: 'auto'};
  15535. trackPosValue = {bottom: trackStartPosPercent + '%', top: trackEndPosPercent + '%'};
  15536. }
  15537. else {
  15538. thumbPosValue = {top: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', bottom: 'auto'};
  15539. trackPosValue = {top: trackStartPosPercent + '%', bottom: trackEndPosPercent + '%'};
  15540. }
  15541. } else {
  15542. if (module.is.reversed()) {
  15543. thumbPosValue = {right: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', left: 'auto'};
  15544. trackPosValue = {right: trackStartPosPercent + '%', left: trackEndPosPercent + '%'};
  15545. }
  15546. else {
  15547. thumbPosValue = {left: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', right: 'auto'};
  15548. trackPosValue = {left: trackStartPosPercent + '%', right: trackEndPosPercent + '%'};
  15549. }
  15550. }
  15551. $targetThumb.css(thumbPosValue);
  15552. $trackFill.css(trackPosValue);
  15553. module.debug('Setting slider position to ' + newPos);
  15554. },
  15555. labelPosition: function (ratio, $label) {
  15556. var
  15557. startMargin = module.get.trackStartMargin(),
  15558. endMargin = module.get.trackEndMargin(),
  15559. posDir =
  15560. module.is.vertical()
  15561. ?
  15562. module.is.reversed() ? 'bottom' : 'top'
  15563. :
  15564. module.is.reversed() ? 'right' : 'left',
  15565. startMarginMod = module.is.reversed() && !module.is.vertical() ? ' - ' : ' + '
  15566. ;
  15567. var position = '(100% - ' + startMargin + ' - ' + endMargin + ') * ' + ratio;
  15568. $label.css(posDir, 'calc(' + position + startMarginMod + startMargin + ')');
  15569. }
  15570. },
  15571. goto: {
  15572. max: function() {
  15573. module.set.value(module.get.max());
  15574. },
  15575. min: function() {
  15576. module.set.value(module.get.min());
  15577. },
  15578. },
  15579. read: {
  15580. metadata: function() {
  15581. var
  15582. data = {
  15583. thumbVal : $module.data(metadata.thumbVal),
  15584. secondThumbVal : $module.data(metadata.secondThumbVal)
  15585. }
  15586. ;
  15587. if(data.thumbVal) {
  15588. if(module.is.range() && data.secondThumbVal) {
  15589. module.debug('Current value set from metadata', data.thumbVal, data.secondThumbVal);
  15590. module.set.rangeValue(data.thumbVal, data.secondThumbVal);
  15591. } else {
  15592. module.debug('Current value set from metadata', data.thumbVal);
  15593. module.set.value(data.thumbVal);
  15594. }
  15595. }
  15596. },
  15597. settings: function() {
  15598. if(settings.start !== false) {
  15599. if(module.is.range()) {
  15600. module.debug('Start position set from settings', settings.start, settings.end);
  15601. module.set.rangeValue(settings.start, settings.end);
  15602. } else {
  15603. module.debug('Start position set from settings', settings.start);
  15604. module.set.value(settings.start);
  15605. }
  15606. }
  15607. }
  15608. },
  15609. setting: function(name, value) {
  15610. module.debug('Changing setting', name, value);
  15611. if( $.isPlainObject(name) ) {
  15612. $.extend(true, settings, name);
  15613. }
  15614. else if(value !== undefined) {
  15615. if($.isPlainObject(settings[name])) {
  15616. $.extend(true, settings[name], value);
  15617. }
  15618. else {
  15619. settings[name] = value;
  15620. }
  15621. }
  15622. else {
  15623. return settings[name];
  15624. }
  15625. },
  15626. internal: function(name, value) {
  15627. if( $.isPlainObject(name) ) {
  15628. $.extend(true, module, name);
  15629. }
  15630. else if(value !== undefined) {
  15631. module[name] = value;
  15632. }
  15633. else {
  15634. return module[name];
  15635. }
  15636. },
  15637. debug: function() {
  15638. if(!settings.silent && settings.debug) {
  15639. if(settings.performance) {
  15640. module.performance.log(arguments);
  15641. }
  15642. else {
  15643. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15644. module.debug.apply(console, arguments);
  15645. }
  15646. }
  15647. },
  15648. verbose: function() {
  15649. if(!settings.silent && settings.verbose && settings.debug) {
  15650. if(settings.performance) {
  15651. module.performance.log(arguments);
  15652. }
  15653. else {
  15654. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15655. module.verbose.apply(console, arguments);
  15656. }
  15657. }
  15658. },
  15659. error: function() {
  15660. if(!settings.silent) {
  15661. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  15662. module.error.apply(console, arguments);
  15663. }
  15664. },
  15665. performance: {
  15666. log: function(message) {
  15667. var
  15668. currentTime,
  15669. executionTime,
  15670. previousTime
  15671. ;
  15672. if(settings.performance) {
  15673. currentTime = new Date().getTime();
  15674. previousTime = time || currentTime;
  15675. executionTime = currentTime - previousTime;
  15676. time = currentTime;
  15677. performance.push({
  15678. 'Name' : message[0],
  15679. 'Arguments' : [].slice.call(message, 1) || '',
  15680. 'Element' : element,
  15681. 'Execution Time' : executionTime
  15682. });
  15683. }
  15684. clearTimeout(module.performance.timer);
  15685. module.performance.timer = setTimeout(module.performance.display, 500);
  15686. },
  15687. display: function() {
  15688. var
  15689. title = settings.name + ':',
  15690. totalTime = 0
  15691. ;
  15692. time = false;
  15693. clearTimeout(module.performance.timer);
  15694. $.each(performance, function(index, data) {
  15695. totalTime += data['Execution Time'];
  15696. });
  15697. title += ' ' + totalTime + 'ms';
  15698. if(moduleSelector) {
  15699. title += ' \'' + moduleSelector + '\'';
  15700. }
  15701. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  15702. console.groupCollapsed(title);
  15703. if(console.table) {
  15704. console.table(performance);
  15705. }
  15706. else {
  15707. $.each(performance, function(index, data) {
  15708. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  15709. });
  15710. }
  15711. console.groupEnd();
  15712. }
  15713. performance = [];
  15714. }
  15715. },
  15716. invoke: function(query, passedArguments, context) {
  15717. var
  15718. object = instance,
  15719. maxDepth,
  15720. found,
  15721. response
  15722. ;
  15723. passedArguments = passedArguments || queryArguments;
  15724. context = element || context;
  15725. if(typeof query == 'string' && object !== undefined) {
  15726. query = query.split(/[\. ]/);
  15727. maxDepth = query.length - 1;
  15728. $.each(query, function(depth, value) {
  15729. var camelCaseValue = (depth != maxDepth)
  15730. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  15731. : query
  15732. ;
  15733. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  15734. object = object[camelCaseValue];
  15735. }
  15736. else if( object[camelCaseValue] !== undefined ) {
  15737. found = object[camelCaseValue];
  15738. return false;
  15739. }
  15740. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  15741. object = object[value];
  15742. }
  15743. else if( object[value] !== undefined ) {
  15744. found = object[value];
  15745. return false;
  15746. }
  15747. else {
  15748. module.error(error.method, query);
  15749. return false;
  15750. }
  15751. });
  15752. }
  15753. if ( $.isFunction( found ) ) {
  15754. response = found.apply(context, passedArguments);
  15755. }
  15756. else if(found !== undefined) {
  15757. response = found;
  15758. }
  15759. if($.isArray(returnedValue)) {
  15760. returnedValue.push(response);
  15761. }
  15762. else if(returnedValue !== undefined) {
  15763. returnedValue = [returnedValue, response];
  15764. }
  15765. else if(response !== undefined) {
  15766. returnedValue = response;
  15767. }
  15768. return found;
  15769. }
  15770. };
  15771. if(methodInvoked) {
  15772. if(instance === undefined) {
  15773. module.initialize();
  15774. }
  15775. module.invoke(query);
  15776. }
  15777. else {
  15778. if(instance !== undefined) {
  15779. instance.invoke('destroy');
  15780. }
  15781. module.initialize();
  15782. }
  15783. })
  15784. ;
  15785. return (returnedValue !== undefined)
  15786. ? returnedValue
  15787. : this
  15788. ;
  15789. };
  15790. $.fn.slider.settings = {
  15791. silent : false,
  15792. debug : false,
  15793. verbose : false,
  15794. performance : true,
  15795. name : 'Slider',
  15796. namespace : 'slider',
  15797. error : {
  15798. method : 'The method you called is not defined.',
  15799. notrange : 'This slider is not a range slider'
  15800. },
  15801. metadata: {
  15802. thumbVal : 'thumbVal',
  15803. secondThumbVal : 'secondThumbVal'
  15804. },
  15805. min : 0,
  15806. max : 20,
  15807. step : 1,
  15808. start : 0,
  15809. end : 20,
  15810. labelType : 'number',
  15811. showLabelTicks : false,
  15812. smooth : false,
  15813. autoAdjustLabels : true,
  15814. labelDistance : 100,
  15815. preventCrossover : true,
  15816. fireOnInit : false,
  15817. //the decimal place to round to if step is undefined
  15818. decimalPlaces : 2,
  15819. // page up/down multiplier. How many more times the steps to take on page up/down press
  15820. pageMultiplier : 2,
  15821. selector: {
  15822. },
  15823. className : {
  15824. reversed : 'reversed',
  15825. disabled : 'disabled',
  15826. labeled : 'labeled',
  15827. ticked : 'ticked',
  15828. vertical : 'vertical',
  15829. range : 'range',
  15830. smooth : 'smooth'
  15831. },
  15832. keys : {
  15833. pageUp : 33,
  15834. pageDown : 34,
  15835. leftArrow : 37,
  15836. upArrow : 38,
  15837. rightArrow : 39,
  15838. downArrow : 40
  15839. },
  15840. labelTypes : {
  15841. number : 'number',
  15842. letter : 'letter'
  15843. },
  15844. onChange : function(value, thumbVal, secondThumbVal){},
  15845. onMove : function(value, thumbVal, secondThumbVal){},
  15846. };
  15847. })( jQuery, window, document );
  15848. /*!
  15849. * # Fomantic-UI - Rating
  15850. * http://github.com/fomantic/Fomantic-UI/
  15851. *
  15852. *
  15853. * Released under the MIT license
  15854. * http://opensource.org/licenses/MIT
  15855. *
  15856. */
  15857. ;(function ($, window, document, undefined) {
  15858. 'use strict';
  15859. $.isFunction = $.isFunction || function(obj) {
  15860. return typeof obj === "function" && typeof obj.nodeType !== "number";
  15861. };
  15862. window = (typeof window != 'undefined' && window.Math == Math)
  15863. ? window
  15864. : (typeof self != 'undefined' && self.Math == Math)
  15865. ? self
  15866. : Function('return this')()
  15867. ;
  15868. $.fn.rating = function(parameters) {
  15869. var
  15870. $allModules = $(this),
  15871. moduleSelector = $allModules.selector || '',
  15872. time = new Date().getTime(),
  15873. performance = [],
  15874. query = arguments[0],
  15875. methodInvoked = (typeof query == 'string'),
  15876. queryArguments = [].slice.call(arguments, 1),
  15877. returnedValue
  15878. ;
  15879. $allModules
  15880. .each(function() {
  15881. var
  15882. settings = ( $.isPlainObject(parameters) )
  15883. ? $.extend(true, {}, $.fn.rating.settings, parameters)
  15884. : $.extend({}, $.fn.rating.settings),
  15885. namespace = settings.namespace,
  15886. className = settings.className,
  15887. metadata = settings.metadata,
  15888. selector = settings.selector,
  15889. cssVars = settings.cssVars,
  15890. eventNamespace = '.' + namespace,
  15891. moduleNamespace = 'module-' + namespace,
  15892. element = this,
  15893. instance = $(this).data(moduleNamespace),
  15894. $module = $(this),
  15895. $icon = $module.find(selector.icon),
  15896. initialLoad,
  15897. module
  15898. ;
  15899. module = {
  15900. initialize: function() {
  15901. module.verbose('Initializing rating module', settings);
  15902. if($icon.length === 0) {
  15903. module.setup.layout();
  15904. }
  15905. if(settings.interactive && !module.is.disabled()) {
  15906. module.enable();
  15907. }
  15908. else {
  15909. module.disable();
  15910. }
  15911. module.set.initialLoad();
  15912. module.set.rating( module.get.initialRating() );
  15913. module.remove.initialLoad();
  15914. module.instantiate();
  15915. },
  15916. instantiate: function() {
  15917. module.verbose('Instantiating module', settings);
  15918. instance = module;
  15919. $module
  15920. .data(moduleNamespace, module)
  15921. ;
  15922. },
  15923. destroy: function() {
  15924. module.verbose('Destroying previous instance', instance);
  15925. module.remove.events();
  15926. $module
  15927. .removeData(moduleNamespace)
  15928. ;
  15929. },
  15930. refresh: function() {
  15931. $icon = $module.find(selector.icon);
  15932. },
  15933. setup: {
  15934. layout: function() {
  15935. var
  15936. maxRating = module.get.maxRating(),
  15937. icon = module.get.icon(),
  15938. html = $.fn.rating.settings.templates.icon(maxRating, icon)
  15939. ;
  15940. module.debug('Generating icon html dynamically');
  15941. $module
  15942. .html(html)
  15943. ;
  15944. module.refresh();
  15945. }
  15946. },
  15947. event: {
  15948. mouseenter: function() {
  15949. var
  15950. $activeIcon = $(this)
  15951. ;
  15952. $activeIcon
  15953. .nextAll()
  15954. .removeClass(className.selected)
  15955. ;
  15956. $module
  15957. .addClass(className.selected)
  15958. ;
  15959. $activeIcon
  15960. .addClass(className.selected)
  15961. .prevAll()
  15962. .addClass(className.selected)
  15963. ;
  15964. },
  15965. mouseleave: function() {
  15966. $module
  15967. .removeClass(className.selected)
  15968. ;
  15969. $icon
  15970. .removeClass(className.selected)
  15971. ;
  15972. },
  15973. click: function() {
  15974. var
  15975. $activeIcon = $(this),
  15976. currentRating = module.get.rating(),
  15977. rating = $icon.index($activeIcon) + 1,
  15978. canClear = (settings.clearable == 'auto')
  15979. ? ($icon.length === 1)
  15980. : settings.clearable
  15981. ;
  15982. if(canClear && currentRating == rating) {
  15983. module.clearRating();
  15984. }
  15985. else {
  15986. module.set.rating( rating );
  15987. }
  15988. }
  15989. },
  15990. clearRating: function() {
  15991. module.debug('Clearing current rating');
  15992. module.set.rating(0);
  15993. },
  15994. bind: {
  15995. events: function() {
  15996. module.verbose('Binding events');
  15997. $module
  15998. .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
  15999. .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
  16000. .on('click' + eventNamespace, selector.icon, module.event.click)
  16001. ;
  16002. }
  16003. },
  16004. remove: {
  16005. events: function() {
  16006. module.verbose('Removing events');
  16007. $module
  16008. .off(eventNamespace)
  16009. ;
  16010. },
  16011. initialLoad: function() {
  16012. initialLoad = false;
  16013. }
  16014. },
  16015. enable: function() {
  16016. module.debug('Setting rating to interactive mode');
  16017. module.bind.events();
  16018. $module
  16019. .removeClass(className.disabled)
  16020. ;
  16021. },
  16022. disable: function() {
  16023. module.debug('Setting rating to read-only mode');
  16024. module.remove.events();
  16025. $module
  16026. .addClass(className.disabled)
  16027. ;
  16028. },
  16029. is: {
  16030. initialLoad: function() {
  16031. return initialLoad;
  16032. },
  16033. disabled: function() {
  16034. return $module.hasClass(className.disabled);
  16035. }
  16036. },
  16037. get: {
  16038. icon: function(){
  16039. var icon = $module.data(metadata.icon);
  16040. if (icon) {
  16041. $module.removeData(metadata.icon);
  16042. }
  16043. return icon || settings.icon;
  16044. },
  16045. initialRating: function() {
  16046. if($module.data(metadata.rating) !== undefined) {
  16047. $module.removeData(metadata.rating);
  16048. return $module.data(metadata.rating);
  16049. }
  16050. return settings.initialRating;
  16051. },
  16052. maxRating: function() {
  16053. if($module.data(metadata.maxRating) !== undefined) {
  16054. $module.removeData(metadata.maxRating);
  16055. return $module.data(metadata.maxRating);
  16056. }
  16057. return settings.maxRating;
  16058. },
  16059. rating: function() {
  16060. var
  16061. currentRating = $icon.filter('.' + className.active).length
  16062. ;
  16063. module.verbose('Current rating retrieved', currentRating);
  16064. return currentRating;
  16065. }
  16066. },
  16067. set: {
  16068. rating: function(rating) {
  16069. var
  16070. ratingIndex = Math.floor(
  16071. (rating - 1 >= 0)
  16072. ? (rating - 1)
  16073. : 0
  16074. ),
  16075. $activeIcon = $icon.eq(ratingIndex),
  16076. $partialActiveIcon = rating <= 1
  16077. ? $activeIcon
  16078. : $activeIcon.next()
  16079. ,
  16080. filledPercentage = (rating % 1) * 100
  16081. ;
  16082. $module
  16083. .removeClass(className.selected)
  16084. ;
  16085. $icon
  16086. .removeClass(className.selected)
  16087. .removeClass(className.active)
  16088. .removeClass(className.partiallyActive)
  16089. ;
  16090. if(rating > 0) {
  16091. module.verbose('Setting current rating to', rating);
  16092. $activeIcon
  16093. .prevAll()
  16094. .addBack()
  16095. .addClass(className.active)
  16096. ;
  16097. if($activeIcon.next() && rating % 1 !== 0) {
  16098. $partialActiveIcon
  16099. .addClass(className.partiallyActive)
  16100. .addClass(className.active)
  16101. ;
  16102. $partialActiveIcon
  16103. .css(cssVars.filledCustomPropName, filledPercentage + '%')
  16104. ;
  16105. if($partialActiveIcon.css('backgroundColor') === 'transparent') {
  16106. $partialActiveIcon
  16107. .removeClass(className.partiallyActive)
  16108. .removeClass(className.active)
  16109. ;
  16110. }
  16111. }
  16112. }
  16113. if(!module.is.initialLoad()) {
  16114. settings.onRate.call(element, rating);
  16115. }
  16116. },
  16117. initialLoad: function() {
  16118. initialLoad = true;
  16119. }
  16120. },
  16121. setting: function(name, value) {
  16122. module.debug('Changing setting', name, value);
  16123. if( $.isPlainObject(name) ) {
  16124. $.extend(true, settings, name);
  16125. }
  16126. else if(value !== undefined) {
  16127. if($.isPlainObject(settings[name])) {
  16128. $.extend(true, settings[name], value);
  16129. }
  16130. else {
  16131. settings[name] = value;
  16132. }
  16133. }
  16134. else {
  16135. return settings[name];
  16136. }
  16137. },
  16138. internal: function(name, value) {
  16139. if( $.isPlainObject(name) ) {
  16140. $.extend(true, module, name);
  16141. }
  16142. else if(value !== undefined) {
  16143. module[name] = value;
  16144. }
  16145. else {
  16146. return module[name];
  16147. }
  16148. },
  16149. debug: function() {
  16150. if(!settings.silent && settings.debug) {
  16151. if(settings.performance) {
  16152. module.performance.log(arguments);
  16153. }
  16154. else {
  16155. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16156. module.debug.apply(console, arguments);
  16157. }
  16158. }
  16159. },
  16160. verbose: function() {
  16161. if(!settings.silent && settings.verbose && settings.debug) {
  16162. if(settings.performance) {
  16163. module.performance.log(arguments);
  16164. }
  16165. else {
  16166. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16167. module.verbose.apply(console, arguments);
  16168. }
  16169. }
  16170. },
  16171. error: function() {
  16172. if(!settings.silent) {
  16173. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  16174. module.error.apply(console, arguments);
  16175. }
  16176. },
  16177. performance: {
  16178. log: function(message) {
  16179. var
  16180. currentTime,
  16181. executionTime,
  16182. previousTime
  16183. ;
  16184. if(settings.performance) {
  16185. currentTime = new Date().getTime();
  16186. previousTime = time || currentTime;
  16187. executionTime = currentTime - previousTime;
  16188. time = currentTime;
  16189. performance.push({
  16190. 'Name' : message[0],
  16191. 'Arguments' : [].slice.call(message, 1) || '',
  16192. 'Element' : element,
  16193. 'Execution Time' : executionTime
  16194. });
  16195. }
  16196. clearTimeout(module.performance.timer);
  16197. module.performance.timer = setTimeout(module.performance.display, 500);
  16198. },
  16199. display: function() {
  16200. var
  16201. title = settings.name + ':',
  16202. totalTime = 0
  16203. ;
  16204. time = false;
  16205. clearTimeout(module.performance.timer);
  16206. $.each(performance, function(index, data) {
  16207. totalTime += data['Execution Time'];
  16208. });
  16209. title += ' ' + totalTime + 'ms';
  16210. if(moduleSelector) {
  16211. title += ' \'' + moduleSelector + '\'';
  16212. }
  16213. if($allModules.length > 1) {
  16214. title += ' ' + '(' + $allModules.length + ')';
  16215. }
  16216. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  16217. console.groupCollapsed(title);
  16218. if(console.table) {
  16219. console.table(performance);
  16220. }
  16221. else {
  16222. $.each(performance, function(index, data) {
  16223. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  16224. });
  16225. }
  16226. console.groupEnd();
  16227. }
  16228. performance = [];
  16229. }
  16230. },
  16231. invoke: function(query, passedArguments, context) {
  16232. var
  16233. object = instance,
  16234. maxDepth,
  16235. found,
  16236. response
  16237. ;
  16238. passedArguments = passedArguments || queryArguments;
  16239. context = element || context;
  16240. if(typeof query == 'string' && object !== undefined) {
  16241. query = query.split(/[\. ]/);
  16242. maxDepth = query.length - 1;
  16243. $.each(query, function(depth, value) {
  16244. var camelCaseValue = (depth != maxDepth)
  16245. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  16246. : query
  16247. ;
  16248. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  16249. object = object[camelCaseValue];
  16250. }
  16251. else if( object[camelCaseValue] !== undefined ) {
  16252. found = object[camelCaseValue];
  16253. return false;
  16254. }
  16255. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  16256. object = object[value];
  16257. }
  16258. else if( object[value] !== undefined ) {
  16259. found = object[value];
  16260. return false;
  16261. }
  16262. else {
  16263. return false;
  16264. }
  16265. });
  16266. }
  16267. if ( $.isFunction( found ) ) {
  16268. response = found.apply(context, passedArguments);
  16269. }
  16270. else if(found !== undefined) {
  16271. response = found;
  16272. }
  16273. if(Array.isArray(returnedValue)) {
  16274. returnedValue.push(response);
  16275. }
  16276. else if(returnedValue !== undefined) {
  16277. returnedValue = [returnedValue, response];
  16278. }
  16279. else if(response !== undefined) {
  16280. returnedValue = response;
  16281. }
  16282. return found;
  16283. }
  16284. };
  16285. if(methodInvoked) {
  16286. if(instance === undefined) {
  16287. module.initialize();
  16288. }
  16289. module.invoke(query);
  16290. }
  16291. else {
  16292. if(instance !== undefined) {
  16293. instance.invoke('destroy');
  16294. }
  16295. module.initialize();
  16296. }
  16297. })
  16298. ;
  16299. return (returnedValue !== undefined)
  16300. ? returnedValue
  16301. : this
  16302. ;
  16303. };
  16304. $.fn.rating.settings = {
  16305. name : 'Rating',
  16306. namespace : 'rating',
  16307. icon : 'star',
  16308. silent : false,
  16309. debug : false,
  16310. verbose : false,
  16311. performance : true,
  16312. initialRating : 0,
  16313. interactive : true,
  16314. maxRating : 4,
  16315. clearable : 'auto',
  16316. fireOnInit : false,
  16317. onRate : function(rating){},
  16318. error : {
  16319. method : 'The method you called is not defined',
  16320. noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
  16321. },
  16322. metadata: {
  16323. rating : 'rating',
  16324. maxRating : 'maxRating',
  16325. icon : 'icon'
  16326. },
  16327. className : {
  16328. active : 'active',
  16329. disabled : 'disabled',
  16330. selected : 'selected',
  16331. loading : 'loading',
  16332. partiallyActive : 'partial'
  16333. },
  16334. cssVars : {
  16335. filledCustomPropName : '--full'
  16336. },
  16337. selector : {
  16338. icon : '.icon'
  16339. },
  16340. templates: {
  16341. icon: function(maxRating, iconClass) {
  16342. var
  16343. icon = 1,
  16344. html = ''
  16345. ;
  16346. while(icon <= maxRating) {
  16347. html += '<i class="'+iconClass+' icon"></i>';
  16348. icon++;
  16349. }
  16350. return html;
  16351. }
  16352. }
  16353. };
  16354. })( jQuery, window, document );
  16355. /*!
  16356. * # Fomantic-UI - Search
  16357. * http://github.com/fomantic/Fomantic-UI/
  16358. *
  16359. *
  16360. * Released under the MIT license
  16361. * http://opensource.org/licenses/MIT
  16362. *
  16363. */
  16364. ;(function ($, window, document, undefined) {
  16365. 'use strict';
  16366. $.isFunction = $.isFunction || function(obj) {
  16367. return typeof obj === "function" && typeof obj.nodeType !== "number";
  16368. };
  16369. window = (typeof window != 'undefined' && window.Math == Math)
  16370. ? window
  16371. : (typeof self != 'undefined' && self.Math == Math)
  16372. ? self
  16373. : Function('return this')()
  16374. ;
  16375. $.fn.search = function(parameters) {
  16376. var
  16377. $allModules = $(this),
  16378. moduleSelector = $allModules.selector || '',
  16379. time = new Date().getTime(),
  16380. performance = [],
  16381. query = arguments[0],
  16382. methodInvoked = (typeof query == 'string'),
  16383. queryArguments = [].slice.call(arguments, 1),
  16384. returnedValue
  16385. ;
  16386. $(this)
  16387. .each(function() {
  16388. var
  16389. settings = ( $.isPlainObject(parameters) )
  16390. ? $.extend(true, {}, $.fn.search.settings, parameters)
  16391. : $.extend({}, $.fn.search.settings),
  16392. className = settings.className,
  16393. metadata = settings.metadata,
  16394. regExp = settings.regExp,
  16395. fields = settings.fields,
  16396. selector = settings.selector,
  16397. error = settings.error,
  16398. namespace = settings.namespace,
  16399. eventNamespace = '.' + namespace,
  16400. moduleNamespace = namespace + '-module',
  16401. $module = $(this),
  16402. $prompt = $module.find(selector.prompt),
  16403. $searchButton = $module.find(selector.searchButton),
  16404. $results = $module.find(selector.results),
  16405. $result = $module.find(selector.result),
  16406. $category = $module.find(selector.category),
  16407. element = this,
  16408. instance = $module.data(moduleNamespace),
  16409. disabledBubbled = false,
  16410. resultsDismissed = false,
  16411. module
  16412. ;
  16413. module = {
  16414. initialize: function() {
  16415. module.verbose('Initializing module');
  16416. module.get.settings();
  16417. module.determine.searchFields();
  16418. module.bind.events();
  16419. module.set.type();
  16420. module.create.results();
  16421. module.instantiate();
  16422. },
  16423. instantiate: function() {
  16424. module.verbose('Storing instance of module', module);
  16425. instance = module;
  16426. $module
  16427. .data(moduleNamespace, module)
  16428. ;
  16429. },
  16430. destroy: function() {
  16431. module.verbose('Destroying instance');
  16432. $module
  16433. .off(eventNamespace)
  16434. .removeData(moduleNamespace)
  16435. ;
  16436. },
  16437. refresh: function() {
  16438. module.debug('Refreshing selector cache');
  16439. $prompt = $module.find(selector.prompt);
  16440. $searchButton = $module.find(selector.searchButton);
  16441. $category = $module.find(selector.category);
  16442. $results = $module.find(selector.results);
  16443. $result = $module.find(selector.result);
  16444. },
  16445. refreshResults: function() {
  16446. $results = $module.find(selector.results);
  16447. $result = $module.find(selector.result);
  16448. },
  16449. bind: {
  16450. events: function() {
  16451. module.verbose('Binding events to search');
  16452. if(settings.automatic) {
  16453. $module
  16454. .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
  16455. ;
  16456. $prompt
  16457. .attr('autocomplete', 'off')
  16458. ;
  16459. }
  16460. $module
  16461. // prompt
  16462. .on('focus' + eventNamespace, selector.prompt, module.event.focus)
  16463. .on('blur' + eventNamespace, selector.prompt, module.event.blur)
  16464. .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
  16465. // search button
  16466. .on('click' + eventNamespace, selector.searchButton, module.query)
  16467. // results
  16468. .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
  16469. .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
  16470. .on('click' + eventNamespace, selector.result, module.event.result.click)
  16471. ;
  16472. }
  16473. },
  16474. determine: {
  16475. searchFields: function() {
  16476. // this makes sure $.extend does not add specified search fields to default fields
  16477. // this is the only setting which should not extend defaults
  16478. if(parameters && parameters.searchFields !== undefined) {
  16479. settings.searchFields = parameters.searchFields;
  16480. }
  16481. }
  16482. },
  16483. event: {
  16484. input: function() {
  16485. if(settings.searchDelay) {
  16486. clearTimeout(module.timer);
  16487. module.timer = setTimeout(function() {
  16488. if(module.is.focused()) {
  16489. module.query();
  16490. }
  16491. }, settings.searchDelay);
  16492. }
  16493. else {
  16494. module.query();
  16495. }
  16496. },
  16497. focus: function() {
  16498. module.set.focus();
  16499. if(settings.searchOnFocus && module.has.minimumCharacters() ) {
  16500. module.query(function() {
  16501. if(module.can.show() ) {
  16502. module.showResults();
  16503. }
  16504. });
  16505. }
  16506. },
  16507. blur: function(event) {
  16508. var
  16509. pageLostFocus = (document.activeElement === this),
  16510. callback = function() {
  16511. module.cancel.query();
  16512. module.remove.focus();
  16513. module.timer = setTimeout(module.hideResults, settings.hideDelay);
  16514. }
  16515. ;
  16516. if(pageLostFocus) {
  16517. return;
  16518. }
  16519. resultsDismissed = false;
  16520. if(module.resultsClicked) {
  16521. module.debug('Determining if user action caused search to close');
  16522. $module
  16523. .one('click.close' + eventNamespace, selector.results, function(event) {
  16524. if(module.is.inMessage(event) || disabledBubbled) {
  16525. $prompt.focus();
  16526. return;
  16527. }
  16528. disabledBubbled = false;
  16529. if( !module.is.animating() && !module.is.hidden()) {
  16530. callback();
  16531. }
  16532. })
  16533. ;
  16534. }
  16535. else {
  16536. module.debug('Input blurred without user action, closing results');
  16537. callback();
  16538. }
  16539. },
  16540. result: {
  16541. mousedown: function() {
  16542. module.resultsClicked = true;
  16543. },
  16544. mouseup: function() {
  16545. module.resultsClicked = false;
  16546. },
  16547. click: function(event) {
  16548. module.debug('Search result selected');
  16549. var
  16550. $result = $(this),
  16551. $title = $result.find(selector.title).eq(0),
  16552. $link = $result.is('a[href]')
  16553. ? $result
  16554. : $result.find('a[href]').eq(0),
  16555. href = $link.attr('href') || false,
  16556. target = $link.attr('target') || false,
  16557. // title is used for result lookup
  16558. value = ($title.length > 0)
  16559. ? $title.text()
  16560. : false,
  16561. results = module.get.results(),
  16562. result = $result.data(metadata.result) || module.get.result(value, results)
  16563. ;
  16564. if(value) {
  16565. module.set.value(value);
  16566. }
  16567. if( $.isFunction(settings.onSelect) ) {
  16568. if(settings.onSelect.call(element, result, results) === false) {
  16569. module.debug('Custom onSelect callback cancelled default select action');
  16570. disabledBubbled = true;
  16571. return;
  16572. }
  16573. }
  16574. module.hideResults();
  16575. if(href) {
  16576. module.verbose('Opening search link found in result', $link);
  16577. if(target == '_blank' || event.ctrlKey) {
  16578. window.open(href);
  16579. }
  16580. else {
  16581. window.location.href = (href);
  16582. }
  16583. }
  16584. }
  16585. }
  16586. },
  16587. handleKeyboard: function(event) {
  16588. var
  16589. // force selector refresh
  16590. $result = $module.find(selector.result),
  16591. $category = $module.find(selector.category),
  16592. $activeResult = $result.filter('.' + className.active),
  16593. currentIndex = $result.index( $activeResult ),
  16594. resultSize = $result.length,
  16595. hasActiveResult = $activeResult.length > 0,
  16596. keyCode = event.which,
  16597. keys = {
  16598. backspace : 8,
  16599. enter : 13,
  16600. escape : 27,
  16601. upArrow : 38,
  16602. downArrow : 40
  16603. },
  16604. newIndex
  16605. ;
  16606. // search shortcuts
  16607. if(keyCode == keys.escape) {
  16608. module.verbose('Escape key pressed, blurring search field');
  16609. module.hideResults();
  16610. resultsDismissed = true;
  16611. }
  16612. if( module.is.visible() ) {
  16613. if(keyCode == keys.enter) {
  16614. module.verbose('Enter key pressed, selecting active result');
  16615. if( $result.filter('.' + className.active).length > 0 ) {
  16616. module.event.result.click.call($result.filter('.' + className.active), event);
  16617. event.preventDefault();
  16618. return false;
  16619. }
  16620. }
  16621. else if(keyCode == keys.upArrow && hasActiveResult) {
  16622. module.verbose('Up key pressed, changing active result');
  16623. newIndex = (currentIndex - 1 < 0)
  16624. ? currentIndex
  16625. : currentIndex - 1
  16626. ;
  16627. $category
  16628. .removeClass(className.active)
  16629. ;
  16630. $result
  16631. .removeClass(className.active)
  16632. .eq(newIndex)
  16633. .addClass(className.active)
  16634. .closest($category)
  16635. .addClass(className.active)
  16636. ;
  16637. event.preventDefault();
  16638. }
  16639. else if(keyCode == keys.downArrow) {
  16640. module.verbose('Down key pressed, changing active result');
  16641. newIndex = (currentIndex + 1 >= resultSize)
  16642. ? currentIndex
  16643. : currentIndex + 1
  16644. ;
  16645. $category
  16646. .removeClass(className.active)
  16647. ;
  16648. $result
  16649. .removeClass(className.active)
  16650. .eq(newIndex)
  16651. .addClass(className.active)
  16652. .closest($category)
  16653. .addClass(className.active)
  16654. ;
  16655. event.preventDefault();
  16656. }
  16657. }
  16658. else {
  16659. // query shortcuts
  16660. if(keyCode == keys.enter) {
  16661. module.verbose('Enter key pressed, executing query');
  16662. module.query();
  16663. module.set.buttonPressed();
  16664. $prompt.one('keyup', module.remove.buttonFocus);
  16665. }
  16666. }
  16667. },
  16668. setup: {
  16669. api: function(searchTerm, callback) {
  16670. var
  16671. apiSettings = {
  16672. debug : settings.debug,
  16673. on : false,
  16674. cache : settings.cache,
  16675. action : 'search',
  16676. urlData : {
  16677. query : searchTerm
  16678. },
  16679. onSuccess : function(response) {
  16680. module.parse.response.call(element, response, searchTerm);
  16681. callback();
  16682. },
  16683. onFailure : function() {
  16684. module.displayMessage(error.serverError);
  16685. callback();
  16686. },
  16687. onAbort : function(response) {
  16688. },
  16689. onError : module.error
  16690. }
  16691. ;
  16692. $.extend(true, apiSettings, settings.apiSettings);
  16693. module.verbose('Setting up API request', apiSettings);
  16694. $module.api(apiSettings);
  16695. }
  16696. },
  16697. can: {
  16698. useAPI: function() {
  16699. return $.fn.api !== undefined;
  16700. },
  16701. show: function() {
  16702. return module.is.focused() && !module.is.visible() && !module.is.empty();
  16703. },
  16704. transition: function() {
  16705. return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
  16706. }
  16707. },
  16708. is: {
  16709. animating: function() {
  16710. return $results.hasClass(className.animating);
  16711. },
  16712. hidden: function() {
  16713. return $results.hasClass(className.hidden);
  16714. },
  16715. inMessage: function(event) {
  16716. if(!event.target) {
  16717. return;
  16718. }
  16719. var
  16720. $target = $(event.target),
  16721. isInDOM = $.contains(document.documentElement, event.target)
  16722. ;
  16723. return (isInDOM && $target.closest(selector.message).length > 0);
  16724. },
  16725. empty: function() {
  16726. return ($results.html() === '');
  16727. },
  16728. visible: function() {
  16729. return ($results.filter(':visible').length > 0);
  16730. },
  16731. focused: function() {
  16732. return ($prompt.filter(':focus').length > 0);
  16733. }
  16734. },
  16735. get: {
  16736. settings: function() {
  16737. if($.isPlainObject(parameters) && parameters.searchFullText) {
  16738. settings.fullTextSearch = parameters.searchFullText;
  16739. module.error(settings.error.oldSearchSyntax, element);
  16740. }
  16741. if (settings.ignoreDiacritics && !String.prototype.normalize) {
  16742. settings.ignoreDiacritics = false;
  16743. module.error(error.noNormalize, element);
  16744. }
  16745. },
  16746. inputEvent: function() {
  16747. var
  16748. prompt = $prompt[0],
  16749. inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
  16750. ? 'input'
  16751. : (prompt !== undefined && prompt.onpropertychange !== undefined)
  16752. ? 'propertychange'
  16753. : 'keyup'
  16754. ;
  16755. return inputEvent;
  16756. },
  16757. value: function() {
  16758. return $prompt.val();
  16759. },
  16760. results: function() {
  16761. var
  16762. results = $module.data(metadata.results)
  16763. ;
  16764. return results;
  16765. },
  16766. result: function(value, results) {
  16767. var
  16768. result = false
  16769. ;
  16770. value = (value !== undefined)
  16771. ? value
  16772. : module.get.value()
  16773. ;
  16774. results = (results !== undefined)
  16775. ? results
  16776. : module.get.results()
  16777. ;
  16778. if(settings.type === 'category') {
  16779. module.debug('Finding result that matches', value);
  16780. $.each(results, function(index, category) {
  16781. if(Array.isArray(category.results)) {
  16782. result = module.search.object(value, category.results)[0];
  16783. // don't continue searching if a result is found
  16784. if(result) {
  16785. return false;
  16786. }
  16787. }
  16788. });
  16789. }
  16790. else {
  16791. module.debug('Finding result in results object', value);
  16792. result = module.search.object(value, results)[0];
  16793. }
  16794. return result || false;
  16795. },
  16796. },
  16797. select: {
  16798. firstResult: function() {
  16799. module.verbose('Selecting first result');
  16800. $result.first().addClass(className.active);
  16801. }
  16802. },
  16803. set: {
  16804. focus: function() {
  16805. $module.addClass(className.focus);
  16806. },
  16807. loading: function() {
  16808. $module.addClass(className.loading);
  16809. },
  16810. value: function(value) {
  16811. module.verbose('Setting search input value', value);
  16812. $prompt
  16813. .val(value)
  16814. ;
  16815. },
  16816. type: function(type) {
  16817. type = type || settings.type;
  16818. if(settings.type == 'category') {
  16819. $module.addClass(settings.type);
  16820. }
  16821. },
  16822. buttonPressed: function() {
  16823. $searchButton.addClass(className.pressed);
  16824. }
  16825. },
  16826. remove: {
  16827. loading: function() {
  16828. $module.removeClass(className.loading);
  16829. },
  16830. focus: function() {
  16831. $module.removeClass(className.focus);
  16832. },
  16833. buttonPressed: function() {
  16834. $searchButton.removeClass(className.pressed);
  16835. },
  16836. diacritics: function(text) {
  16837. return settings.ignoreDiacritics ? text.normalize('NFD').replace(/[\u0300-\u036f]/g, '') : text;
  16838. }
  16839. },
  16840. query: function(callback) {
  16841. callback = $.isFunction(callback)
  16842. ? callback
  16843. : function(){}
  16844. ;
  16845. var
  16846. searchTerm = module.get.value(),
  16847. cache = module.read.cache(searchTerm)
  16848. ;
  16849. callback = callback || function() {};
  16850. if( module.has.minimumCharacters() ) {
  16851. if(cache) {
  16852. module.debug('Reading result from cache', searchTerm);
  16853. module.save.results(cache.results);
  16854. module.addResults(cache.html);
  16855. module.inject.id(cache.results);
  16856. callback();
  16857. }
  16858. else {
  16859. module.debug('Querying for', searchTerm);
  16860. if($.isPlainObject(settings.source) || Array.isArray(settings.source)) {
  16861. module.search.local(searchTerm);
  16862. callback();
  16863. }
  16864. else if( module.can.useAPI() ) {
  16865. module.search.remote(searchTerm, callback);
  16866. }
  16867. else {
  16868. module.error(error.source);
  16869. callback();
  16870. }
  16871. }
  16872. settings.onSearchQuery.call(element, searchTerm);
  16873. }
  16874. else {
  16875. module.hideResults();
  16876. }
  16877. },
  16878. search: {
  16879. local: function(searchTerm) {
  16880. var
  16881. results = module.search.object(searchTerm, settings.source),
  16882. searchHTML
  16883. ;
  16884. module.set.loading();
  16885. module.save.results(results);
  16886. module.debug('Returned full local search results', results);
  16887. if(settings.maxResults > 0) {
  16888. module.debug('Using specified max results', results);
  16889. results = results.slice(0, settings.maxResults);
  16890. }
  16891. if(settings.type == 'category') {
  16892. results = module.create.categoryResults(results);
  16893. }
  16894. searchHTML = module.generateResults({
  16895. results: results
  16896. });
  16897. module.remove.loading();
  16898. module.addResults(searchHTML);
  16899. module.inject.id(results);
  16900. module.write.cache(searchTerm, {
  16901. html : searchHTML,
  16902. results : results
  16903. });
  16904. },
  16905. remote: function(searchTerm, callback) {
  16906. callback = $.isFunction(callback)
  16907. ? callback
  16908. : function(){}
  16909. ;
  16910. if($module.api('is loading')) {
  16911. $module.api('abort');
  16912. }
  16913. module.setup.api(searchTerm, callback);
  16914. $module
  16915. .api('query')
  16916. ;
  16917. },
  16918. object: function(searchTerm, source, searchFields) {
  16919. searchTerm = module.remove.diacritics(String(searchTerm));
  16920. var
  16921. results = [],
  16922. exactResults = [],
  16923. fuzzyResults = [],
  16924. searchExp = searchTerm.replace(regExp.escape, '\\$&'),
  16925. matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
  16926. // avoid duplicates when pushing results
  16927. addResult = function(array, result) {
  16928. var
  16929. notResult = ($.inArray(result, results) == -1),
  16930. notFuzzyResult = ($.inArray(result, fuzzyResults) == -1),
  16931. notExactResults = ($.inArray(result, exactResults) == -1)
  16932. ;
  16933. if(notResult && notFuzzyResult && notExactResults) {
  16934. array.push(result);
  16935. }
  16936. }
  16937. ;
  16938. source = source || settings.source;
  16939. searchFields = (searchFields !== undefined)
  16940. ? searchFields
  16941. : settings.searchFields
  16942. ;
  16943. // search fields should be array to loop correctly
  16944. if(!Array.isArray(searchFields)) {
  16945. searchFields = [searchFields];
  16946. }
  16947. // exit conditions if no source
  16948. if(source === undefined || source === false) {
  16949. module.error(error.source);
  16950. return [];
  16951. }
  16952. // iterate through search fields looking for matches
  16953. $.each(searchFields, function(index, field) {
  16954. $.each(source, function(label, content) {
  16955. var
  16956. fieldExists = (typeof content[field] == 'string') || (typeof content[field] == 'number')
  16957. ;
  16958. if(fieldExists) {
  16959. var text;
  16960. if (typeof content[field] === 'string'){
  16961. text = module.remove.diacritics(content[field]);
  16962. } else {
  16963. text = content[field].toString();
  16964. }
  16965. if( text.search(matchRegExp) !== -1) {
  16966. // content starts with value (first in results)
  16967. addResult(results, content);
  16968. }
  16969. else if(settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text) ) {
  16970. // content fuzzy matches (last in results)
  16971. addResult(exactResults, content);
  16972. }
  16973. else if(settings.fullTextSearch == true && module.fuzzySearch(searchTerm, text) ) {
  16974. // content fuzzy matches (last in results)
  16975. addResult(fuzzyResults, content);
  16976. }
  16977. }
  16978. });
  16979. });
  16980. $.merge(exactResults, fuzzyResults);
  16981. $.merge(results, exactResults);
  16982. return results;
  16983. }
  16984. },
  16985. exactSearch: function (query, term) {
  16986. query = query.toLowerCase();
  16987. term = term.toLowerCase();
  16988. return term.indexOf(query) > -1;
  16989. },
  16990. fuzzySearch: function(query, term) {
  16991. var
  16992. termLength = term.length,
  16993. queryLength = query.length
  16994. ;
  16995. if(typeof query !== 'string') {
  16996. return false;
  16997. }
  16998. query = query.toLowerCase();
  16999. term = term.toLowerCase();
  17000. if(queryLength > termLength) {
  17001. return false;
  17002. }
  17003. if(queryLength === termLength) {
  17004. return (query === term);
  17005. }
  17006. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  17007. var
  17008. queryCharacter = query.charCodeAt(characterIndex)
  17009. ;
  17010. while(nextCharacterIndex < termLength) {
  17011. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  17012. continue search;
  17013. }
  17014. }
  17015. return false;
  17016. }
  17017. return true;
  17018. },
  17019. parse: {
  17020. response: function(response, searchTerm) {
  17021. if(Array.isArray(response)){
  17022. var o={};
  17023. o[fields.results]=response;
  17024. response = o;
  17025. }
  17026. var
  17027. searchHTML = module.generateResults(response)
  17028. ;
  17029. module.verbose('Parsing server response', response);
  17030. if(response !== undefined) {
  17031. if(searchTerm !== undefined && response[fields.results] !== undefined) {
  17032. module.addResults(searchHTML);
  17033. module.inject.id(response[fields.results]);
  17034. module.write.cache(searchTerm, {
  17035. html : searchHTML,
  17036. results : response[fields.results]
  17037. });
  17038. module.save.results(response[fields.results]);
  17039. }
  17040. }
  17041. }
  17042. },
  17043. cancel: {
  17044. query: function() {
  17045. if( module.can.useAPI() ) {
  17046. $module.api('abort');
  17047. }
  17048. }
  17049. },
  17050. has: {
  17051. minimumCharacters: function() {
  17052. var
  17053. searchTerm = module.get.value(),
  17054. numCharacters = searchTerm.length
  17055. ;
  17056. return (numCharacters >= settings.minCharacters);
  17057. },
  17058. results: function() {
  17059. if($results.length === 0) {
  17060. return false;
  17061. }
  17062. var
  17063. html = $results.html()
  17064. ;
  17065. return html != '';
  17066. }
  17067. },
  17068. clear: {
  17069. cache: function(value) {
  17070. var
  17071. cache = $module.data(metadata.cache)
  17072. ;
  17073. if(!value) {
  17074. module.debug('Clearing cache', value);
  17075. $module.removeData(metadata.cache);
  17076. }
  17077. else if(value && cache && cache[value]) {
  17078. module.debug('Removing value from cache', value);
  17079. delete cache[value];
  17080. $module.data(metadata.cache, cache);
  17081. }
  17082. }
  17083. },
  17084. read: {
  17085. cache: function(name) {
  17086. var
  17087. cache = $module.data(metadata.cache)
  17088. ;
  17089. if(settings.cache) {
  17090. module.verbose('Checking cache for generated html for query', name);
  17091. return (typeof cache == 'object') && (cache[name] !== undefined)
  17092. ? cache[name]
  17093. : false
  17094. ;
  17095. }
  17096. return false;
  17097. }
  17098. },
  17099. create: {
  17100. categoryResults: function(results) {
  17101. var
  17102. categoryResults = {}
  17103. ;
  17104. $.each(results, function(index, result) {
  17105. if(!result.category) {
  17106. return;
  17107. }
  17108. if(categoryResults[result.category] === undefined) {
  17109. module.verbose('Creating new category of results', result.category);
  17110. categoryResults[result.category] = {
  17111. name : result.category,
  17112. results : [result]
  17113. };
  17114. }
  17115. else {
  17116. categoryResults[result.category].results.push(result);
  17117. }
  17118. });
  17119. return categoryResults;
  17120. },
  17121. id: function(resultIndex, categoryIndex) {
  17122. var
  17123. resultID = (resultIndex + 1), // not zero indexed
  17124. letterID,
  17125. id
  17126. ;
  17127. if(categoryIndex !== undefined) {
  17128. // start char code for "A"
  17129. letterID = String.fromCharCode(97 + categoryIndex);
  17130. id = letterID + resultID;
  17131. module.verbose('Creating category result id', id);
  17132. }
  17133. else {
  17134. id = resultID;
  17135. module.verbose('Creating result id', id);
  17136. }
  17137. return id;
  17138. },
  17139. results: function() {
  17140. if($results.length === 0) {
  17141. $results = $('<div />')
  17142. .addClass(className.results)
  17143. .appendTo($module)
  17144. ;
  17145. }
  17146. }
  17147. },
  17148. inject: {
  17149. result: function(result, resultIndex, categoryIndex) {
  17150. module.verbose('Injecting result into results');
  17151. var
  17152. $selectedResult = (categoryIndex !== undefined)
  17153. ? $results
  17154. .children().eq(categoryIndex)
  17155. .children(selector.results)
  17156. .first()
  17157. .children(selector.result)
  17158. .eq(resultIndex)
  17159. : $results
  17160. .children(selector.result).eq(resultIndex)
  17161. ;
  17162. module.verbose('Injecting results metadata', $selectedResult);
  17163. $selectedResult
  17164. .data(metadata.result, result)
  17165. ;
  17166. },
  17167. id: function(results) {
  17168. module.debug('Injecting unique ids into results');
  17169. var
  17170. // since results may be object, we must use counters
  17171. categoryIndex = 0,
  17172. resultIndex = 0
  17173. ;
  17174. if(settings.type === 'category') {
  17175. // iterate through each category result
  17176. $.each(results, function(index, category) {
  17177. if(category.results.length > 0){
  17178. resultIndex = 0;
  17179. $.each(category.results, function(index, result) {
  17180. if(result.id === undefined) {
  17181. result.id = module.create.id(resultIndex, categoryIndex);
  17182. }
  17183. module.inject.result(result, resultIndex, categoryIndex);
  17184. resultIndex++;
  17185. });
  17186. categoryIndex++;
  17187. }
  17188. });
  17189. }
  17190. else {
  17191. // top level
  17192. $.each(results, function(index, result) {
  17193. if(result.id === undefined) {
  17194. result.id = module.create.id(resultIndex);
  17195. }
  17196. module.inject.result(result, resultIndex);
  17197. resultIndex++;
  17198. });
  17199. }
  17200. return results;
  17201. }
  17202. },
  17203. save: {
  17204. results: function(results) {
  17205. module.verbose('Saving current search results to metadata', results);
  17206. $module.data(metadata.results, results);
  17207. }
  17208. },
  17209. write: {
  17210. cache: function(name, value) {
  17211. var
  17212. cache = ($module.data(metadata.cache) !== undefined)
  17213. ? $module.data(metadata.cache)
  17214. : {}
  17215. ;
  17216. if(settings.cache) {
  17217. module.verbose('Writing generated html to cache', name, value);
  17218. cache[name] = value;
  17219. $module
  17220. .data(metadata.cache, cache)
  17221. ;
  17222. }
  17223. }
  17224. },
  17225. addResults: function(html) {
  17226. if( $.isFunction(settings.onResultsAdd) ) {
  17227. if( settings.onResultsAdd.call($results, html) === false ) {
  17228. module.debug('onResultsAdd callback cancelled default action');
  17229. return false;
  17230. }
  17231. }
  17232. if(html) {
  17233. $results
  17234. .html(html)
  17235. ;
  17236. module.refreshResults();
  17237. if(settings.selectFirstResult) {
  17238. module.select.firstResult();
  17239. }
  17240. module.showResults();
  17241. }
  17242. else {
  17243. module.hideResults(function() {
  17244. $results.empty();
  17245. });
  17246. }
  17247. },
  17248. showResults: function(callback) {
  17249. callback = $.isFunction(callback)
  17250. ? callback
  17251. : function(){}
  17252. ;
  17253. if(resultsDismissed) {
  17254. return;
  17255. }
  17256. if(!module.is.visible() && module.has.results()) {
  17257. if( module.can.transition() ) {
  17258. module.debug('Showing results with css animations');
  17259. $results
  17260. .transition({
  17261. animation : settings.transition + ' in',
  17262. debug : settings.debug,
  17263. verbose : settings.verbose,
  17264. duration : settings.duration,
  17265. onComplete : function() {
  17266. callback();
  17267. },
  17268. queue : true
  17269. })
  17270. ;
  17271. }
  17272. else {
  17273. module.debug('Showing results with javascript');
  17274. $results
  17275. .stop()
  17276. .fadeIn(settings.duration, settings.easing)
  17277. ;
  17278. }
  17279. settings.onResultsOpen.call($results);
  17280. }
  17281. },
  17282. hideResults: function(callback) {
  17283. callback = $.isFunction(callback)
  17284. ? callback
  17285. : function(){}
  17286. ;
  17287. if( module.is.visible() ) {
  17288. if( module.can.transition() ) {
  17289. module.debug('Hiding results with css animations');
  17290. $results
  17291. .transition({
  17292. animation : settings.transition + ' out',
  17293. debug : settings.debug,
  17294. verbose : settings.verbose,
  17295. duration : settings.duration,
  17296. onComplete : function() {
  17297. callback();
  17298. },
  17299. queue : true
  17300. })
  17301. ;
  17302. }
  17303. else {
  17304. module.debug('Hiding results with javascript');
  17305. $results
  17306. .stop()
  17307. .fadeOut(settings.duration, settings.easing)
  17308. ;
  17309. }
  17310. settings.onResultsClose.call($results);
  17311. }
  17312. },
  17313. generateResults: function(response) {
  17314. module.debug('Generating html from response', response);
  17315. var
  17316. template = settings.templates[settings.type],
  17317. isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])),
  17318. isProperArray = (Array.isArray(response[fields.results]) && response[fields.results].length > 0),
  17319. html = ''
  17320. ;
  17321. if(isProperObject || isProperArray ) {
  17322. if(settings.maxResults > 0) {
  17323. if(isProperObject) {
  17324. if(settings.type == 'standard') {
  17325. module.error(error.maxResults);
  17326. }
  17327. }
  17328. else {
  17329. response[fields.results] = response[fields.results].slice(0, settings.maxResults);
  17330. }
  17331. }
  17332. if($.isFunction(template)) {
  17333. html = template(response, fields, settings.preserveHTML);
  17334. }
  17335. else {
  17336. module.error(error.noTemplate, false);
  17337. }
  17338. }
  17339. else if(settings.showNoResults) {
  17340. html = module.displayMessage(error.noResults, 'empty', error.noResultsHeader);
  17341. }
  17342. settings.onResults.call(element, response);
  17343. return html;
  17344. },
  17345. displayMessage: function(text, type, header) {
  17346. type = type || 'standard';
  17347. module.debug('Displaying message', text, type, header);
  17348. module.addResults( settings.templates.message(text, type, header) );
  17349. return settings.templates.message(text, type, header);
  17350. },
  17351. setting: function(name, value) {
  17352. if( $.isPlainObject(name) ) {
  17353. $.extend(true, settings, name);
  17354. }
  17355. else if(value !== undefined) {
  17356. settings[name] = value;
  17357. }
  17358. else {
  17359. return settings[name];
  17360. }
  17361. },
  17362. internal: function(name, value) {
  17363. if( $.isPlainObject(name) ) {
  17364. $.extend(true, module, name);
  17365. }
  17366. else if(value !== undefined) {
  17367. module[name] = value;
  17368. }
  17369. else {
  17370. return module[name];
  17371. }
  17372. },
  17373. debug: function() {
  17374. if(!settings.silent && settings.debug) {
  17375. if(settings.performance) {
  17376. module.performance.log(arguments);
  17377. }
  17378. else {
  17379. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17380. module.debug.apply(console, arguments);
  17381. }
  17382. }
  17383. },
  17384. verbose: function() {
  17385. if(!settings.silent && settings.verbose && settings.debug) {
  17386. if(settings.performance) {
  17387. module.performance.log(arguments);
  17388. }
  17389. else {
  17390. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17391. module.verbose.apply(console, arguments);
  17392. }
  17393. }
  17394. },
  17395. error: function() {
  17396. if(!settings.silent) {
  17397. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  17398. module.error.apply(console, arguments);
  17399. }
  17400. },
  17401. performance: {
  17402. log: function(message) {
  17403. var
  17404. currentTime,
  17405. executionTime,
  17406. previousTime
  17407. ;
  17408. if(settings.performance) {
  17409. currentTime = new Date().getTime();
  17410. previousTime = time || currentTime;
  17411. executionTime = currentTime - previousTime;
  17412. time = currentTime;
  17413. performance.push({
  17414. 'Name' : message[0],
  17415. 'Arguments' : [].slice.call(message, 1) || '',
  17416. 'Element' : element,
  17417. 'Execution Time' : executionTime
  17418. });
  17419. }
  17420. clearTimeout(module.performance.timer);
  17421. module.performance.timer = setTimeout(module.performance.display, 500);
  17422. },
  17423. display: function() {
  17424. var
  17425. title = settings.name + ':',
  17426. totalTime = 0
  17427. ;
  17428. time = false;
  17429. clearTimeout(module.performance.timer);
  17430. $.each(performance, function(index, data) {
  17431. totalTime += data['Execution Time'];
  17432. });
  17433. title += ' ' + totalTime + 'ms';
  17434. if(moduleSelector) {
  17435. title += ' \'' + moduleSelector + '\'';
  17436. }
  17437. if($allModules.length > 1) {
  17438. title += ' ' + '(' + $allModules.length + ')';
  17439. }
  17440. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  17441. console.groupCollapsed(title);
  17442. if(console.table) {
  17443. console.table(performance);
  17444. }
  17445. else {
  17446. $.each(performance, function(index, data) {
  17447. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  17448. });
  17449. }
  17450. console.groupEnd();
  17451. }
  17452. performance = [];
  17453. }
  17454. },
  17455. invoke: function(query, passedArguments, context) {
  17456. var
  17457. object = instance,
  17458. maxDepth,
  17459. found,
  17460. response
  17461. ;
  17462. passedArguments = passedArguments || queryArguments;
  17463. context = element || context;
  17464. if(typeof query == 'string' && object !== undefined) {
  17465. query = query.split(/[\. ]/);
  17466. maxDepth = query.length - 1;
  17467. $.each(query, function(depth, value) {
  17468. var camelCaseValue = (depth != maxDepth)
  17469. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  17470. : query
  17471. ;
  17472. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  17473. object = object[camelCaseValue];
  17474. }
  17475. else if( object[camelCaseValue] !== undefined ) {
  17476. found = object[camelCaseValue];
  17477. return false;
  17478. }
  17479. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  17480. object = object[value];
  17481. }
  17482. else if( object[value] !== undefined ) {
  17483. found = object[value];
  17484. return false;
  17485. }
  17486. else {
  17487. return false;
  17488. }
  17489. });
  17490. }
  17491. if( $.isFunction( found ) ) {
  17492. response = found.apply(context, passedArguments);
  17493. }
  17494. else if(found !== undefined) {
  17495. response = found;
  17496. }
  17497. if(Array.isArray(returnedValue)) {
  17498. returnedValue.push(response);
  17499. }
  17500. else if(returnedValue !== undefined) {
  17501. returnedValue = [returnedValue, response];
  17502. }
  17503. else if(response !== undefined) {
  17504. returnedValue = response;
  17505. }
  17506. return found;
  17507. }
  17508. };
  17509. if(methodInvoked) {
  17510. if(instance === undefined) {
  17511. module.initialize();
  17512. }
  17513. module.invoke(query);
  17514. }
  17515. else {
  17516. if(instance !== undefined) {
  17517. instance.invoke('destroy');
  17518. }
  17519. module.initialize();
  17520. }
  17521. })
  17522. ;
  17523. return (returnedValue !== undefined)
  17524. ? returnedValue
  17525. : this
  17526. ;
  17527. };
  17528. $.fn.search.settings = {
  17529. name : 'Search',
  17530. namespace : 'search',
  17531. silent : false,
  17532. debug : false,
  17533. verbose : false,
  17534. performance : true,
  17535. // template to use (specified in settings.templates)
  17536. type : 'standard',
  17537. // minimum characters required to search
  17538. minCharacters : 1,
  17539. // whether to select first result after searching automatically
  17540. selectFirstResult : false,
  17541. // API config
  17542. apiSettings : false,
  17543. // object to search
  17544. source : false,
  17545. // Whether search should query current term on focus
  17546. searchOnFocus : true,
  17547. // fields to search
  17548. searchFields : [
  17549. 'id',
  17550. 'title',
  17551. 'description'
  17552. ],
  17553. // field to display in standard results template
  17554. displayField : '',
  17555. // search anywhere in value (set to 'exact' to require exact matches
  17556. fullTextSearch : 'exact',
  17557. // match results also if they contain diacritics of the same base character (for example searching for "a" will also match "á" or "â" or "à", etc...)
  17558. ignoreDiacritics : false,
  17559. // whether to add events to prompt automatically
  17560. automatic : true,
  17561. // delay before hiding menu after blur
  17562. hideDelay : 0,
  17563. // delay before searching
  17564. searchDelay : 200,
  17565. // maximum results returned from search
  17566. maxResults : 7,
  17567. // whether to store lookups in local cache
  17568. cache : true,
  17569. // whether no results errors should be shown
  17570. showNoResults : true,
  17571. // preserve possible html of resultset values
  17572. preserveHTML : true,
  17573. // transition settings
  17574. transition : 'scale',
  17575. duration : 200,
  17576. easing : 'easeOutExpo',
  17577. // callbacks
  17578. onSelect : false,
  17579. onResultsAdd : false,
  17580. onSearchQuery : function(query){},
  17581. onResults : function(response){},
  17582. onResultsOpen : function(){},
  17583. onResultsClose : function(){},
  17584. className: {
  17585. animating : 'animating',
  17586. active : 'active',
  17587. empty : 'empty',
  17588. focus : 'focus',
  17589. hidden : 'hidden',
  17590. loading : 'loading',
  17591. results : 'results',
  17592. pressed : 'down'
  17593. },
  17594. error : {
  17595. source : 'Cannot search. No source used, and Semantic API module was not included',
  17596. noResultsHeader : 'No Results',
  17597. noResults : 'Your search returned no results',
  17598. logging : 'Error in debug logging, exiting.',
  17599. noEndpoint : 'No search endpoint was specified',
  17600. noTemplate : 'A valid template name was not specified.',
  17601. oldSearchSyntax : 'searchFullText setting has been renamed fullTextSearch for consistency, please adjust your settings.',
  17602. serverError : 'There was an issue querying the server.',
  17603. maxResults : 'Results must be an array to use maxResults setting',
  17604. method : 'The method you called is not defined.',
  17605. noNormalize : '"ignoreDiacritics" setting will be ignored. Browser does not support String().normalize(). You may consider including <https://cdn.jsdelivr.net/npm/[email protected]/lib/unorm.min.js> as a polyfill.'
  17606. },
  17607. metadata: {
  17608. cache : 'cache',
  17609. results : 'results',
  17610. result : 'result'
  17611. },
  17612. regExp: {
  17613. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  17614. beginsWith : '(?:\s|^)'
  17615. },
  17616. // maps api response attributes to internal representation
  17617. fields: {
  17618. categories : 'results', // array of categories (category view)
  17619. categoryName : 'name', // name of category (category view)
  17620. categoryResults : 'results', // array of results (category view)
  17621. description : 'description', // result description
  17622. image : 'image', // result image
  17623. price : 'price', // result price
  17624. results : 'results', // array of results (standard)
  17625. title : 'title', // result title
  17626. url : 'url', // result url
  17627. action : 'action', // "view more" object name
  17628. actionText : 'text', // "view more" text
  17629. actionURL : 'url' // "view more" url
  17630. },
  17631. selector : {
  17632. prompt : '.prompt',
  17633. searchButton : '.search.button',
  17634. results : '.results',
  17635. message : '.results > .message',
  17636. category : '.category',
  17637. result : '.result',
  17638. title : '.title, .name'
  17639. },
  17640. templates: {
  17641. escape: function(string, preserveHTML) {
  17642. if (preserveHTML){
  17643. return string;
  17644. }
  17645. var
  17646. badChars = /[<>"'`]/g,
  17647. shouldEscape = /[&<>"'`]/,
  17648. escape = {
  17649. "<": "&lt;",
  17650. ">": "&gt;",
  17651. '"': "&quot;",
  17652. "'": "&#x27;",
  17653. "`": "&#x60;"
  17654. },
  17655. escapedChar = function(chr) {
  17656. return escape[chr];
  17657. }
  17658. ;
  17659. if(shouldEscape.test(string)) {
  17660. string = string.replace(/&(?![a-z0-9#]{1,6};)/, "&amp;");
  17661. return string.replace(badChars, escapedChar);
  17662. }
  17663. return string;
  17664. },
  17665. message: function(message, type, header) {
  17666. var
  17667. html = ''
  17668. ;
  17669. if(message !== undefined && type !== undefined) {
  17670. html += ''
  17671. + '<div class="message ' + type + '">'
  17672. ;
  17673. if(header) {
  17674. html += ''
  17675. + '<div class="header">' + header + '</div>'
  17676. ;
  17677. }
  17678. html += ' <div class="description">' + message + '</div>';
  17679. html += '</div>';
  17680. }
  17681. return html;
  17682. },
  17683. category: function(response, fields, preserveHTML) {
  17684. var
  17685. html = '',
  17686. escape = $.fn.search.settings.templates.escape
  17687. ;
  17688. if(response[fields.categoryResults] !== undefined) {
  17689. // each category
  17690. $.each(response[fields.categoryResults], function(index, category) {
  17691. if(category[fields.results] !== undefined && category.results.length > 0) {
  17692. html += '<div class="category">';
  17693. if(category[fields.categoryName] !== undefined) {
  17694. html += '<div class="name">' + escape(category[fields.categoryName], preserveHTML) + '</div>';
  17695. }
  17696. // each item inside category
  17697. html += '<div class="results">';
  17698. $.each(category.results, function(index, result) {
  17699. if(result[fields.url]) {
  17700. html += '<a class="result" href="' + result[fields.url].replace(/"/g,"") + '">';
  17701. }
  17702. else {
  17703. html += '<a class="result">';
  17704. }
  17705. if(result[fields.image] !== undefined) {
  17706. html += ''
  17707. + '<div class="image">'
  17708. + ' <img src="' + result[fields.image].replace(/"/g,"") + '">'
  17709. + '</div>'
  17710. ;
  17711. }
  17712. html += '<div class="content">';
  17713. if(result[fields.price] !== undefined) {
  17714. html += '<div class="price">' + escape(result[fields.price], preserveHTML) + '</div>';
  17715. }
  17716. if(result[fields.title] !== undefined) {
  17717. html += '<div class="title">' + escape(result[fields.title], preserveHTML) + '</div>';
  17718. }
  17719. if(result[fields.description] !== undefined) {
  17720. html += '<div class="description">' + escape(result[fields.description], preserveHTML) + '</div>';
  17721. }
  17722. html += ''
  17723. + '</div>'
  17724. ;
  17725. html += '</a>';
  17726. });
  17727. html += '</div>';
  17728. html += ''
  17729. + '</div>'
  17730. ;
  17731. }
  17732. });
  17733. if(response[fields.action]) {
  17734. if(fields.actionURL === false) {
  17735. html += ''
  17736. + '<div class="action">'
  17737. + escape(response[fields.action][fields.actionText], preserveHTML)
  17738. + '</div>';
  17739. } else {
  17740. html += ''
  17741. + '<a href="' + response[fields.action][fields.actionURL].replace(/"/g,"") + '" class="action">'
  17742. + escape(response[fields.action][fields.actionText], preserveHTML)
  17743. + '</a>';
  17744. }
  17745. }
  17746. return html;
  17747. }
  17748. return false;
  17749. },
  17750. standard: function(response, fields, preserveHTML) {
  17751. var
  17752. html = '',
  17753. escape = $.fn.search.settings.templates.escape
  17754. ;
  17755. if(response[fields.results] !== undefined) {
  17756. // each result
  17757. $.each(response[fields.results], function(index, result) {
  17758. if(result[fields.url]) {
  17759. html += '<a class="result" href="' + result[fields.url].replace(/"/g,"") + '">';
  17760. }
  17761. else {
  17762. html += '<a class="result">';
  17763. }
  17764. if(result[fields.image] !== undefined) {
  17765. html += ''
  17766. + '<div class="image">'
  17767. + ' <img src="' + result[fields.image].replace(/"/g,"") + '">'
  17768. + '</div>'
  17769. ;
  17770. }
  17771. html += '<div class="content">';
  17772. if(result[fields.price] !== undefined) {
  17773. html += '<div class="price">' + escape(result[fields.price], preserveHTML) + '</div>';
  17774. }
  17775. if(result[fields.title] !== undefined) {
  17776. html += '<div class="title">' + escape(result[fields.title], preserveHTML) + '</div>';
  17777. }
  17778. if(result[fields.description] !== undefined) {
  17779. html += '<div class="description">' + escape(result[fields.description], preserveHTML) + '</div>';
  17780. }
  17781. html += ''
  17782. + '</div>'
  17783. ;
  17784. html += '</a>';
  17785. });
  17786. if(response[fields.action]) {
  17787. if(fields.actionURL === false) {
  17788. html += ''
  17789. + '<div class="action">'
  17790. + escape(response[fields.action][fields.actionText], preserveHTML)
  17791. + '</div>';
  17792. } else {
  17793. html += ''
  17794. + '<a href="' + response[fields.action][fields.actionURL].replace(/"/g,"") + '" class="action">'
  17795. + escape(response[fields.action][fields.actionText], preserveHTML)
  17796. + '</a>';
  17797. }
  17798. }
  17799. return html;
  17800. }
  17801. return false;
  17802. }
  17803. }
  17804. };
  17805. })( jQuery, window, document );
  17806. /*!
  17807. * # Fomantic-UI - Shape
  17808. * http://github.com/fomantic/Fomantic-UI/
  17809. *
  17810. *
  17811. * Released under the MIT license
  17812. * http://opensource.org/licenses/MIT
  17813. *
  17814. */
  17815. ;(function ($, window, document, undefined) {
  17816. 'use strict';
  17817. $.isFunction = $.isFunction || function(obj) {
  17818. return typeof obj === "function" && typeof obj.nodeType !== "number";
  17819. };
  17820. window = (typeof window != 'undefined' && window.Math == Math)
  17821. ? window
  17822. : (typeof self != 'undefined' && self.Math == Math)
  17823. ? self
  17824. : Function('return this')()
  17825. ;
  17826. $.fn.shape = function(parameters) {
  17827. var
  17828. $allModules = $(this),
  17829. time = new Date().getTime(),
  17830. performance = [],
  17831. query = arguments[0],
  17832. methodInvoked = (typeof query == 'string'),
  17833. queryArguments = [].slice.call(arguments, 1),
  17834. requestAnimationFrame = window.requestAnimationFrame
  17835. || window.mozRequestAnimationFrame
  17836. || window.webkitRequestAnimationFrame
  17837. || window.msRequestAnimationFrame
  17838. || function(callback) { setTimeout(callback, 0); },
  17839. returnedValue
  17840. ;
  17841. $allModules
  17842. .each(function() {
  17843. var
  17844. moduleSelector = $allModules.selector || '',
  17845. settings = ( $.isPlainObject(parameters) )
  17846. ? $.extend(true, {}, $.fn.shape.settings, parameters)
  17847. : $.extend({}, $.fn.shape.settings),
  17848. // internal aliases
  17849. namespace = settings.namespace,
  17850. selector = settings.selector,
  17851. error = settings.error,
  17852. className = settings.className,
  17853. // define namespaces for modules
  17854. eventNamespace = '.' + namespace,
  17855. moduleNamespace = 'module-' + namespace,
  17856. // selector cache
  17857. $module = $(this),
  17858. $sides = $module.find('>' + selector.sides),
  17859. $side = $sides.find('>' + selector.side),
  17860. // private variables
  17861. nextIndex = false,
  17862. $activeSide,
  17863. $nextSide,
  17864. // standard module
  17865. element = this,
  17866. instance = $module.data(moduleNamespace),
  17867. module
  17868. ;
  17869. module = {
  17870. initialize: function() {
  17871. module.verbose('Initializing module for', element);
  17872. module.set.defaultSide();
  17873. module.instantiate();
  17874. },
  17875. instantiate: function() {
  17876. module.verbose('Storing instance of module', module);
  17877. instance = module;
  17878. $module
  17879. .data(moduleNamespace, instance)
  17880. ;
  17881. },
  17882. destroy: function() {
  17883. module.verbose('Destroying previous module for', element);
  17884. $module
  17885. .removeData(moduleNamespace)
  17886. .off(eventNamespace)
  17887. ;
  17888. },
  17889. refresh: function() {
  17890. module.verbose('Refreshing selector cache for', element);
  17891. $module = $(element);
  17892. $sides = $(this).find(selector.sides);
  17893. $side = $(this).find(selector.side);
  17894. },
  17895. repaint: function() {
  17896. module.verbose('Forcing repaint event');
  17897. var
  17898. shape = $sides[0] || document.createElement('div'),
  17899. fakeAssignment = shape.offsetWidth
  17900. ;
  17901. },
  17902. animate: function(propertyObject, callback) {
  17903. module.verbose('Animating box with properties', propertyObject);
  17904. callback = callback || function(event) {
  17905. module.verbose('Executing animation callback');
  17906. if(event !== undefined) {
  17907. event.stopPropagation();
  17908. }
  17909. module.reset();
  17910. module.set.active();
  17911. };
  17912. settings.beforeChange.call($nextSide[0]);
  17913. if(module.get.transitionEvent()) {
  17914. module.verbose('Starting CSS animation');
  17915. $module
  17916. .addClass(className.animating)
  17917. ;
  17918. $sides
  17919. .css(propertyObject)
  17920. .one(module.get.transitionEvent(), callback)
  17921. ;
  17922. module.set.duration(settings.duration);
  17923. requestAnimationFrame(function() {
  17924. $module
  17925. .addClass(className.animating)
  17926. ;
  17927. $activeSide
  17928. .addClass(className.hidden)
  17929. ;
  17930. });
  17931. }
  17932. else {
  17933. callback();
  17934. }
  17935. },
  17936. queue: function(method) {
  17937. module.debug('Queueing animation of', method);
  17938. $sides
  17939. .one(module.get.transitionEvent(), function() {
  17940. module.debug('Executing queued animation');
  17941. setTimeout(function(){
  17942. $module.shape(method);
  17943. }, 0);
  17944. })
  17945. ;
  17946. },
  17947. reset: function() {
  17948. module.verbose('Animating states reset');
  17949. $module
  17950. .removeClass(className.animating)
  17951. .attr('style', '')
  17952. .removeAttr('style')
  17953. ;
  17954. // removeAttr style does not consistently work in safari
  17955. $sides
  17956. .attr('style', '')
  17957. .removeAttr('style')
  17958. ;
  17959. $side
  17960. .attr('style', '')
  17961. .removeAttr('style')
  17962. .removeClass(className.hidden)
  17963. ;
  17964. $nextSide
  17965. .removeClass(className.animating)
  17966. .attr('style', '')
  17967. .removeAttr('style')
  17968. ;
  17969. },
  17970. is: {
  17971. complete: function() {
  17972. return ($side.filter('.' + className.active)[0] == $nextSide[0]);
  17973. },
  17974. animating: function() {
  17975. return $module.hasClass(className.animating);
  17976. },
  17977. hidden: function() {
  17978. return $module.closest(':hidden').length > 0;
  17979. }
  17980. },
  17981. set: {
  17982. defaultSide: function() {
  17983. $activeSide = $side.filter('.' + settings.className.active);
  17984. $nextSide = ( $activeSide.next(selector.side).length > 0 )
  17985. ? $activeSide.next(selector.side)
  17986. : $side.first()
  17987. ;
  17988. nextIndex = false;
  17989. module.verbose('Active side set to', $activeSide);
  17990. module.verbose('Next side set to', $nextSide);
  17991. },
  17992. duration: function(duration) {
  17993. duration = duration || settings.duration;
  17994. duration = (typeof duration == 'number')
  17995. ? duration + 'ms'
  17996. : duration
  17997. ;
  17998. module.verbose('Setting animation duration', duration);
  17999. if(settings.duration || settings.duration === 0) {
  18000. $sides.add($side)
  18001. .css({
  18002. '-webkit-transition-duration': duration,
  18003. '-moz-transition-duration': duration,
  18004. '-ms-transition-duration': duration,
  18005. '-o-transition-duration': duration,
  18006. 'transition-duration': duration
  18007. })
  18008. ;
  18009. }
  18010. },
  18011. currentStageSize: function() {
  18012. var
  18013. $activeSide = $side.filter('.' + settings.className.active),
  18014. width = $activeSide.outerWidth(true),
  18015. height = $activeSide.outerHeight(true)
  18016. ;
  18017. $module
  18018. .css({
  18019. width: width,
  18020. height: height
  18021. })
  18022. ;
  18023. },
  18024. stageSize: function() {
  18025. var
  18026. $clone = $module.clone().addClass(className.loading),
  18027. $side = $clone.find('>' + selector.sides + '>' + selector.side),
  18028. $activeSide = $side.filter('.' + settings.className.active),
  18029. $nextSide = (nextIndex)
  18030. ? $side.eq(nextIndex)
  18031. : ( $activeSide.next(selector.side).length > 0 )
  18032. ? $activeSide.next(selector.side)
  18033. : $side.first(),
  18034. newWidth = (settings.width === 'next')
  18035. ? $nextSide.outerWidth(true)
  18036. : (settings.width === 'initial')
  18037. ? $module.width()
  18038. : settings.width,
  18039. newHeight = (settings.height === 'next')
  18040. ? $nextSide.outerHeight(true)
  18041. : (settings.height === 'initial')
  18042. ? $module.height()
  18043. : settings.height
  18044. ;
  18045. $activeSide.removeClass(className.active);
  18046. $nextSide.addClass(className.active);
  18047. $clone.insertAfter($module);
  18048. $clone.remove();
  18049. if(settings.width !== 'auto') {
  18050. $module.css('width', newWidth + settings.jitter);
  18051. module.verbose('Specifying width during animation', newWidth);
  18052. }
  18053. if(settings.height !== 'auto') {
  18054. $module.css('height', newHeight + settings.jitter);
  18055. module.verbose('Specifying height during animation', newHeight);
  18056. }
  18057. },
  18058. nextSide: function(selector) {
  18059. nextIndex = selector;
  18060. $nextSide = $side.filter(selector);
  18061. nextIndex = $side.index($nextSide);
  18062. if($nextSide.length === 0) {
  18063. module.set.defaultSide();
  18064. module.error(error.side);
  18065. }
  18066. module.verbose('Next side manually set to', $nextSide);
  18067. },
  18068. active: function() {
  18069. module.verbose('Setting new side to active', $nextSide);
  18070. $side
  18071. .removeClass(className.active)
  18072. ;
  18073. $nextSide
  18074. .addClass(className.active)
  18075. ;
  18076. settings.onChange.call($nextSide[0]);
  18077. module.set.defaultSide();
  18078. }
  18079. },
  18080. flip: {
  18081. to: function(type,stage){
  18082. if(module.is.hidden()) {
  18083. module.debug('Module not visible', $nextSide);
  18084. return;
  18085. }
  18086. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  18087. module.debug('Side already visible', $nextSide);
  18088. return;
  18089. }
  18090. var
  18091. transform = module.get.transform[type]()
  18092. ;
  18093. if( !module.is.animating()) {
  18094. module.debug('Flipping '+type, $nextSide);
  18095. module.set.stageSize();
  18096. module.stage[stage]();
  18097. module.animate(transform);
  18098. }
  18099. else {
  18100. module.queue('flip '+type);
  18101. }
  18102. },
  18103. up: function() {
  18104. module.flip.to('up','above');
  18105. },
  18106. down: function() {
  18107. module.flip.to('down','below');
  18108. },
  18109. left: function() {
  18110. module.flip.to('left','left');
  18111. },
  18112. right: function() {
  18113. module.flip.to('right','right');
  18114. },
  18115. over: function() {
  18116. module.flip.to('over','behind');
  18117. },
  18118. back: function() {
  18119. module.flip.to('back','behind');
  18120. }
  18121. },
  18122. get: {
  18123. transform: {
  18124. up: function() {
  18125. var
  18126. translateZ = $activeSide.outerHeight(true) / 2,
  18127. translateY = $nextSide.outerHeight(true) - translateZ
  18128. ;
  18129. return {
  18130. transform: 'translateY(' + translateY + 'px) translateZ(-'+ translateZ + 'px) rotateX(-90deg)'
  18131. };
  18132. },
  18133. down: function() {
  18134. var
  18135. translate = {
  18136. z: $activeSide.outerHeight(true) / 2
  18137. }
  18138. ;
  18139. return {
  18140. transform: 'translateY(-' + translate.z + 'px) translateZ(-'+ translate.z + 'px) rotateX(90deg)'
  18141. };
  18142. },
  18143. left: function() {
  18144. var
  18145. translateZ = $activeSide.outerWidth(true) / 2,
  18146. translateX = $nextSide.outerWidth(true) - translateZ
  18147. ;
  18148. return {
  18149. transform: 'translateX(' + translateX + 'px) translateZ(-' + translateZ + 'px) rotateY(90deg)'
  18150. };
  18151. },
  18152. right: function() {
  18153. var
  18154. translate = {
  18155. z : $activeSide.outerWidth(true) / 2
  18156. }
  18157. ;
  18158. return {
  18159. transform: 'translateX(-' + translate.z + 'px) translateZ(-' + translate.z + 'px) rotateY(-90deg)'
  18160. };
  18161. },
  18162. over: function() {
  18163. var
  18164. translate = {
  18165. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  18166. }
  18167. ;
  18168. return {
  18169. transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
  18170. };
  18171. },
  18172. back: function() {
  18173. var
  18174. translate = {
  18175. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  18176. }
  18177. ;
  18178. return {
  18179. transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
  18180. };
  18181. }
  18182. },
  18183. transitionEvent: function() {
  18184. var
  18185. element = document.createElement('element'),
  18186. transitions = {
  18187. 'transition' :'transitionend',
  18188. 'OTransition' :'oTransitionEnd',
  18189. 'MozTransition' :'transitionend',
  18190. 'WebkitTransition' :'webkitTransitionEnd'
  18191. },
  18192. transition
  18193. ;
  18194. for(transition in transitions){
  18195. if( element.style[transition] !== undefined ){
  18196. return transitions[transition];
  18197. }
  18198. }
  18199. },
  18200. nextSide: function() {
  18201. return ( $activeSide.next(selector.side).length > 0 )
  18202. ? $activeSide.next(selector.side)
  18203. : $side.first()
  18204. ;
  18205. }
  18206. },
  18207. stage: {
  18208. above: function() {
  18209. var
  18210. box = {
  18211. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  18212. depth : {
  18213. active : ($nextSide.outerHeight(true) / 2),
  18214. next : ($activeSide.outerHeight(true) / 2)
  18215. }
  18216. }
  18217. ;
  18218. module.verbose('Setting the initial animation position as above', $nextSide, box);
  18219. $activeSide
  18220. .css({
  18221. 'transform' : 'rotateX(0deg)'
  18222. })
  18223. ;
  18224. $nextSide
  18225. .addClass(className.animating)
  18226. .css({
  18227. 'top' : box.origin + 'px',
  18228. 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px) translateY(-' + box.depth.active + 'px)'
  18229. })
  18230. ;
  18231. },
  18232. below: function() {
  18233. var
  18234. box = {
  18235. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  18236. depth : {
  18237. active : ($nextSide.outerHeight(true) / 2),
  18238. next : ($activeSide.outerHeight(true) / 2)
  18239. }
  18240. }
  18241. ;
  18242. module.verbose('Setting the initial animation position as below', $nextSide, box);
  18243. $activeSide
  18244. .css({
  18245. 'transform' : 'rotateX(0deg)'
  18246. })
  18247. ;
  18248. $nextSide
  18249. .addClass(className.animating)
  18250. .css({
  18251. 'top' : box.origin + 'px',
  18252. 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px) translateY(' + box.depth.active + 'px)'
  18253. })
  18254. ;
  18255. },
  18256. left: function() {
  18257. var
  18258. height = {
  18259. active : $activeSide.outerWidth(true),
  18260. next : $nextSide.outerWidth(true)
  18261. },
  18262. box = {
  18263. origin : ( ( height.active - height.next ) / 2),
  18264. depth : {
  18265. active : (height.next / 2),
  18266. next : (height.active / 2)
  18267. }
  18268. }
  18269. ;
  18270. module.verbose('Setting the initial animation position as left', $nextSide, box);
  18271. $activeSide
  18272. .css({
  18273. 'transform' : 'rotateY(0deg)'
  18274. })
  18275. ;
  18276. $nextSide
  18277. .addClass(className.animating)
  18278. .css({
  18279. 'left' : box.origin + 'px',
  18280. 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px) translateX(-' + box.depth.active + 'px)'
  18281. })
  18282. ;
  18283. },
  18284. right: function() {
  18285. var
  18286. height = {
  18287. active : $activeSide.outerWidth(true),
  18288. next : $nextSide.outerWidth(true)
  18289. },
  18290. box = {
  18291. origin : ( ( height.active - height.next ) / 2),
  18292. depth : {
  18293. active : (height.next / 2),
  18294. next : (height.active / 2)
  18295. }
  18296. }
  18297. ;
  18298. module.verbose('Setting the initial animation position as right', $nextSide, box);
  18299. $activeSide
  18300. .css({
  18301. 'transform' : 'rotateY(0deg)'
  18302. })
  18303. ;
  18304. $nextSide
  18305. .addClass(className.animating)
  18306. .css({
  18307. 'left' : box.origin + 'px',
  18308. 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px) translateX(' + box.depth.active + 'px)'
  18309. })
  18310. ;
  18311. },
  18312. behind: function() {
  18313. var
  18314. height = {
  18315. active : $activeSide.outerWidth(true),
  18316. next : $nextSide.outerWidth(true)
  18317. },
  18318. box = {
  18319. origin : ( ( height.active - height.next ) / 2),
  18320. depth : {
  18321. active : (height.next / 2),
  18322. next : (height.active / 2)
  18323. }
  18324. }
  18325. ;
  18326. module.verbose('Setting the initial animation position as behind', $nextSide, box);
  18327. $activeSide
  18328. .css({
  18329. 'transform' : 'rotateY(0deg)'
  18330. })
  18331. ;
  18332. $nextSide
  18333. .addClass(className.animating)
  18334. .css({
  18335. 'left' : box.origin + 'px',
  18336. 'transform' : 'rotateY(-180deg)'
  18337. })
  18338. ;
  18339. }
  18340. },
  18341. setting: function(name, value) {
  18342. module.debug('Changing setting', name, value);
  18343. if( $.isPlainObject(name) ) {
  18344. $.extend(true, settings, name);
  18345. }
  18346. else if(value !== undefined) {
  18347. if($.isPlainObject(settings[name])) {
  18348. $.extend(true, settings[name], value);
  18349. }
  18350. else {
  18351. settings[name] = value;
  18352. }
  18353. }
  18354. else {
  18355. return settings[name];
  18356. }
  18357. },
  18358. internal: function(name, value) {
  18359. if( $.isPlainObject(name) ) {
  18360. $.extend(true, module, name);
  18361. }
  18362. else if(value !== undefined) {
  18363. module[name] = value;
  18364. }
  18365. else {
  18366. return module[name];
  18367. }
  18368. },
  18369. debug: function() {
  18370. if(!settings.silent && settings.debug) {
  18371. if(settings.performance) {
  18372. module.performance.log(arguments);
  18373. }
  18374. else {
  18375. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18376. module.debug.apply(console, arguments);
  18377. }
  18378. }
  18379. },
  18380. verbose: function() {
  18381. if(!settings.silent && settings.verbose && settings.debug) {
  18382. if(settings.performance) {
  18383. module.performance.log(arguments);
  18384. }
  18385. else {
  18386. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18387. module.verbose.apply(console, arguments);
  18388. }
  18389. }
  18390. },
  18391. error: function() {
  18392. if(!settings.silent) {
  18393. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  18394. module.error.apply(console, arguments);
  18395. }
  18396. },
  18397. performance: {
  18398. log: function(message) {
  18399. var
  18400. currentTime,
  18401. executionTime,
  18402. previousTime
  18403. ;
  18404. if(settings.performance) {
  18405. currentTime = new Date().getTime();
  18406. previousTime = time || currentTime;
  18407. executionTime = currentTime - previousTime;
  18408. time = currentTime;
  18409. performance.push({
  18410. 'Name' : message[0],
  18411. 'Arguments' : [].slice.call(message, 1) || '',
  18412. 'Element' : element,
  18413. 'Execution Time' : executionTime
  18414. });
  18415. }
  18416. clearTimeout(module.performance.timer);
  18417. module.performance.timer = setTimeout(module.performance.display, 500);
  18418. },
  18419. display: function() {
  18420. var
  18421. title = settings.name + ':',
  18422. totalTime = 0
  18423. ;
  18424. time = false;
  18425. clearTimeout(module.performance.timer);
  18426. $.each(performance, function(index, data) {
  18427. totalTime += data['Execution Time'];
  18428. });
  18429. title += ' ' + totalTime + 'ms';
  18430. if(moduleSelector) {
  18431. title += ' \'' + moduleSelector + '\'';
  18432. }
  18433. if($allModules.length > 1) {
  18434. title += ' ' + '(' + $allModules.length + ')';
  18435. }
  18436. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  18437. console.groupCollapsed(title);
  18438. if(console.table) {
  18439. console.table(performance);
  18440. }
  18441. else {
  18442. $.each(performance, function(index, data) {
  18443. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  18444. });
  18445. }
  18446. console.groupEnd();
  18447. }
  18448. performance = [];
  18449. }
  18450. },
  18451. invoke: function(query, passedArguments, context) {
  18452. var
  18453. object = instance,
  18454. maxDepth,
  18455. found,
  18456. response
  18457. ;
  18458. passedArguments = passedArguments || queryArguments;
  18459. context = element || context;
  18460. if(typeof query == 'string' && object !== undefined) {
  18461. query = query.split(/[\. ]/);
  18462. maxDepth = query.length - 1;
  18463. $.each(query, function(depth, value) {
  18464. var camelCaseValue = (depth != maxDepth)
  18465. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  18466. : query
  18467. ;
  18468. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  18469. object = object[camelCaseValue];
  18470. }
  18471. else if( object[camelCaseValue] !== undefined ) {
  18472. found = object[camelCaseValue];
  18473. return false;
  18474. }
  18475. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  18476. object = object[value];
  18477. }
  18478. else if( object[value] !== undefined ) {
  18479. found = object[value];
  18480. return false;
  18481. }
  18482. else {
  18483. return false;
  18484. }
  18485. });
  18486. }
  18487. if ( $.isFunction( found ) ) {
  18488. response = found.apply(context, passedArguments);
  18489. }
  18490. else if(found !== undefined) {
  18491. response = found;
  18492. }
  18493. if(Array.isArray(returnedValue)) {
  18494. returnedValue.push(response);
  18495. }
  18496. else if(returnedValue !== undefined) {
  18497. returnedValue = [returnedValue, response];
  18498. }
  18499. else if(response !== undefined) {
  18500. returnedValue = response;
  18501. }
  18502. return found;
  18503. }
  18504. };
  18505. if(methodInvoked) {
  18506. if(instance === undefined) {
  18507. module.initialize();
  18508. }
  18509. var $inputs = $module.find('input');
  18510. if( $inputs.length > 0) {
  18511. $inputs.blur();
  18512. setTimeout(function(){
  18513. module.invoke(query);
  18514. }, 150);
  18515. } else {
  18516. module.invoke(query);
  18517. }
  18518. }
  18519. else {
  18520. if(instance !== undefined) {
  18521. instance.invoke('destroy');
  18522. }
  18523. module.initialize();
  18524. }
  18525. })
  18526. ;
  18527. return (returnedValue !== undefined)
  18528. ? returnedValue
  18529. : this
  18530. ;
  18531. };
  18532. $.fn.shape.settings = {
  18533. // module info
  18534. name : 'Shape',
  18535. // hide all debug content
  18536. silent : false,
  18537. // debug content outputted to console
  18538. debug : false,
  18539. // verbose debug output
  18540. verbose : false,
  18541. // fudge factor in pixels when swapping from 2d to 3d (can be useful to correct rounding errors)
  18542. jitter : 0,
  18543. // performance data output
  18544. performance: true,
  18545. // event namespace
  18546. namespace : 'shape',
  18547. // width during animation, can be set to 'auto', initial', 'next' or pixel amount
  18548. width: 'initial',
  18549. // height during animation, can be set to 'auto', 'initial', 'next' or pixel amount
  18550. height: 'initial',
  18551. // callback occurs on side change
  18552. beforeChange : function() {},
  18553. onChange : function() {},
  18554. // allow animation to same side
  18555. allowRepeats: false,
  18556. // animation duration
  18557. duration : false,
  18558. // possible errors
  18559. error: {
  18560. side : 'You tried to switch to a side that does not exist.',
  18561. method : 'The method you called is not defined'
  18562. },
  18563. // classnames used
  18564. className : {
  18565. animating : 'animating',
  18566. hidden : 'hidden',
  18567. loading : 'loading',
  18568. active : 'active'
  18569. },
  18570. // selectors used
  18571. selector : {
  18572. sides : '.sides',
  18573. side : '.side'
  18574. }
  18575. };
  18576. })( jQuery, window, document );
  18577. /*!
  18578. * # Fomantic-UI - Sidebar
  18579. * http://github.com/fomantic/Fomantic-UI/
  18580. *
  18581. *
  18582. * Released under the MIT license
  18583. * http://opensource.org/licenses/MIT
  18584. *
  18585. */
  18586. ;(function ($, window, document, undefined) {
  18587. 'use strict';
  18588. $.isFunction = $.isFunction || function(obj) {
  18589. return typeof obj === "function" && typeof obj.nodeType !== "number";
  18590. };
  18591. window = (typeof window != 'undefined' && window.Math == Math)
  18592. ? window
  18593. : (typeof self != 'undefined' && self.Math == Math)
  18594. ? self
  18595. : Function('return this')()
  18596. ;
  18597. $.fn.sidebar = function(parameters) {
  18598. var
  18599. $allModules = $(this),
  18600. $window = $(window),
  18601. $document = $(document),
  18602. $html = $('html'),
  18603. $head = $('head'),
  18604. moduleSelector = $allModules.selector || '',
  18605. time = new Date().getTime(),
  18606. performance = [],
  18607. query = arguments[0],
  18608. methodInvoked = (typeof query == 'string'),
  18609. queryArguments = [].slice.call(arguments, 1),
  18610. requestAnimationFrame = window.requestAnimationFrame
  18611. || window.mozRequestAnimationFrame
  18612. || window.webkitRequestAnimationFrame
  18613. || window.msRequestAnimationFrame
  18614. || function(callback) { setTimeout(callback, 0); },
  18615. returnedValue
  18616. ;
  18617. $allModules
  18618. .each(function() {
  18619. var
  18620. settings = ( $.isPlainObject(parameters) )
  18621. ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
  18622. : $.extend({}, $.fn.sidebar.settings),
  18623. selector = settings.selector,
  18624. className = settings.className,
  18625. namespace = settings.namespace,
  18626. regExp = settings.regExp,
  18627. error = settings.error,
  18628. eventNamespace = '.' + namespace,
  18629. moduleNamespace = 'module-' + namespace,
  18630. $module = $(this),
  18631. $context = $(settings.context),
  18632. $sidebars = $module.children(selector.sidebar),
  18633. $fixed = $context.children(selector.fixed),
  18634. $pusher = $context.children(selector.pusher),
  18635. $style,
  18636. element = this,
  18637. instance = $module.data(moduleNamespace),
  18638. elementNamespace,
  18639. id,
  18640. currentScroll,
  18641. transitionEvent,
  18642. module
  18643. ;
  18644. module = {
  18645. initialize: function() {
  18646. module.debug('Initializing sidebar', parameters);
  18647. module.create.id();
  18648. transitionEvent = module.get.transitionEvent();
  18649. // avoids locking rendering if initialized in onReady
  18650. if(settings.delaySetup) {
  18651. requestAnimationFrame(module.setup.layout);
  18652. }
  18653. else {
  18654. module.setup.layout();
  18655. }
  18656. requestAnimationFrame(function() {
  18657. module.setup.cache();
  18658. });
  18659. module.instantiate();
  18660. },
  18661. instantiate: function() {
  18662. module.verbose('Storing instance of module', module);
  18663. instance = module;
  18664. $module
  18665. .data(moduleNamespace, module)
  18666. ;
  18667. },
  18668. create: {
  18669. id: function() {
  18670. id = (Math.random().toString(16) + '000000000').substr(2,8);
  18671. elementNamespace = '.' + id;
  18672. module.verbose('Creating unique id for element', id);
  18673. }
  18674. },
  18675. destroy: function() {
  18676. module.verbose('Destroying previous module for', $module);
  18677. $module
  18678. .off(eventNamespace)
  18679. .removeData(moduleNamespace)
  18680. ;
  18681. if(module.is.ios()) {
  18682. module.remove.ios();
  18683. }
  18684. // bound by uuid
  18685. $context.off(elementNamespace);
  18686. $window.off(elementNamespace);
  18687. $document.off(elementNamespace);
  18688. },
  18689. event: {
  18690. clickaway: function(event) {
  18691. if(settings.closable){
  18692. var
  18693. clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
  18694. clickedContext = ($context.is(event.target))
  18695. ;
  18696. if(clickedInPusher) {
  18697. module.verbose('User clicked on dimmed page');
  18698. module.hide();
  18699. }
  18700. if(clickedContext) {
  18701. module.verbose('User clicked on dimmable context (scaled out page)');
  18702. module.hide();
  18703. }
  18704. }
  18705. },
  18706. touch: function(event) {
  18707. //event.stopPropagation();
  18708. },
  18709. containScroll: function(event) {
  18710. if(element.scrollTop <= 0) {
  18711. element.scrollTop = 1;
  18712. }
  18713. if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
  18714. element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
  18715. }
  18716. },
  18717. scroll: function(event) {
  18718. if( $(event.target).closest(selector.sidebar).length === 0 ) {
  18719. event.preventDefault();
  18720. }
  18721. }
  18722. },
  18723. bind: {
  18724. clickaway: function() {
  18725. module.verbose('Adding clickaway events to context', $context);
  18726. $context
  18727. .on('click' + elementNamespace, module.event.clickaway)
  18728. .on('touchend' + elementNamespace, module.event.clickaway)
  18729. ;
  18730. },
  18731. scrollLock: function() {
  18732. if(settings.scrollLock) {
  18733. module.debug('Disabling page scroll');
  18734. $window
  18735. .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
  18736. ;
  18737. }
  18738. module.verbose('Adding events to contain sidebar scroll');
  18739. $document
  18740. .on('touchmove' + elementNamespace, module.event.touch)
  18741. ;
  18742. $module
  18743. .on('scroll' + eventNamespace, module.event.containScroll)
  18744. ;
  18745. }
  18746. },
  18747. unbind: {
  18748. clickaway: function() {
  18749. module.verbose('Removing clickaway events from context', $context);
  18750. $context.off(elementNamespace);
  18751. },
  18752. scrollLock: function() {
  18753. module.verbose('Removing scroll lock from page');
  18754. $document.off(elementNamespace);
  18755. $window.off(elementNamespace);
  18756. $module.off('scroll' + eventNamespace);
  18757. }
  18758. },
  18759. add: {
  18760. inlineCSS: function() {
  18761. var
  18762. width = module.cache.width || $module.outerWidth(),
  18763. height = module.cache.height || $module.outerHeight(),
  18764. isRTL = module.is.rtl(),
  18765. direction = module.get.direction(),
  18766. distance = {
  18767. left : width,
  18768. right : -width,
  18769. top : height,
  18770. bottom : -height
  18771. },
  18772. style
  18773. ;
  18774. if(isRTL){
  18775. module.verbose('RTL detected, flipping widths');
  18776. distance.left = -width;
  18777. distance.right = width;
  18778. }
  18779. style = '<style>';
  18780. if(direction === 'left' || direction === 'right') {
  18781. module.debug('Adding CSS rules for animation distance', width);
  18782. style += ''
  18783. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  18784. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  18785. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  18786. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  18787. + ' }'
  18788. ;
  18789. }
  18790. else if(direction === 'top' || direction == 'bottom') {
  18791. style += ''
  18792. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  18793. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  18794. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  18795. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  18796. + ' }'
  18797. ;
  18798. }
  18799. /* IE is only browser not to create context with transforms */
  18800. /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
  18801. if( module.is.ie() ) {
  18802. if(direction === 'left' || direction === 'right') {
  18803. module.debug('Adding CSS rules for animation distance', width);
  18804. style += ''
  18805. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  18806. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  18807. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  18808. + ' }'
  18809. ;
  18810. }
  18811. else if(direction === 'top' || direction == 'bottom') {
  18812. style += ''
  18813. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  18814. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  18815. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  18816. + ' }'
  18817. ;
  18818. }
  18819. /* opposite sides visible forces content overlay */
  18820. style += ''
  18821. + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
  18822. + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
  18823. + ' -webkit-transform: translate3d(0, 0, 0);'
  18824. + ' transform: translate3d(0, 0, 0);'
  18825. + ' }'
  18826. ;
  18827. }
  18828. style += '</style>';
  18829. $style = $(style)
  18830. .appendTo($head)
  18831. ;
  18832. module.debug('Adding sizing css to head', $style);
  18833. }
  18834. },
  18835. refresh: function() {
  18836. module.verbose('Refreshing selector cache');
  18837. $context = $(settings.context);
  18838. $sidebars = $context.children(selector.sidebar);
  18839. $pusher = $context.children(selector.pusher);
  18840. $fixed = $context.children(selector.fixed);
  18841. module.clear.cache();
  18842. },
  18843. refreshSidebars: function() {
  18844. module.verbose('Refreshing other sidebars');
  18845. $sidebars = $context.children(selector.sidebar);
  18846. },
  18847. repaint: function() {
  18848. module.verbose('Forcing repaint event');
  18849. element.style.display = 'none';
  18850. var ignored = element.offsetHeight;
  18851. element.scrollTop = element.scrollTop;
  18852. element.style.display = '';
  18853. },
  18854. setup: {
  18855. cache: function() {
  18856. module.cache = {
  18857. width : $module.outerWidth(),
  18858. height : $module.outerHeight()
  18859. };
  18860. },
  18861. layout: function() {
  18862. if( $context.children(selector.pusher).length === 0 ) {
  18863. module.debug('Adding wrapper element for sidebar');
  18864. module.error(error.pusher);
  18865. $pusher = $('<div class="pusher" />');
  18866. $context
  18867. .children()
  18868. .not(selector.omitted)
  18869. .not($sidebars)
  18870. .wrapAll($pusher)
  18871. ;
  18872. module.refresh();
  18873. }
  18874. if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
  18875. module.debug('Moved sidebar to correct parent element');
  18876. module.error(error.movedSidebar, element);
  18877. $module.detach().prependTo($context);
  18878. module.refresh();
  18879. }
  18880. module.clear.cache();
  18881. module.set.pushable();
  18882. module.set.direction();
  18883. }
  18884. },
  18885. attachEvents: function(selector, event) {
  18886. var
  18887. $toggle = $(selector)
  18888. ;
  18889. event = $.isFunction(module[event])
  18890. ? module[event]
  18891. : module.toggle
  18892. ;
  18893. if($toggle.length > 0) {
  18894. module.debug('Attaching sidebar events to element', selector, event);
  18895. $toggle
  18896. .on('click' + eventNamespace, event)
  18897. ;
  18898. }
  18899. else {
  18900. module.error(error.notFound, selector);
  18901. }
  18902. },
  18903. show: function(callback) {
  18904. callback = $.isFunction(callback)
  18905. ? callback
  18906. : function(){}
  18907. ;
  18908. if(module.is.hidden()) {
  18909. module.refreshSidebars();
  18910. if(settings.overlay) {
  18911. module.error(error.overlay);
  18912. settings.transition = 'overlay';
  18913. }
  18914. module.refresh();
  18915. if(module.othersActive()) {
  18916. module.debug('Other sidebars currently visible');
  18917. if(settings.exclusive) {
  18918. // if not overlay queue animation after hide
  18919. if(settings.transition != 'overlay') {
  18920. module.hideOthers(module.show);
  18921. return;
  18922. }
  18923. else {
  18924. module.hideOthers();
  18925. }
  18926. }
  18927. else {
  18928. settings.transition = 'overlay';
  18929. }
  18930. }
  18931. module.pushPage(function() {
  18932. callback.call(element);
  18933. settings.onShow.call(element);
  18934. });
  18935. settings.onChange.call(element);
  18936. settings.onVisible.call(element);
  18937. }
  18938. else {
  18939. module.debug('Sidebar is already visible');
  18940. }
  18941. },
  18942. hide: function(callback) {
  18943. callback = $.isFunction(callback)
  18944. ? callback
  18945. : function(){}
  18946. ;
  18947. if(module.is.visible() || module.is.animating()) {
  18948. module.debug('Hiding sidebar', callback);
  18949. module.refreshSidebars();
  18950. module.pullPage(function() {
  18951. callback.call(element);
  18952. settings.onHidden.call(element);
  18953. });
  18954. settings.onChange.call(element);
  18955. settings.onHide.call(element);
  18956. }
  18957. },
  18958. othersAnimating: function() {
  18959. return ($sidebars.not($module).filter('.' + className.animating).length > 0);
  18960. },
  18961. othersVisible: function() {
  18962. return ($sidebars.not($module).filter('.' + className.visible).length > 0);
  18963. },
  18964. othersActive: function() {
  18965. return(module.othersVisible() || module.othersAnimating());
  18966. },
  18967. hideOthers: function(callback) {
  18968. var
  18969. $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
  18970. sidebarCount = $otherSidebars.length,
  18971. callbackCount = 0
  18972. ;
  18973. callback = callback || function(){};
  18974. $otherSidebars
  18975. .sidebar('hide', function() {
  18976. callbackCount++;
  18977. if(callbackCount == sidebarCount) {
  18978. callback();
  18979. }
  18980. })
  18981. ;
  18982. },
  18983. toggle: function() {
  18984. module.verbose('Determining toggled direction');
  18985. if(module.is.hidden()) {
  18986. module.show();
  18987. }
  18988. else {
  18989. module.hide();
  18990. }
  18991. },
  18992. pushPage: function(callback) {
  18993. var
  18994. transition = module.get.transition(),
  18995. $transition = (transition === 'overlay' || module.othersActive())
  18996. ? $module
  18997. : $pusher,
  18998. animate,
  18999. dim,
  19000. transitionEnd
  19001. ;
  19002. callback = $.isFunction(callback)
  19003. ? callback
  19004. : function(){}
  19005. ;
  19006. if(settings.transition == 'scale down') {
  19007. module.scrollToTop();
  19008. }
  19009. module.set.transition(transition);
  19010. module.repaint();
  19011. animate = function() {
  19012. module.bind.clickaway();
  19013. module.add.inlineCSS();
  19014. module.set.animating();
  19015. module.set.visible();
  19016. };
  19017. dim = function() {
  19018. module.set.dimmed();
  19019. };
  19020. transitionEnd = function(event) {
  19021. if( event.target == $transition[0] ) {
  19022. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  19023. module.remove.animating();
  19024. module.bind.scrollLock();
  19025. callback.call(element);
  19026. }
  19027. };
  19028. $transition.off(transitionEvent + elementNamespace);
  19029. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  19030. requestAnimationFrame(animate);
  19031. if(settings.dimPage && !module.othersVisible()) {
  19032. requestAnimationFrame(dim);
  19033. }
  19034. },
  19035. pullPage: function(callback) {
  19036. var
  19037. transition = module.get.transition(),
  19038. $transition = (transition == 'overlay' || module.othersActive())
  19039. ? $module
  19040. : $pusher,
  19041. animate,
  19042. transitionEnd
  19043. ;
  19044. callback = $.isFunction(callback)
  19045. ? callback
  19046. : function(){}
  19047. ;
  19048. module.verbose('Removing context push state', module.get.direction());
  19049. module.unbind.clickaway();
  19050. module.unbind.scrollLock();
  19051. animate = function() {
  19052. module.set.transition(transition);
  19053. module.set.animating();
  19054. module.remove.visible();
  19055. if(settings.dimPage && !module.othersVisible()) {
  19056. $pusher.removeClass(className.dimmed);
  19057. }
  19058. };
  19059. transitionEnd = function(event) {
  19060. if( event.target == $transition[0] ) {
  19061. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  19062. module.remove.animating();
  19063. module.remove.transition();
  19064. module.remove.inlineCSS();
  19065. if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
  19066. module.scrollBack();
  19067. }
  19068. callback.call(element);
  19069. }
  19070. };
  19071. $transition.off(transitionEvent + elementNamespace);
  19072. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  19073. requestAnimationFrame(animate);
  19074. },
  19075. scrollToTop: function() {
  19076. module.verbose('Scrolling to top of page to avoid animation issues');
  19077. currentScroll = $(window).scrollTop();
  19078. $module.scrollTop(0);
  19079. window.scrollTo(0, 0);
  19080. },
  19081. scrollBack: function() {
  19082. module.verbose('Scrolling back to original page position');
  19083. window.scrollTo(0, currentScroll);
  19084. },
  19085. clear: {
  19086. cache: function() {
  19087. module.verbose('Clearing cached dimensions');
  19088. module.cache = {};
  19089. }
  19090. },
  19091. set: {
  19092. // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
  19093. // (This is no longer necessary in latest iOS)
  19094. ios: function() {
  19095. $html.addClass(className.ios);
  19096. },
  19097. // container
  19098. pushed: function() {
  19099. $context.addClass(className.pushed);
  19100. },
  19101. pushable: function() {
  19102. $context.addClass(className.pushable);
  19103. },
  19104. // pusher
  19105. dimmed: function() {
  19106. $pusher.addClass(className.dimmed);
  19107. },
  19108. // sidebar
  19109. active: function() {
  19110. $module.addClass(className.active);
  19111. },
  19112. animating: function() {
  19113. $module.addClass(className.animating);
  19114. },
  19115. transition: function(transition) {
  19116. transition = transition || module.get.transition();
  19117. $module.addClass(transition);
  19118. },
  19119. direction: function(direction) {
  19120. direction = direction || module.get.direction();
  19121. $module.addClass(className[direction]);
  19122. },
  19123. visible: function() {
  19124. $module.addClass(className.visible);
  19125. },
  19126. overlay: function() {
  19127. $module.addClass(className.overlay);
  19128. }
  19129. },
  19130. remove: {
  19131. inlineCSS: function() {
  19132. module.debug('Removing inline css styles', $style);
  19133. if($style && $style.length > 0) {
  19134. $style.remove();
  19135. }
  19136. },
  19137. // ios scroll on html not document
  19138. ios: function() {
  19139. $html.removeClass(className.ios);
  19140. },
  19141. // context
  19142. pushed: function() {
  19143. $context.removeClass(className.pushed);
  19144. },
  19145. pushable: function() {
  19146. $context.removeClass(className.pushable);
  19147. },
  19148. // sidebar
  19149. active: function() {
  19150. $module.removeClass(className.active);
  19151. },
  19152. animating: function() {
  19153. $module.removeClass(className.animating);
  19154. },
  19155. transition: function(transition) {
  19156. transition = transition || module.get.transition();
  19157. $module.removeClass(transition);
  19158. },
  19159. direction: function(direction) {
  19160. direction = direction || module.get.direction();
  19161. $module.removeClass(className[direction]);
  19162. },
  19163. visible: function() {
  19164. $module.removeClass(className.visible);
  19165. },
  19166. overlay: function() {
  19167. $module.removeClass(className.overlay);
  19168. }
  19169. },
  19170. get: {
  19171. direction: function() {
  19172. if($module.hasClass(className.top)) {
  19173. return className.top;
  19174. }
  19175. else if($module.hasClass(className.right)) {
  19176. return className.right;
  19177. }
  19178. else if($module.hasClass(className.bottom)) {
  19179. return className.bottom;
  19180. }
  19181. return className.left;
  19182. },
  19183. transition: function() {
  19184. var
  19185. direction = module.get.direction(),
  19186. transition
  19187. ;
  19188. transition = ( module.is.mobile() )
  19189. ? (settings.mobileTransition == 'auto')
  19190. ? settings.defaultTransition.mobile[direction]
  19191. : settings.mobileTransition
  19192. : (settings.transition == 'auto')
  19193. ? settings.defaultTransition.computer[direction]
  19194. : settings.transition
  19195. ;
  19196. module.verbose('Determined transition', transition);
  19197. return transition;
  19198. },
  19199. transitionEvent: function() {
  19200. var
  19201. element = document.createElement('element'),
  19202. transitions = {
  19203. 'transition' :'transitionend',
  19204. 'OTransition' :'oTransitionEnd',
  19205. 'MozTransition' :'transitionend',
  19206. 'WebkitTransition' :'webkitTransitionEnd'
  19207. },
  19208. transition
  19209. ;
  19210. for(transition in transitions){
  19211. if( element.style[transition] !== undefined ){
  19212. return transitions[transition];
  19213. }
  19214. }
  19215. }
  19216. },
  19217. is: {
  19218. ie: function() {
  19219. var
  19220. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  19221. isIE = ('ActiveXObject' in window)
  19222. ;
  19223. return (isIE11 || isIE);
  19224. },
  19225. ios: function() {
  19226. var
  19227. userAgent = navigator.userAgent,
  19228. isIOS = userAgent.match(regExp.ios),
  19229. isMobileChrome = userAgent.match(regExp.mobileChrome)
  19230. ;
  19231. if(isIOS && !isMobileChrome) {
  19232. module.verbose('Browser was found to be iOS', userAgent);
  19233. return true;
  19234. }
  19235. else {
  19236. return false;
  19237. }
  19238. },
  19239. mobile: function() {
  19240. var
  19241. userAgent = navigator.userAgent,
  19242. isMobile = userAgent.match(regExp.mobile)
  19243. ;
  19244. if(isMobile) {
  19245. module.verbose('Browser was found to be mobile', userAgent);
  19246. return true;
  19247. }
  19248. else {
  19249. module.verbose('Browser is not mobile, using regular transition', userAgent);
  19250. return false;
  19251. }
  19252. },
  19253. hidden: function() {
  19254. return !module.is.visible();
  19255. },
  19256. visible: function() {
  19257. return $module.hasClass(className.visible);
  19258. },
  19259. // alias
  19260. open: function() {
  19261. return module.is.visible();
  19262. },
  19263. closed: function() {
  19264. return module.is.hidden();
  19265. },
  19266. vertical: function() {
  19267. return $module.hasClass(className.top);
  19268. },
  19269. animating: function() {
  19270. return $context.hasClass(className.animating);
  19271. },
  19272. rtl: function () {
  19273. if(module.cache.rtl === undefined) {
  19274. module.cache.rtl = $module.attr('dir') === 'rtl' || $module.css('direction') === 'rtl';
  19275. }
  19276. return module.cache.rtl;
  19277. }
  19278. },
  19279. setting: function(name, value) {
  19280. module.debug('Changing setting', name, value);
  19281. if( $.isPlainObject(name) ) {
  19282. $.extend(true, settings, name);
  19283. }
  19284. else if(value !== undefined) {
  19285. if($.isPlainObject(settings[name])) {
  19286. $.extend(true, settings[name], value);
  19287. }
  19288. else {
  19289. settings[name] = value;
  19290. }
  19291. }
  19292. else {
  19293. return settings[name];
  19294. }
  19295. },
  19296. internal: function(name, value) {
  19297. if( $.isPlainObject(name) ) {
  19298. $.extend(true, module, name);
  19299. }
  19300. else if(value !== undefined) {
  19301. module[name] = value;
  19302. }
  19303. else {
  19304. return module[name];
  19305. }
  19306. },
  19307. debug: function() {
  19308. if(!settings.silent && settings.debug) {
  19309. if(settings.performance) {
  19310. module.performance.log(arguments);
  19311. }
  19312. else {
  19313. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19314. module.debug.apply(console, arguments);
  19315. }
  19316. }
  19317. },
  19318. verbose: function() {
  19319. if(!settings.silent && settings.verbose && settings.debug) {
  19320. if(settings.performance) {
  19321. module.performance.log(arguments);
  19322. }
  19323. else {
  19324. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19325. module.verbose.apply(console, arguments);
  19326. }
  19327. }
  19328. },
  19329. error: function() {
  19330. if(!settings.silent) {
  19331. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  19332. module.error.apply(console, arguments);
  19333. }
  19334. },
  19335. performance: {
  19336. log: function(message) {
  19337. var
  19338. currentTime,
  19339. executionTime,
  19340. previousTime
  19341. ;
  19342. if(settings.performance) {
  19343. currentTime = new Date().getTime();
  19344. previousTime = time || currentTime;
  19345. executionTime = currentTime - previousTime;
  19346. time = currentTime;
  19347. performance.push({
  19348. 'Name' : message[0],
  19349. 'Arguments' : [].slice.call(message, 1) || '',
  19350. 'Element' : element,
  19351. 'Execution Time' : executionTime
  19352. });
  19353. }
  19354. clearTimeout(module.performance.timer);
  19355. module.performance.timer = setTimeout(module.performance.display, 500);
  19356. },
  19357. display: function() {
  19358. var
  19359. title = settings.name + ':',
  19360. totalTime = 0
  19361. ;
  19362. time = false;
  19363. clearTimeout(module.performance.timer);
  19364. $.each(performance, function(index, data) {
  19365. totalTime += data['Execution Time'];
  19366. });
  19367. title += ' ' + totalTime + 'ms';
  19368. if(moduleSelector) {
  19369. title += ' \'' + moduleSelector + '\'';
  19370. }
  19371. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  19372. console.groupCollapsed(title);
  19373. if(console.table) {
  19374. console.table(performance);
  19375. }
  19376. else {
  19377. $.each(performance, function(index, data) {
  19378. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  19379. });
  19380. }
  19381. console.groupEnd();
  19382. }
  19383. performance = [];
  19384. }
  19385. },
  19386. invoke: function(query, passedArguments, context) {
  19387. var
  19388. object = instance,
  19389. maxDepth,
  19390. found,
  19391. response
  19392. ;
  19393. passedArguments = passedArguments || queryArguments;
  19394. context = element || context;
  19395. if(typeof query == 'string' && object !== undefined) {
  19396. query = query.split(/[\. ]/);
  19397. maxDepth = query.length - 1;
  19398. $.each(query, function(depth, value) {
  19399. var camelCaseValue = (depth != maxDepth)
  19400. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  19401. : query
  19402. ;
  19403. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  19404. object = object[camelCaseValue];
  19405. }
  19406. else if( object[camelCaseValue] !== undefined ) {
  19407. found = object[camelCaseValue];
  19408. return false;
  19409. }
  19410. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  19411. object = object[value];
  19412. }
  19413. else if( object[value] !== undefined ) {
  19414. found = object[value];
  19415. return false;
  19416. }
  19417. else {
  19418. module.error(error.method, query);
  19419. return false;
  19420. }
  19421. });
  19422. }
  19423. if ( $.isFunction( found ) ) {
  19424. response = found.apply(context, passedArguments);
  19425. }
  19426. else if(found !== undefined) {
  19427. response = found;
  19428. }
  19429. if(Array.isArray(returnedValue)) {
  19430. returnedValue.push(response);
  19431. }
  19432. else if(returnedValue !== undefined) {
  19433. returnedValue = [returnedValue, response];
  19434. }
  19435. else if(response !== undefined) {
  19436. returnedValue = response;
  19437. }
  19438. return found;
  19439. }
  19440. }
  19441. ;
  19442. if(methodInvoked) {
  19443. if(instance === undefined) {
  19444. module.initialize();
  19445. }
  19446. module.invoke(query);
  19447. }
  19448. else {
  19449. if(instance !== undefined) {
  19450. module.invoke('destroy');
  19451. }
  19452. module.initialize();
  19453. }
  19454. });
  19455. return (returnedValue !== undefined)
  19456. ? returnedValue
  19457. : this
  19458. ;
  19459. };
  19460. $.fn.sidebar.settings = {
  19461. name : 'Sidebar',
  19462. namespace : 'sidebar',
  19463. silent : false,
  19464. debug : false,
  19465. verbose : false,
  19466. performance : true,
  19467. transition : 'auto',
  19468. mobileTransition : 'auto',
  19469. defaultTransition : {
  19470. computer: {
  19471. left : 'uncover',
  19472. right : 'uncover',
  19473. top : 'overlay',
  19474. bottom : 'overlay'
  19475. },
  19476. mobile: {
  19477. left : 'uncover',
  19478. right : 'uncover',
  19479. top : 'overlay',
  19480. bottom : 'overlay'
  19481. }
  19482. },
  19483. context : 'body',
  19484. exclusive : false,
  19485. closable : true,
  19486. dimPage : true,
  19487. scrollLock : false,
  19488. returnScroll : false,
  19489. delaySetup : false,
  19490. duration : 500,
  19491. onChange : function(){},
  19492. onShow : function(){},
  19493. onHide : function(){},
  19494. onHidden : function(){},
  19495. onVisible : function(){},
  19496. className : {
  19497. active : 'active',
  19498. animating : 'animating',
  19499. dimmed : 'dimmed',
  19500. ios : 'ios',
  19501. pushable : 'pushable',
  19502. pushed : 'pushed',
  19503. right : 'right',
  19504. top : 'top',
  19505. left : 'left',
  19506. bottom : 'bottom',
  19507. visible : 'visible'
  19508. },
  19509. selector: {
  19510. fixed : '.fixed',
  19511. omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
  19512. pusher : '.pusher',
  19513. sidebar : '.ui.sidebar'
  19514. },
  19515. regExp: {
  19516. ios : /(iPad|iPhone|iPod)/g,
  19517. mobileChrome : /(CriOS)/g,
  19518. mobile : /Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/g
  19519. },
  19520. error : {
  19521. method : 'The method you called is not defined.',
  19522. pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
  19523. movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
  19524. overlay : 'The overlay setting is no longer supported, use animation: overlay',
  19525. notFound : 'There were no elements that matched the specified selector'
  19526. }
  19527. };
  19528. })( jQuery, window, document );
  19529. /*!
  19530. * # Fomantic-UI - Sticky
  19531. * http://github.com/fomantic/Fomantic-UI/
  19532. *
  19533. *
  19534. * Released under the MIT license
  19535. * http://opensource.org/licenses/MIT
  19536. *
  19537. */
  19538. ;(function ($, window, document, undefined) {
  19539. 'use strict';
  19540. $.isFunction = $.isFunction || function(obj) {
  19541. return typeof obj === "function" && typeof obj.nodeType !== "number";
  19542. };
  19543. window = (typeof window != 'undefined' && window.Math == Math)
  19544. ? window
  19545. : (typeof self != 'undefined' && self.Math == Math)
  19546. ? self
  19547. : Function('return this')()
  19548. ;
  19549. $.fn.sticky = function(parameters) {
  19550. var
  19551. $allModules = $(this),
  19552. moduleSelector = $allModules.selector || '',
  19553. time = new Date().getTime(),
  19554. performance = [],
  19555. query = arguments[0],
  19556. methodInvoked = (typeof query == 'string'),
  19557. queryArguments = [].slice.call(arguments, 1),
  19558. returnedValue
  19559. ;
  19560. $allModules
  19561. .each(function() {
  19562. var
  19563. settings = ( $.isPlainObject(parameters) )
  19564. ? $.extend(true, {}, $.fn.sticky.settings, parameters)
  19565. : $.extend({}, $.fn.sticky.settings),
  19566. className = settings.className,
  19567. namespace = settings.namespace,
  19568. error = settings.error,
  19569. eventNamespace = '.' + namespace,
  19570. moduleNamespace = 'module-' + namespace,
  19571. $module = $(this),
  19572. $window = $(window),
  19573. $scroll = $(settings.scrollContext),
  19574. $container,
  19575. $context,
  19576. instance = $module.data(moduleNamespace),
  19577. requestAnimationFrame = window.requestAnimationFrame
  19578. || window.mozRequestAnimationFrame
  19579. || window.webkitRequestAnimationFrame
  19580. || window.msRequestAnimationFrame
  19581. || function(callback) { setTimeout(callback, 0); },
  19582. element = this,
  19583. documentObserver,
  19584. observer,
  19585. module
  19586. ;
  19587. module = {
  19588. initialize: function() {
  19589. module.determineContainer();
  19590. module.determineContext();
  19591. module.verbose('Initializing sticky', settings, $container);
  19592. module.save.positions();
  19593. module.checkErrors();
  19594. module.bind.events();
  19595. if(settings.observeChanges) {
  19596. module.observeChanges();
  19597. }
  19598. module.instantiate();
  19599. },
  19600. instantiate: function() {
  19601. module.verbose('Storing instance of module', module);
  19602. instance = module;
  19603. $module
  19604. .data(moduleNamespace, module)
  19605. ;
  19606. },
  19607. destroy: function() {
  19608. module.verbose('Destroying previous instance');
  19609. module.reset();
  19610. if(documentObserver) {
  19611. documentObserver.disconnect();
  19612. }
  19613. if(observer) {
  19614. observer.disconnect();
  19615. }
  19616. $window
  19617. .off('load' + eventNamespace, module.event.load)
  19618. .off('resize' + eventNamespace, module.event.resize)
  19619. ;
  19620. $scroll
  19621. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  19622. ;
  19623. $module.removeData(moduleNamespace);
  19624. },
  19625. observeChanges: function() {
  19626. if('MutationObserver' in window) {
  19627. documentObserver = new MutationObserver(module.event.documentChanged);
  19628. observer = new MutationObserver(module.event.changed);
  19629. documentObserver.observe(document, {
  19630. childList : true,
  19631. subtree : true
  19632. });
  19633. observer.observe(element, {
  19634. childList : true,
  19635. subtree : true
  19636. });
  19637. observer.observe($context[0], {
  19638. childList : true,
  19639. subtree : true
  19640. });
  19641. module.debug('Setting up mutation observer', observer);
  19642. }
  19643. },
  19644. determineContainer: function() {
  19645. if(settings.container) {
  19646. $container = $(settings.container);
  19647. }
  19648. else {
  19649. $container = $module.offsetParent();
  19650. }
  19651. },
  19652. determineContext: function() {
  19653. if(settings.context) {
  19654. $context = $(settings.context);
  19655. }
  19656. else {
  19657. $context = $container;
  19658. }
  19659. if($context.length === 0) {
  19660. module.error(error.invalidContext, settings.context, $module);
  19661. return;
  19662. }
  19663. },
  19664. checkErrors: function() {
  19665. if( module.is.hidden() ) {
  19666. module.error(error.visible, $module);
  19667. }
  19668. if(module.cache.element.height > module.cache.context.height) {
  19669. module.reset();
  19670. module.error(error.elementSize, $module);
  19671. return;
  19672. }
  19673. },
  19674. bind: {
  19675. events: function() {
  19676. $window
  19677. .on('load' + eventNamespace, module.event.load)
  19678. .on('resize' + eventNamespace, module.event.resize)
  19679. ;
  19680. // pub/sub pattern
  19681. $scroll
  19682. .off('scroll' + eventNamespace)
  19683. .on('scroll' + eventNamespace, module.event.scroll)
  19684. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  19685. ;
  19686. }
  19687. },
  19688. event: {
  19689. changed: function(mutations) {
  19690. clearTimeout(module.timer);
  19691. module.timer = setTimeout(function() {
  19692. module.verbose('DOM tree modified, updating sticky menu', mutations);
  19693. module.refresh();
  19694. }, 100);
  19695. },
  19696. documentChanged: function(mutations) {
  19697. [].forEach.call(mutations, function(mutation) {
  19698. if(mutation.removedNodes) {
  19699. [].forEach.call(mutation.removedNodes, function(node) {
  19700. if(node == element || $(node).find(element).length > 0) {
  19701. module.debug('Element removed from DOM, tearing down events');
  19702. module.destroy();
  19703. }
  19704. });
  19705. }
  19706. });
  19707. },
  19708. load: function() {
  19709. module.verbose('Page contents finished loading');
  19710. requestAnimationFrame(module.refresh);
  19711. },
  19712. resize: function() {
  19713. module.verbose('Window resized');
  19714. requestAnimationFrame(module.refresh);
  19715. },
  19716. scroll: function() {
  19717. requestAnimationFrame(function() {
  19718. $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
  19719. });
  19720. },
  19721. scrollchange: function(event, scrollPosition) {
  19722. module.stick(scrollPosition);
  19723. settings.onScroll.call(element);
  19724. }
  19725. },
  19726. refresh: function(hardRefresh) {
  19727. module.reset();
  19728. if(!settings.context) {
  19729. module.determineContext();
  19730. }
  19731. if(hardRefresh) {
  19732. module.determineContainer();
  19733. }
  19734. module.save.positions();
  19735. module.stick();
  19736. settings.onReposition.call(element);
  19737. },
  19738. supports: {
  19739. sticky: function() {
  19740. var
  19741. $element = $('<div/>')
  19742. ;
  19743. $element.addClass(className.supported);
  19744. return($element.css('position').match('sticky'));
  19745. }
  19746. },
  19747. save: {
  19748. lastScroll: function(scroll) {
  19749. module.lastScroll = scroll;
  19750. },
  19751. elementScroll: function(scroll) {
  19752. module.elementScroll = scroll;
  19753. },
  19754. positions: function() {
  19755. var
  19756. scrollContext = {
  19757. height : $scroll.height()
  19758. },
  19759. element = {
  19760. margin: {
  19761. top : parseInt($module.css('margin-top'), 10),
  19762. bottom : parseInt($module.css('margin-bottom'), 10),
  19763. },
  19764. offset : $module.offset(),
  19765. width : $module.outerWidth(),
  19766. height : $module.outerHeight()
  19767. },
  19768. context = {
  19769. offset : $context.offset(),
  19770. height : $context.outerHeight()
  19771. }
  19772. ;
  19773. if( !module.is.standardScroll() ) {
  19774. module.debug('Non-standard scroll. Removing scroll offset from element offset');
  19775. scrollContext.top = $scroll.scrollTop();
  19776. scrollContext.left = $scroll.scrollLeft();
  19777. element.offset.top += scrollContext.top;
  19778. context.offset.top += scrollContext.top;
  19779. element.offset.left += scrollContext.left;
  19780. context.offset.left += scrollContext.left;
  19781. }
  19782. module.cache = {
  19783. fits : ( (element.height + settings.offset) <= scrollContext.height),
  19784. sameHeight : (element.height == context.height),
  19785. scrollContext : {
  19786. height : scrollContext.height
  19787. },
  19788. element: {
  19789. margin : element.margin,
  19790. top : element.offset.top - element.margin.top,
  19791. left : element.offset.left,
  19792. width : element.width,
  19793. height : element.height,
  19794. bottom : element.offset.top + element.height
  19795. },
  19796. context: {
  19797. top : context.offset.top,
  19798. height : context.height,
  19799. bottom : context.offset.top + context.height
  19800. }
  19801. };
  19802. module.set.containerSize();
  19803. module.stick();
  19804. module.debug('Caching element positions', module.cache);
  19805. }
  19806. },
  19807. get: {
  19808. direction: function(scroll) {
  19809. var
  19810. direction = 'down'
  19811. ;
  19812. scroll = scroll || $scroll.scrollTop();
  19813. if(module.lastScroll !== undefined) {
  19814. if(module.lastScroll < scroll) {
  19815. direction = 'down';
  19816. }
  19817. else if(module.lastScroll > scroll) {
  19818. direction = 'up';
  19819. }
  19820. }
  19821. return direction;
  19822. },
  19823. scrollChange: function(scroll) {
  19824. scroll = scroll || $scroll.scrollTop();
  19825. return (module.lastScroll)
  19826. ? (scroll - module.lastScroll)
  19827. : 0
  19828. ;
  19829. },
  19830. currentElementScroll: function() {
  19831. if(module.elementScroll) {
  19832. return module.elementScroll;
  19833. }
  19834. return ( module.is.top() )
  19835. ? Math.abs(parseInt($module.css('top'), 10)) || 0
  19836. : Math.abs(parseInt($module.css('bottom'), 10)) || 0
  19837. ;
  19838. },
  19839. elementScroll: function(scroll) {
  19840. scroll = scroll || $scroll.scrollTop();
  19841. var
  19842. element = module.cache.element,
  19843. scrollContext = module.cache.scrollContext,
  19844. delta = module.get.scrollChange(scroll),
  19845. maxScroll = (element.height - scrollContext.height + settings.offset),
  19846. elementScroll = module.get.currentElementScroll(),
  19847. possibleScroll = (elementScroll + delta)
  19848. ;
  19849. if(module.cache.fits || possibleScroll < 0) {
  19850. elementScroll = 0;
  19851. }
  19852. else if(possibleScroll > maxScroll ) {
  19853. elementScroll = maxScroll;
  19854. }
  19855. else {
  19856. elementScroll = possibleScroll;
  19857. }
  19858. return elementScroll;
  19859. }
  19860. },
  19861. remove: {
  19862. lastScroll: function() {
  19863. delete module.lastScroll;
  19864. },
  19865. elementScroll: function(scroll) {
  19866. delete module.elementScroll;
  19867. },
  19868. minimumSize: function() {
  19869. $container
  19870. .css('min-height', '')
  19871. ;
  19872. },
  19873. offset: function() {
  19874. $module.css('margin-top', '');
  19875. }
  19876. },
  19877. set: {
  19878. offset: function() {
  19879. module.verbose('Setting offset on element', settings.offset);
  19880. $module
  19881. .css('margin-top', settings.offset)
  19882. ;
  19883. },
  19884. containerSize: function() {
  19885. var
  19886. tagName = $container.get(0).tagName
  19887. ;
  19888. if(tagName === 'HTML' || tagName == 'body') {
  19889. // this can trigger for too many reasons
  19890. //module.error(error.container, tagName, $module);
  19891. module.determineContainer();
  19892. }
  19893. else {
  19894. if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
  19895. module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
  19896. $container.css({
  19897. height: module.cache.context.height
  19898. });
  19899. }
  19900. }
  19901. },
  19902. minimumSize: function() {
  19903. var
  19904. element = module.cache.element
  19905. ;
  19906. $container
  19907. .css('min-height', element.height)
  19908. ;
  19909. },
  19910. scroll: function(scroll) {
  19911. module.debug('Setting scroll on element', scroll);
  19912. if(module.elementScroll == scroll) {
  19913. return;
  19914. }
  19915. if( module.is.top() ) {
  19916. $module
  19917. .css('bottom', '')
  19918. .css('top', -scroll)
  19919. ;
  19920. }
  19921. if( module.is.bottom() ) {
  19922. $module
  19923. .css('top', '')
  19924. .css('bottom', scroll)
  19925. ;
  19926. }
  19927. },
  19928. size: function() {
  19929. if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
  19930. element.style.setProperty('width', module.cache.element.width + 'px', 'important');
  19931. element.style.setProperty('height', module.cache.element.height + 'px', 'important');
  19932. }
  19933. }
  19934. },
  19935. is: {
  19936. standardScroll: function() {
  19937. return ($scroll[0] == window);
  19938. },
  19939. top: function() {
  19940. return $module.hasClass(className.top);
  19941. },
  19942. bottom: function() {
  19943. return $module.hasClass(className.bottom);
  19944. },
  19945. initialPosition: function() {
  19946. return (!module.is.fixed() && !module.is.bound());
  19947. },
  19948. hidden: function() {
  19949. return (!$module.is(':visible'));
  19950. },
  19951. bound: function() {
  19952. return $module.hasClass(className.bound);
  19953. },
  19954. fixed: function() {
  19955. return $module.hasClass(className.fixed);
  19956. }
  19957. },
  19958. stick: function(scroll) {
  19959. var
  19960. cachedPosition = scroll || $scroll.scrollTop(),
  19961. cache = module.cache,
  19962. fits = cache.fits,
  19963. sameHeight = cache.sameHeight,
  19964. element = cache.element,
  19965. scrollContext = cache.scrollContext,
  19966. context = cache.context,
  19967. offset = (module.is.bottom() && settings.pushing)
  19968. ? settings.bottomOffset
  19969. : settings.offset,
  19970. scroll = {
  19971. top : cachedPosition + offset,
  19972. bottom : cachedPosition + offset + scrollContext.height
  19973. },
  19974. elementScroll = (fits)
  19975. ? 0
  19976. : module.get.elementScroll(scroll.top),
  19977. // shorthand
  19978. doesntFit = !fits,
  19979. elementVisible = (element.height !== 0)
  19980. ;
  19981. if(elementVisible && !sameHeight) {
  19982. if( module.is.initialPosition() ) {
  19983. if(scroll.top >= context.bottom) {
  19984. module.debug('Initial element position is bottom of container');
  19985. module.bindBottom();
  19986. }
  19987. else if(scroll.top > element.top) {
  19988. if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  19989. module.debug('Initial element position is bottom of container');
  19990. module.bindBottom();
  19991. }
  19992. else {
  19993. module.debug('Initial element position is fixed');
  19994. module.fixTop();
  19995. }
  19996. }
  19997. }
  19998. else if( module.is.fixed() ) {
  19999. // currently fixed top
  20000. if( module.is.top() ) {
  20001. if( scroll.top <= element.top ) {
  20002. module.debug('Fixed element reached top of container');
  20003. module.setInitialPosition();
  20004. }
  20005. else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  20006. module.debug('Fixed element reached bottom of container');
  20007. module.bindBottom();
  20008. }
  20009. // scroll element if larger than screen
  20010. else if(doesntFit) {
  20011. module.set.scroll(elementScroll);
  20012. module.save.lastScroll(scroll.top);
  20013. module.save.elementScroll(elementScroll);
  20014. }
  20015. }
  20016. // currently fixed bottom
  20017. else if(module.is.bottom() ) {
  20018. // top edge
  20019. if( (scroll.bottom - element.height) <= element.top) {
  20020. module.debug('Bottom fixed rail has reached top of container');
  20021. module.setInitialPosition();
  20022. }
  20023. // bottom edge
  20024. else if(scroll.bottom >= context.bottom) {
  20025. module.debug('Bottom fixed rail has reached bottom of container');
  20026. module.bindBottom();
  20027. }
  20028. // scroll element if larger than screen
  20029. else if(doesntFit) {
  20030. module.set.scroll(elementScroll);
  20031. module.save.lastScroll(scroll.top);
  20032. module.save.elementScroll(elementScroll);
  20033. }
  20034. }
  20035. }
  20036. else if( module.is.bottom() ) {
  20037. if( scroll.top <= element.top ) {
  20038. module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
  20039. module.setInitialPosition();
  20040. }
  20041. else {
  20042. if(settings.pushing) {
  20043. if(module.is.bound() && scroll.bottom <= context.bottom ) {
  20044. module.debug('Fixing bottom attached element to bottom of browser.');
  20045. module.fixBottom();
  20046. }
  20047. }
  20048. else {
  20049. if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
  20050. module.debug('Fixing bottom attached element to top of browser.');
  20051. module.fixTop();
  20052. }
  20053. }
  20054. }
  20055. }
  20056. }
  20057. },
  20058. bindTop: function() {
  20059. module.debug('Binding element to top of parent container');
  20060. module.remove.offset();
  20061. $module
  20062. .css({
  20063. left : '',
  20064. top : '',
  20065. marginBottom : ''
  20066. })
  20067. .removeClass(className.fixed)
  20068. .removeClass(className.bottom)
  20069. .addClass(className.bound)
  20070. .addClass(className.top)
  20071. ;
  20072. settings.onTop.call(element);
  20073. settings.onUnstick.call(element);
  20074. },
  20075. bindBottom: function() {
  20076. module.debug('Binding element to bottom of parent container');
  20077. module.remove.offset();
  20078. $module
  20079. .css({
  20080. left : '',
  20081. top : ''
  20082. })
  20083. .removeClass(className.fixed)
  20084. .removeClass(className.top)
  20085. .addClass(className.bound)
  20086. .addClass(className.bottom)
  20087. ;
  20088. settings.onBottom.call(element);
  20089. settings.onUnstick.call(element);
  20090. },
  20091. setInitialPosition: function() {
  20092. module.debug('Returning to initial position');
  20093. module.unfix();
  20094. module.unbind();
  20095. },
  20096. fixTop: function() {
  20097. module.debug('Fixing element to top of page');
  20098. if(settings.setSize) {
  20099. module.set.size();
  20100. }
  20101. module.set.minimumSize();
  20102. module.set.offset();
  20103. $module
  20104. .css({
  20105. left : module.cache.element.left,
  20106. bottom : '',
  20107. marginBottom : ''
  20108. })
  20109. .removeClass(className.bound)
  20110. .removeClass(className.bottom)
  20111. .addClass(className.fixed)
  20112. .addClass(className.top)
  20113. ;
  20114. settings.onStick.call(element);
  20115. },
  20116. fixBottom: function() {
  20117. module.debug('Sticking element to bottom of page');
  20118. if(settings.setSize) {
  20119. module.set.size();
  20120. }
  20121. module.set.minimumSize();
  20122. module.set.offset();
  20123. $module
  20124. .css({
  20125. left : module.cache.element.left,
  20126. bottom : '',
  20127. marginBottom : ''
  20128. })
  20129. .removeClass(className.bound)
  20130. .removeClass(className.top)
  20131. .addClass(className.fixed)
  20132. .addClass(className.bottom)
  20133. ;
  20134. settings.onStick.call(element);
  20135. },
  20136. unbind: function() {
  20137. if( module.is.bound() ) {
  20138. module.debug('Removing container bound position on element');
  20139. module.remove.offset();
  20140. $module
  20141. .removeClass(className.bound)
  20142. .removeClass(className.top)
  20143. .removeClass(className.bottom)
  20144. ;
  20145. }
  20146. },
  20147. unfix: function() {
  20148. if( module.is.fixed() ) {
  20149. module.debug('Removing fixed position on element');
  20150. module.remove.minimumSize();
  20151. module.remove.offset();
  20152. $module
  20153. .removeClass(className.fixed)
  20154. .removeClass(className.top)
  20155. .removeClass(className.bottom)
  20156. ;
  20157. settings.onUnstick.call(element);
  20158. }
  20159. },
  20160. reset: function() {
  20161. module.debug('Resetting elements position');
  20162. module.unbind();
  20163. module.unfix();
  20164. module.resetCSS();
  20165. module.remove.offset();
  20166. module.remove.lastScroll();
  20167. },
  20168. resetCSS: function() {
  20169. $module
  20170. .css({
  20171. width : '',
  20172. height : ''
  20173. })
  20174. ;
  20175. $container
  20176. .css({
  20177. height: ''
  20178. })
  20179. ;
  20180. },
  20181. setting: function(name, value) {
  20182. if( $.isPlainObject(name) ) {
  20183. $.extend(true, settings, name);
  20184. }
  20185. else if(value !== undefined) {
  20186. settings[name] = value;
  20187. }
  20188. else {
  20189. return settings[name];
  20190. }
  20191. },
  20192. internal: function(name, value) {
  20193. if( $.isPlainObject(name) ) {
  20194. $.extend(true, module, name);
  20195. }
  20196. else if(value !== undefined) {
  20197. module[name] = value;
  20198. }
  20199. else {
  20200. return module[name];
  20201. }
  20202. },
  20203. debug: function() {
  20204. if(!settings.silent && settings.debug) {
  20205. if(settings.performance) {
  20206. module.performance.log(arguments);
  20207. }
  20208. else {
  20209. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20210. module.debug.apply(console, arguments);
  20211. }
  20212. }
  20213. },
  20214. verbose: function() {
  20215. if(!settings.silent && settings.verbose && settings.debug) {
  20216. if(settings.performance) {
  20217. module.performance.log(arguments);
  20218. }
  20219. else {
  20220. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20221. module.verbose.apply(console, arguments);
  20222. }
  20223. }
  20224. },
  20225. error: function() {
  20226. if(!settings.silent) {
  20227. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  20228. module.error.apply(console, arguments);
  20229. }
  20230. },
  20231. performance: {
  20232. log: function(message) {
  20233. var
  20234. currentTime,
  20235. executionTime,
  20236. previousTime
  20237. ;
  20238. if(settings.performance) {
  20239. currentTime = new Date().getTime();
  20240. previousTime = time || currentTime;
  20241. executionTime = currentTime - previousTime;
  20242. time = currentTime;
  20243. performance.push({
  20244. 'Name' : message[0],
  20245. 'Arguments' : [].slice.call(message, 1) || '',
  20246. 'Element' : element,
  20247. 'Execution Time' : executionTime
  20248. });
  20249. }
  20250. clearTimeout(module.performance.timer);
  20251. module.performance.timer = setTimeout(module.performance.display, 0);
  20252. },
  20253. display: function() {
  20254. var
  20255. title = settings.name + ':',
  20256. totalTime = 0
  20257. ;
  20258. time = false;
  20259. clearTimeout(module.performance.timer);
  20260. $.each(performance, function(index, data) {
  20261. totalTime += data['Execution Time'];
  20262. });
  20263. title += ' ' + totalTime + 'ms';
  20264. if(moduleSelector) {
  20265. title += ' \'' + moduleSelector + '\'';
  20266. }
  20267. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  20268. console.groupCollapsed(title);
  20269. if(console.table) {
  20270. console.table(performance);
  20271. }
  20272. else {
  20273. $.each(performance, function(index, data) {
  20274. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  20275. });
  20276. }
  20277. console.groupEnd();
  20278. }
  20279. performance = [];
  20280. }
  20281. },
  20282. invoke: function(query, passedArguments, context) {
  20283. var
  20284. object = instance,
  20285. maxDepth,
  20286. found,
  20287. response
  20288. ;
  20289. passedArguments = passedArguments || queryArguments;
  20290. context = element || context;
  20291. if(typeof query == 'string' && object !== undefined) {
  20292. query = query.split(/[\. ]/);
  20293. maxDepth = query.length - 1;
  20294. $.each(query, function(depth, value) {
  20295. var camelCaseValue = (depth != maxDepth)
  20296. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  20297. : query
  20298. ;
  20299. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  20300. object = object[camelCaseValue];
  20301. }
  20302. else if( object[camelCaseValue] !== undefined ) {
  20303. found = object[camelCaseValue];
  20304. return false;
  20305. }
  20306. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  20307. object = object[value];
  20308. }
  20309. else if( object[value] !== undefined ) {
  20310. found = object[value];
  20311. return false;
  20312. }
  20313. else {
  20314. return false;
  20315. }
  20316. });
  20317. }
  20318. if ( $.isFunction( found ) ) {
  20319. response = found.apply(context, passedArguments);
  20320. }
  20321. else if(found !== undefined) {
  20322. response = found;
  20323. }
  20324. if(Array.isArray(returnedValue)) {
  20325. returnedValue.push(response);
  20326. }
  20327. else if(returnedValue !== undefined) {
  20328. returnedValue = [returnedValue, response];
  20329. }
  20330. else if(response !== undefined) {
  20331. returnedValue = response;
  20332. }
  20333. return found;
  20334. }
  20335. };
  20336. if(methodInvoked) {
  20337. if(instance === undefined) {
  20338. module.initialize();
  20339. }
  20340. module.invoke(query);
  20341. }
  20342. else {
  20343. if(instance !== undefined) {
  20344. instance.invoke('destroy');
  20345. }
  20346. module.initialize();
  20347. }
  20348. })
  20349. ;
  20350. return (returnedValue !== undefined)
  20351. ? returnedValue
  20352. : this
  20353. ;
  20354. };
  20355. $.fn.sticky.settings = {
  20356. name : 'Sticky',
  20357. namespace : 'sticky',
  20358. silent : false,
  20359. debug : false,
  20360. verbose : true,
  20361. performance : true,
  20362. // whether to stick in the opposite direction on scroll up
  20363. pushing : false,
  20364. context : false,
  20365. container : false,
  20366. // Context to watch scroll events
  20367. scrollContext : window,
  20368. // Offset to adjust scroll
  20369. offset : 0,
  20370. // Offset to adjust scroll when attached to bottom of screen
  20371. bottomOffset : 0,
  20372. // will only set container height if difference between context and container is larger than this number
  20373. jitter : 5,
  20374. // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
  20375. setSize : true,
  20376. // Whether to automatically observe changes with Mutation Observers
  20377. observeChanges : false,
  20378. // Called when position is recalculated
  20379. onReposition : function(){},
  20380. // Called on each scroll
  20381. onScroll : function(){},
  20382. // Called when element is stuck to viewport
  20383. onStick : function(){},
  20384. // Called when element is unstuck from viewport
  20385. onUnstick : function(){},
  20386. // Called when element reaches top of context
  20387. onTop : function(){},
  20388. // Called when element reaches bottom of context
  20389. onBottom : function(){},
  20390. error : {
  20391. container : 'Sticky element must be inside a relative container',
  20392. visible : 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to surpress this warning in production.',
  20393. method : 'The method you called is not defined.',
  20394. invalidContext : 'Context specified does not exist',
  20395. elementSize : 'Sticky element is larger than its container, cannot create sticky.'
  20396. },
  20397. className : {
  20398. bound : 'bound',
  20399. fixed : 'fixed',
  20400. supported : 'native',
  20401. top : 'top',
  20402. bottom : 'bottom'
  20403. }
  20404. };
  20405. })( jQuery, window, document );
  20406. /*!
  20407. * # Fomantic-UI - Tab
  20408. * http://github.com/fomantic/Fomantic-UI/
  20409. *
  20410. *
  20411. * Released under the MIT license
  20412. * http://opensource.org/licenses/MIT
  20413. *
  20414. */
  20415. ;(function ($, window, document, undefined) {
  20416. 'use strict';
  20417. $.isWindow = $.isWindow || function(obj) {
  20418. return obj != null && obj === obj.window;
  20419. };
  20420. $.isFunction = $.isFunction || function(obj) {
  20421. return typeof obj === "function" && typeof obj.nodeType !== "number";
  20422. };
  20423. window = (typeof window != 'undefined' && window.Math == Math)
  20424. ? window
  20425. : (typeof self != 'undefined' && self.Math == Math)
  20426. ? self
  20427. : Function('return this')()
  20428. ;
  20429. $.fn.tab = function(parameters) {
  20430. var
  20431. // use window context if none specified
  20432. $allModules = $.isFunction(this)
  20433. ? $(window)
  20434. : $(this),
  20435. moduleSelector = $allModules.selector || '',
  20436. time = new Date().getTime(),
  20437. performance = [],
  20438. query = arguments[0],
  20439. methodInvoked = (typeof query == 'string'),
  20440. queryArguments = [].slice.call(arguments, 1),
  20441. initializedHistory = false,
  20442. returnedValue
  20443. ;
  20444. $allModules
  20445. .each(function() {
  20446. var
  20447. settings = ( $.isPlainObject(parameters) )
  20448. ? $.extend(true, {}, $.fn.tab.settings, parameters)
  20449. : $.extend({}, $.fn.tab.settings),
  20450. className = settings.className,
  20451. metadata = settings.metadata,
  20452. selector = settings.selector,
  20453. error = settings.error,
  20454. regExp = settings.regExp,
  20455. eventNamespace = '.' + settings.namespace,
  20456. moduleNamespace = 'module-' + settings.namespace,
  20457. $module = $(this),
  20458. $context,
  20459. $tabs,
  20460. cache = {},
  20461. firstLoad = true,
  20462. recursionDepth = 0,
  20463. element = this,
  20464. instance = $module.data(moduleNamespace),
  20465. activeTabPath,
  20466. parameterArray,
  20467. module,
  20468. historyEvent
  20469. ;
  20470. module = {
  20471. initialize: function() {
  20472. module.debug('Initializing tab menu item', $module);
  20473. module.fix.callbacks();
  20474. module.determineTabs();
  20475. module.debug('Determining tabs', settings.context, $tabs);
  20476. // set up automatic routing
  20477. if(settings.auto) {
  20478. module.set.auto();
  20479. }
  20480. module.bind.events();
  20481. if(settings.history && !initializedHistory) {
  20482. module.initializeHistory();
  20483. initializedHistory = true;
  20484. }
  20485. if(instance === undefined && module.determine.activeTab() == null) {
  20486. module.debug('No active tab detected, setting first tab active', module.get.initialPath());
  20487. module.changeTab(module.get.initialPath());
  20488. };
  20489. module.instantiate();
  20490. },
  20491. instantiate: function () {
  20492. module.verbose('Storing instance of module', module);
  20493. instance = module;
  20494. $module
  20495. .data(moduleNamespace, module)
  20496. ;
  20497. },
  20498. destroy: function() {
  20499. module.debug('Destroying tabs', $module);
  20500. $module
  20501. .removeData(moduleNamespace)
  20502. .off(eventNamespace)
  20503. ;
  20504. },
  20505. bind: {
  20506. events: function() {
  20507. // if using $.tab don't add events
  20508. if( !$.isWindow( element ) ) {
  20509. module.debug('Attaching tab activation events to element', $module);
  20510. $module
  20511. .on('click' + eventNamespace, module.event.click)
  20512. ;
  20513. }
  20514. }
  20515. },
  20516. determineTabs: function() {
  20517. var
  20518. $reference
  20519. ;
  20520. // determine tab context
  20521. if(settings.context === 'parent') {
  20522. if($module.closest(selector.ui).length > 0) {
  20523. $reference = $module.closest(selector.ui);
  20524. module.verbose('Using closest UI element as parent', $reference);
  20525. }
  20526. else {
  20527. $reference = $module;
  20528. }
  20529. $context = $reference.parent();
  20530. module.verbose('Determined parent element for creating context', $context);
  20531. }
  20532. else if(settings.context) {
  20533. $context = $(settings.context);
  20534. module.verbose('Using selector for tab context', settings.context, $context);
  20535. }
  20536. else {
  20537. $context = $('body');
  20538. }
  20539. // find tabs
  20540. if(settings.childrenOnly) {
  20541. $tabs = $context.children(selector.tabs);
  20542. module.debug('Searching tab context children for tabs', $context, $tabs);
  20543. }
  20544. else {
  20545. $tabs = $context.find(selector.tabs);
  20546. module.debug('Searching tab context for tabs', $context, $tabs);
  20547. }
  20548. },
  20549. fix: {
  20550. callbacks: function() {
  20551. if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
  20552. if(parameters.onTabLoad) {
  20553. parameters.onLoad = parameters.onTabLoad;
  20554. delete parameters.onTabLoad;
  20555. module.error(error.legacyLoad, parameters.onLoad);
  20556. }
  20557. if(parameters.onTabInit) {
  20558. parameters.onFirstLoad = parameters.onTabInit;
  20559. delete parameters.onTabInit;
  20560. module.error(error.legacyInit, parameters.onFirstLoad);
  20561. }
  20562. settings = $.extend(true, {}, $.fn.tab.settings, parameters);
  20563. }
  20564. }
  20565. },
  20566. initializeHistory: function() {
  20567. module.debug('Initializing page state');
  20568. if( $.address === undefined ) {
  20569. module.error(error.state);
  20570. return false;
  20571. }
  20572. else {
  20573. if(settings.historyType == 'state') {
  20574. module.debug('Using HTML5 to manage state');
  20575. if(settings.path !== false) {
  20576. $.address
  20577. .history(true)
  20578. .state(settings.path)
  20579. ;
  20580. }
  20581. else {
  20582. module.error(error.path);
  20583. return false;
  20584. }
  20585. }
  20586. $.address
  20587. .bind('change', module.event.history.change)
  20588. ;
  20589. }
  20590. },
  20591. event: {
  20592. click: function(event) {
  20593. var
  20594. tabPath = $(this).data(metadata.tab)
  20595. ;
  20596. if(tabPath !== undefined) {
  20597. if(settings.history) {
  20598. module.verbose('Updating page state', event);
  20599. $.address.value(tabPath);
  20600. }
  20601. else {
  20602. module.verbose('Changing tab', event);
  20603. module.changeTab(tabPath);
  20604. }
  20605. event.preventDefault();
  20606. }
  20607. else {
  20608. module.debug('No tab specified');
  20609. }
  20610. },
  20611. history: {
  20612. change: function(event) {
  20613. var
  20614. tabPath = event.pathNames.join('/') || module.get.initialPath(),
  20615. pageTitle = settings.templates.determineTitle(tabPath) || false
  20616. ;
  20617. module.performance.display();
  20618. module.debug('History change event', tabPath, event);
  20619. historyEvent = event;
  20620. if(tabPath !== undefined) {
  20621. module.changeTab(tabPath);
  20622. }
  20623. if(pageTitle) {
  20624. $.address.title(pageTitle);
  20625. }
  20626. }
  20627. }
  20628. },
  20629. refresh: function() {
  20630. if(activeTabPath) {
  20631. module.debug('Refreshing tab', activeTabPath);
  20632. module.changeTab(activeTabPath);
  20633. }
  20634. },
  20635. cache: {
  20636. read: function(cacheKey) {
  20637. return (cacheKey !== undefined)
  20638. ? cache[cacheKey]
  20639. : false
  20640. ;
  20641. },
  20642. add: function(cacheKey, content) {
  20643. cacheKey = cacheKey || activeTabPath;
  20644. module.debug('Adding cached content for', cacheKey);
  20645. cache[cacheKey] = content;
  20646. },
  20647. remove: function(cacheKey) {
  20648. cacheKey = cacheKey || activeTabPath;
  20649. module.debug('Removing cached content for', cacheKey);
  20650. delete cache[cacheKey];
  20651. }
  20652. },
  20653. escape: {
  20654. string: function(text) {
  20655. text = String(text);
  20656. return text.replace(regExp.escape, '\\$&');
  20657. }
  20658. },
  20659. set: {
  20660. auto: function() {
  20661. var
  20662. url = (typeof settings.path == 'string')
  20663. ? settings.path.replace(/\/$/, '') + '/{$tab}'
  20664. : '/{$tab}'
  20665. ;
  20666. module.verbose('Setting up automatic tab retrieval from server', url);
  20667. if($.isPlainObject(settings.apiSettings)) {
  20668. settings.apiSettings.url = url;
  20669. }
  20670. else {
  20671. settings.apiSettings = {
  20672. url: url
  20673. };
  20674. }
  20675. },
  20676. loading: function(tabPath) {
  20677. var
  20678. $tab = module.get.tabElement(tabPath),
  20679. isLoading = $tab.hasClass(className.loading)
  20680. ;
  20681. if(!isLoading) {
  20682. module.verbose('Setting loading state for', $tab);
  20683. $tab
  20684. .addClass(className.loading)
  20685. .siblings($tabs)
  20686. .removeClass(className.active + ' ' + className.loading)
  20687. ;
  20688. if($tab.length > 0) {
  20689. settings.onRequest.call($tab[0], tabPath);
  20690. }
  20691. }
  20692. },
  20693. state: function(state) {
  20694. $.address.value(state);
  20695. }
  20696. },
  20697. changeTab: function(tabPath) {
  20698. var
  20699. pushStateAvailable = (window.history && window.history.pushState),
  20700. shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
  20701. remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
  20702. // only add default path if not remote content
  20703. pathArray = (remoteContent && !shouldIgnoreLoad)
  20704. ? module.utilities.pathToArray(tabPath)
  20705. : module.get.defaultPathArray(tabPath)
  20706. ;
  20707. tabPath = module.utilities.arrayToPath(pathArray);
  20708. $.each(pathArray, function(index, tab) {
  20709. var
  20710. currentPathArray = pathArray.slice(0, index + 1),
  20711. currentPath = module.utilities.arrayToPath(currentPathArray),
  20712. isTab = module.is.tab(currentPath),
  20713. isLastIndex = (index + 1 == pathArray.length),
  20714. $tab = module.get.tabElement(currentPath),
  20715. $anchor,
  20716. nextPathArray,
  20717. nextPath,
  20718. isLastTab
  20719. ;
  20720. module.verbose('Looking for tab', tab);
  20721. if(isTab) {
  20722. module.verbose('Tab was found', tab);
  20723. // scope up
  20724. activeTabPath = currentPath;
  20725. parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
  20726. if(isLastIndex) {
  20727. isLastTab = true;
  20728. }
  20729. else {
  20730. nextPathArray = pathArray.slice(0, index + 2);
  20731. nextPath = module.utilities.arrayToPath(nextPathArray);
  20732. isLastTab = ( !module.is.tab(nextPath) );
  20733. if(isLastTab) {
  20734. module.verbose('Tab parameters found', nextPathArray);
  20735. }
  20736. }
  20737. if(isLastTab && remoteContent) {
  20738. if(!shouldIgnoreLoad) {
  20739. module.activate.navigation(currentPath);
  20740. module.fetch.content(currentPath, tabPath);
  20741. }
  20742. else {
  20743. module.debug('Ignoring remote content on first tab load', currentPath);
  20744. firstLoad = false;
  20745. module.cache.add(tabPath, $tab.html());
  20746. module.activate.all(currentPath);
  20747. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20748. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20749. }
  20750. return false;
  20751. }
  20752. else {
  20753. module.debug('Opened local tab', currentPath);
  20754. module.activate.all(currentPath);
  20755. if( !module.cache.read(currentPath) ) {
  20756. module.cache.add(currentPath, true);
  20757. module.debug('First time tab loaded calling tab init');
  20758. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20759. }
  20760. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20761. }
  20762. }
  20763. else if(tabPath.search('/') == -1 && tabPath !== '') {
  20764. // look for in page anchor
  20765. tabPath = module.escape.string(tabPath);
  20766. $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
  20767. currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
  20768. $tab = module.get.tabElement(currentPath);
  20769. // if anchor exists use parent tab
  20770. if($anchor && $anchor.length > 0 && currentPath) {
  20771. module.debug('Anchor link used, opening parent tab', $tab, $anchor);
  20772. if( !$tab.hasClass(className.active) ) {
  20773. setTimeout(function() {
  20774. module.scrollTo($anchor);
  20775. }, 0);
  20776. }
  20777. module.activate.all(currentPath);
  20778. if( !module.cache.read(currentPath) ) {
  20779. module.cache.add(currentPath, true);
  20780. module.debug('First time tab loaded calling tab init');
  20781. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20782. }
  20783. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20784. return false;
  20785. }
  20786. }
  20787. else {
  20788. module.error(error.missingTab, $module, $context, currentPath);
  20789. return false;
  20790. }
  20791. });
  20792. },
  20793. scrollTo: function($element) {
  20794. var
  20795. scrollOffset = ($element && $element.length > 0)
  20796. ? $element.offset().top
  20797. : false
  20798. ;
  20799. if(scrollOffset !== false) {
  20800. module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
  20801. $(document).scrollTop(scrollOffset);
  20802. }
  20803. },
  20804. update: {
  20805. content: function(tabPath, html, evaluateScripts) {
  20806. var
  20807. $tab = module.get.tabElement(tabPath),
  20808. tab = $tab[0]
  20809. ;
  20810. evaluateScripts = (evaluateScripts !== undefined)
  20811. ? evaluateScripts
  20812. : settings.evaluateScripts
  20813. ;
  20814. if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') {
  20815. $tab
  20816. .empty()
  20817. .append($(html).clone(true))
  20818. ;
  20819. }
  20820. else {
  20821. if(evaluateScripts) {
  20822. module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
  20823. $tab.html(html);
  20824. }
  20825. else {
  20826. module.debug('Updating HTML', tabPath, html);
  20827. tab.innerHTML = html;
  20828. }
  20829. }
  20830. }
  20831. },
  20832. fetch: {
  20833. content: function(tabPath, fullTabPath) {
  20834. var
  20835. $tab = module.get.tabElement(tabPath),
  20836. apiSettings = {
  20837. dataType : 'html',
  20838. encodeParameters : false,
  20839. on : 'now',
  20840. cache : settings.alwaysRefresh,
  20841. headers : {
  20842. 'X-Remote': true
  20843. },
  20844. onSuccess : function(response) {
  20845. if(settings.cacheType == 'response') {
  20846. module.cache.add(fullTabPath, response);
  20847. }
  20848. module.update.content(tabPath, response);
  20849. if(tabPath == activeTabPath) {
  20850. module.debug('Content loaded', tabPath);
  20851. module.activate.tab(tabPath);
  20852. }
  20853. else {
  20854. module.debug('Content loaded in background', tabPath);
  20855. }
  20856. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  20857. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  20858. if(settings.loadOnce) {
  20859. module.cache.add(fullTabPath, true);
  20860. }
  20861. else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) {
  20862. setTimeout(function() {
  20863. var
  20864. $clone = $tab.children().clone(true)
  20865. ;
  20866. $clone = $clone.not('script');
  20867. module.cache.add(fullTabPath, $clone);
  20868. }, 0);
  20869. }
  20870. else {
  20871. module.cache.add(fullTabPath, $tab.html());
  20872. }
  20873. },
  20874. urlData: {
  20875. tab: fullTabPath
  20876. }
  20877. },
  20878. request = $tab.api('get request') || false,
  20879. existingRequest = ( request && request.state() === 'pending' ),
  20880. requestSettings,
  20881. cachedContent
  20882. ;
  20883. fullTabPath = fullTabPath || tabPath;
  20884. cachedContent = module.cache.read(fullTabPath);
  20885. if(settings.cache && cachedContent) {
  20886. module.activate.tab(tabPath);
  20887. module.debug('Adding cached content', fullTabPath);
  20888. if(!settings.loadOnce) {
  20889. if(settings.evaluateScripts == 'once') {
  20890. module.update.content(tabPath, cachedContent, false);
  20891. }
  20892. else {
  20893. module.update.content(tabPath, cachedContent);
  20894. }
  20895. }
  20896. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  20897. }
  20898. else if(existingRequest) {
  20899. module.set.loading(tabPath);
  20900. module.debug('Content is already loading', fullTabPath);
  20901. }
  20902. else if($.api !== undefined) {
  20903. requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
  20904. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  20905. module.set.loading(tabPath);
  20906. $tab.api(requestSettings);
  20907. }
  20908. else {
  20909. module.error(error.api);
  20910. }
  20911. }
  20912. },
  20913. activate: {
  20914. all: function(tabPath) {
  20915. module.activate.tab(tabPath);
  20916. module.activate.navigation(tabPath);
  20917. },
  20918. tab: function(tabPath) {
  20919. var
  20920. $tab = module.get.tabElement(tabPath),
  20921. $deactiveTabs = (settings.deactivate == 'siblings')
  20922. ? $tab.siblings($tabs)
  20923. : $tabs.not($tab),
  20924. isActive = $tab.hasClass(className.active)
  20925. ;
  20926. module.verbose('Showing tab content for', $tab);
  20927. if(!isActive) {
  20928. $tab
  20929. .addClass(className.active)
  20930. ;
  20931. $deactiveTabs
  20932. .removeClass(className.active + ' ' + className.loading)
  20933. ;
  20934. if($tab.length > 0) {
  20935. settings.onVisible.call($tab[0], tabPath);
  20936. }
  20937. }
  20938. },
  20939. navigation: function(tabPath) {
  20940. var
  20941. $navigation = module.get.navElement(tabPath),
  20942. $deactiveNavigation = (settings.deactivate == 'siblings')
  20943. ? $navigation.siblings($allModules)
  20944. : $allModules.not($navigation),
  20945. isActive = $navigation.hasClass(className.active)
  20946. ;
  20947. module.verbose('Activating tab navigation for', $navigation, tabPath);
  20948. if(!isActive) {
  20949. $navigation
  20950. .addClass(className.active)
  20951. ;
  20952. $deactiveNavigation
  20953. .removeClass(className.active + ' ' + className.loading)
  20954. ;
  20955. }
  20956. }
  20957. },
  20958. deactivate: {
  20959. all: function() {
  20960. module.deactivate.navigation();
  20961. module.deactivate.tabs();
  20962. },
  20963. navigation: function() {
  20964. $allModules
  20965. .removeClass(className.active)
  20966. ;
  20967. },
  20968. tabs: function() {
  20969. $tabs
  20970. .removeClass(className.active + ' ' + className.loading)
  20971. ;
  20972. }
  20973. },
  20974. is: {
  20975. tab: function(tabName) {
  20976. return (tabName !== undefined)
  20977. ? ( module.get.tabElement(tabName).length > 0 )
  20978. : false
  20979. ;
  20980. }
  20981. },
  20982. get: {
  20983. initialPath: function() {
  20984. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  20985. },
  20986. path: function() {
  20987. return $.address.value();
  20988. },
  20989. // adds default tabs to tab path
  20990. defaultPathArray: function(tabPath) {
  20991. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  20992. },
  20993. defaultPath: function(tabPath) {
  20994. var
  20995. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + module.escape.string(tabPath) + '/"]').eq(0),
  20996. defaultTab = $defaultNav.data(metadata.tab) || false
  20997. ;
  20998. if( defaultTab ) {
  20999. module.debug('Found default tab', defaultTab);
  21000. if(recursionDepth < settings.maxDepth) {
  21001. recursionDepth++;
  21002. return module.get.defaultPath(defaultTab);
  21003. }
  21004. module.error(error.recursion);
  21005. }
  21006. else {
  21007. module.debug('No default tabs found for', tabPath, $tabs);
  21008. }
  21009. recursionDepth = 0;
  21010. return tabPath;
  21011. },
  21012. navElement: function(tabPath) {
  21013. tabPath = tabPath || activeTabPath;
  21014. return $allModules.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]');
  21015. },
  21016. tabElement: function(tabPath) {
  21017. var
  21018. $fullPathTab,
  21019. $simplePathTab,
  21020. tabPathArray,
  21021. lastTab
  21022. ;
  21023. tabPath = tabPath || activeTabPath;
  21024. tabPathArray = module.utilities.pathToArray(tabPath);
  21025. lastTab = module.utilities.last(tabPathArray);
  21026. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]');
  21027. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + module.escape.string(lastTab) + '"]');
  21028. return ($fullPathTab.length > 0)
  21029. ? $fullPathTab
  21030. : $simplePathTab
  21031. ;
  21032. },
  21033. tab: function() {
  21034. return activeTabPath;
  21035. }
  21036. },
  21037. determine: {
  21038. activeTab: function() {
  21039. var activeTab = null;
  21040. $tabs.each(function(_index, tab) {
  21041. var $tab = $(tab);
  21042. if( $tab.hasClass(className.active) ) {
  21043. var
  21044. tabPath = $(this).data(metadata.tab),
  21045. $anchor = $allModules.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]')
  21046. ;
  21047. if( $anchor.hasClass(className.active) ) {
  21048. activeTab = tabPath;
  21049. }
  21050. }
  21051. });
  21052. return activeTab;
  21053. }
  21054. },
  21055. utilities: {
  21056. filterArray: function(keepArray, removeArray) {
  21057. return $.grep(keepArray, function(keepValue) {
  21058. return ( $.inArray(keepValue, removeArray) == -1);
  21059. });
  21060. },
  21061. last: function(array) {
  21062. return Array.isArray(array)
  21063. ? array[ array.length - 1]
  21064. : false
  21065. ;
  21066. },
  21067. pathToArray: function(pathName) {
  21068. if(pathName === undefined) {
  21069. pathName = activeTabPath;
  21070. }
  21071. return typeof pathName == 'string'
  21072. ? pathName.split('/')
  21073. : [pathName]
  21074. ;
  21075. },
  21076. arrayToPath: function(pathArray) {
  21077. return Array.isArray(pathArray)
  21078. ? pathArray.join('/')
  21079. : false
  21080. ;
  21081. }
  21082. },
  21083. setting: function(name, value) {
  21084. module.debug('Changing setting', name, value);
  21085. if( $.isPlainObject(name) ) {
  21086. $.extend(true, settings, name);
  21087. }
  21088. else if(value !== undefined) {
  21089. if($.isPlainObject(settings[name])) {
  21090. $.extend(true, settings[name], value);
  21091. }
  21092. else {
  21093. settings[name] = value;
  21094. }
  21095. }
  21096. else {
  21097. return settings[name];
  21098. }
  21099. },
  21100. internal: function(name, value) {
  21101. if( $.isPlainObject(name) ) {
  21102. $.extend(true, module, name);
  21103. }
  21104. else if(value !== undefined) {
  21105. module[name] = value;
  21106. }
  21107. else {
  21108. return module[name];
  21109. }
  21110. },
  21111. debug: function() {
  21112. if(!settings.silent && settings.debug) {
  21113. if(settings.performance) {
  21114. module.performance.log(arguments);
  21115. }
  21116. else {
  21117. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21118. module.debug.apply(console, arguments);
  21119. }
  21120. }
  21121. },
  21122. verbose: function() {
  21123. if(!settings.silent && settings.verbose && settings.debug) {
  21124. if(settings.performance) {
  21125. module.performance.log(arguments);
  21126. }
  21127. else {
  21128. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21129. module.verbose.apply(console, arguments);
  21130. }
  21131. }
  21132. },
  21133. error: function() {
  21134. if(!settings.silent) {
  21135. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  21136. module.error.apply(console, arguments);
  21137. }
  21138. },
  21139. performance: {
  21140. log: function(message) {
  21141. var
  21142. currentTime,
  21143. executionTime,
  21144. previousTime
  21145. ;
  21146. if(settings.performance) {
  21147. currentTime = new Date().getTime();
  21148. previousTime = time || currentTime;
  21149. executionTime = currentTime - previousTime;
  21150. time = currentTime;
  21151. performance.push({
  21152. 'Name' : message[0],
  21153. 'Arguments' : [].slice.call(message, 1) || '',
  21154. 'Element' : element,
  21155. 'Execution Time' : executionTime
  21156. });
  21157. }
  21158. clearTimeout(module.performance.timer);
  21159. module.performance.timer = setTimeout(module.performance.display, 500);
  21160. },
  21161. display: function() {
  21162. var
  21163. title = settings.name + ':',
  21164. totalTime = 0
  21165. ;
  21166. time = false;
  21167. clearTimeout(module.performance.timer);
  21168. $.each(performance, function(index, data) {
  21169. totalTime += data['Execution Time'];
  21170. });
  21171. title += ' ' + totalTime + 'ms';
  21172. if(moduleSelector) {
  21173. title += ' \'' + moduleSelector + '\'';
  21174. }
  21175. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  21176. console.groupCollapsed(title);
  21177. if(console.table) {
  21178. console.table(performance);
  21179. }
  21180. else {
  21181. $.each(performance, function(index, data) {
  21182. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  21183. });
  21184. }
  21185. console.groupEnd();
  21186. }
  21187. performance = [];
  21188. }
  21189. },
  21190. invoke: function(query, passedArguments, context) {
  21191. var
  21192. object = instance,
  21193. maxDepth,
  21194. found,
  21195. response
  21196. ;
  21197. passedArguments = passedArguments || queryArguments;
  21198. context = element || context;
  21199. if(typeof query == 'string' && object !== undefined) {
  21200. query = query.split(/[\. ]/);
  21201. maxDepth = query.length - 1;
  21202. $.each(query, function(depth, value) {
  21203. var camelCaseValue = (depth != maxDepth)
  21204. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  21205. : query
  21206. ;
  21207. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  21208. object = object[camelCaseValue];
  21209. }
  21210. else if( object[camelCaseValue] !== undefined ) {
  21211. found = object[camelCaseValue];
  21212. return false;
  21213. }
  21214. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  21215. object = object[value];
  21216. }
  21217. else if( object[value] !== undefined ) {
  21218. found = object[value];
  21219. return false;
  21220. }
  21221. else {
  21222. module.error(error.method, query);
  21223. return false;
  21224. }
  21225. });
  21226. }
  21227. if ( $.isFunction( found ) ) {
  21228. response = found.apply(context, passedArguments);
  21229. }
  21230. else if(found !== undefined) {
  21231. response = found;
  21232. }
  21233. if(Array.isArray(returnedValue)) {
  21234. returnedValue.push(response);
  21235. }
  21236. else if(returnedValue !== undefined) {
  21237. returnedValue = [returnedValue, response];
  21238. }
  21239. else if(response !== undefined) {
  21240. returnedValue = response;
  21241. }
  21242. return found;
  21243. }
  21244. };
  21245. if(methodInvoked) {
  21246. if(instance === undefined) {
  21247. module.initialize();
  21248. }
  21249. module.invoke(query);
  21250. }
  21251. else {
  21252. if(instance !== undefined) {
  21253. instance.invoke('destroy');
  21254. }
  21255. module.initialize();
  21256. }
  21257. })
  21258. ;
  21259. return (returnedValue !== undefined)
  21260. ? returnedValue
  21261. : this
  21262. ;
  21263. };
  21264. // shortcut for tabbed content with no defined navigation
  21265. $.tab = function() {
  21266. $(window).tab.apply(this, arguments);
  21267. };
  21268. $.fn.tab.settings = {
  21269. name : 'Tab',
  21270. namespace : 'tab',
  21271. silent : false,
  21272. debug : false,
  21273. verbose : false,
  21274. performance : true,
  21275. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  21276. history : false, // use browser history
  21277. historyType : 'hash', // #/ or html5 state
  21278. path : false, // base path of url
  21279. context : false, // specify a context that tabs must appear inside
  21280. childrenOnly : false, // use only tabs that are children of context
  21281. maxDepth : 25, // max depth a tab can be nested
  21282. deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together
  21283. alwaysRefresh : false, // load tab content new every tab click
  21284. cache : true, // cache the content requests to pull locally
  21285. loadOnce : false, // Whether tab data should only be loaded once when using remote content
  21286. cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute
  21287. ignoreFirstLoad : false, // don't load remote content on first load
  21288. apiSettings : false, // settings for api call
  21289. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  21290. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  21291. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  21292. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  21293. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  21294. templates : {
  21295. determineTitle: function(tabArray) {} // returns page title for path
  21296. },
  21297. error: {
  21298. api : 'You attempted to load content without API module',
  21299. method : 'The method you called is not defined',
  21300. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  21301. noContent : 'The tab you specified is missing a content url.',
  21302. path : 'History enabled, but no path was specified',
  21303. recursion : 'Max recursive depth reached',
  21304. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  21305. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  21306. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  21307. },
  21308. regExp : {
  21309. escape : /[-[\]{}()*+?.,\\^$|#\s:=@]/g
  21310. },
  21311. metadata : {
  21312. tab : 'tab',
  21313. loaded : 'loaded',
  21314. promise: 'promise'
  21315. },
  21316. className : {
  21317. loading : 'loading',
  21318. active : 'active'
  21319. },
  21320. selector : {
  21321. tabs : '.ui.tab',
  21322. ui : '.ui'
  21323. }
  21324. };
  21325. })( jQuery, window, document );
  21326. /*!
  21327. * # Fomantic-UI - Toast
  21328. * http://github.com/fomantic/Fomantic-UI/
  21329. *
  21330. *
  21331. * Released under the MIT license
  21332. * http://opensource.org/licenses/MIT
  21333. *
  21334. */
  21335. ;(function ($, window, document, undefined) {
  21336. 'use strict';
  21337. $.isFunction = $.isFunction || function(obj) {
  21338. return typeof obj === "function" && typeof obj.nodeType !== "number";
  21339. };
  21340. window = (typeof window != 'undefined' && window.Math == Math)
  21341. ? window
  21342. : (typeof self != 'undefined' && self.Math == Math)
  21343. ? self
  21344. : Function('return this')()
  21345. ;
  21346. $.fn.toast = function(parameters) {
  21347. var
  21348. $allModules = $(this),
  21349. moduleSelector = $allModules.selector || '',
  21350. time = new Date().getTime(),
  21351. performance = [],
  21352. query = arguments[0],
  21353. methodInvoked = (typeof query == 'string'),
  21354. queryArguments = [].slice.call(arguments, 1),
  21355. returnedValue
  21356. ;
  21357. $allModules
  21358. .each(function() {
  21359. var
  21360. settings = ( $.isPlainObject(parameters) )
  21361. ? $.extend(true, {}, $.fn.toast.settings, parameters)
  21362. : $.extend({}, $.fn.toast.settings),
  21363. className = settings.className,
  21364. selector = settings.selector,
  21365. error = settings.error,
  21366. namespace = settings.namespace,
  21367. fields = settings.fields,
  21368. eventNamespace = '.' + namespace,
  21369. moduleNamespace = namespace + '-module',
  21370. $module = $(this),
  21371. $toastBox,
  21372. $toast,
  21373. $actions,
  21374. $progress,
  21375. $progressBar,
  21376. $animationObject,
  21377. $close,
  21378. $context = (settings.context)
  21379. ? $(settings.context)
  21380. : $('body'),
  21381. isToastComponent = $module.hasClass('toast') || $module.hasClass('message') || $module.hasClass('card'),
  21382. element = this,
  21383. instance = isToastComponent ? $module.data(moduleNamespace) : undefined,
  21384. module
  21385. ;
  21386. module = {
  21387. initialize: function() {
  21388. module.verbose('Initializing element');
  21389. if (!module.has.container()) {
  21390. module.create.container();
  21391. }
  21392. if(isToastComponent || settings.message !== '' || settings.title !== '' || module.get.iconClass() !== '' || settings.showImage || module.has.configActions()) {
  21393. if(typeof settings.showProgress !== 'string' || [className.top,className.bottom].indexOf(settings.showProgress) === -1 ) {
  21394. settings.showProgress = false;
  21395. }
  21396. module.create.toast();
  21397. if(settings.closeOnClick && (settings.closeIcon || $($toast).find(selector.input).length > 0 || module.has.configActions())){
  21398. settings.closeOnClick = false;
  21399. }
  21400. if(!settings.closeOnClick) {
  21401. $toastBox.addClass(className.unclickable);
  21402. }
  21403. module.bind.events();
  21404. }
  21405. module.instantiate();
  21406. if($toastBox) {
  21407. module.show();
  21408. }
  21409. },
  21410. instantiate: function() {
  21411. module.verbose('Storing instance of toast');
  21412. instance = module;
  21413. $module
  21414. .data(moduleNamespace, instance)
  21415. ;
  21416. },
  21417. destroy: function() {
  21418. if($toastBox) {
  21419. module.debug('Removing toast', $toastBox);
  21420. module.unbind.events();
  21421. $toastBox.remove();
  21422. $toastBox = undefined;
  21423. $toast = undefined;
  21424. $animationObject = undefined;
  21425. settings.onRemove.call($toastBox, element);
  21426. $progress = undefined;
  21427. $progressBar = undefined;
  21428. $close = undefined;
  21429. }
  21430. $module
  21431. .removeData(moduleNamespace)
  21432. ;
  21433. },
  21434. show: function(callback) {
  21435. callback = callback || function(){};
  21436. module.debug('Showing toast');
  21437. if(settings.onShow.call($toastBox, element) === false) {
  21438. module.debug('onShow callback returned false, cancelling toast animation');
  21439. return;
  21440. }
  21441. module.animate.show(callback);
  21442. },
  21443. close: function(callback) {
  21444. callback = callback || function(){};
  21445. module.remove.visible();
  21446. module.unbind.events();
  21447. module.animate.close(callback);
  21448. },
  21449. create: {
  21450. container: function() {
  21451. module.verbose('Creating container');
  21452. $context.append($('<div/>',{class: settings.position + ' ' + className.container}));
  21453. },
  21454. toast: function() {
  21455. $toastBox = $('<div/>', {class: className.box});
  21456. if (!isToastComponent) {
  21457. module.verbose('Creating toast');
  21458. $toast = $('<div/>');
  21459. var $content = $('<div/>', {class: className.content});
  21460. var iconClass = module.get.iconClass();
  21461. if (iconClass !== '') {
  21462. $toast.append($('<i/>', {class: iconClass + ' ' + className.icon}));
  21463. }
  21464. if (settings.showImage) {
  21465. $toast.append($('<img>', {
  21466. class: className.image + ' ' + settings.classImage,
  21467. src: settings.showImage
  21468. }));
  21469. }
  21470. if (settings.title !== '') {
  21471. $content.append($('<div/>', {
  21472. class: className.title,
  21473. text: settings.title
  21474. }));
  21475. }
  21476. $content.append($('<div/>', {html: module.helpers.escape(settings.message, settings.preserveHTML)}));
  21477. $toast
  21478. .addClass(settings.class + ' ' + className.toast)
  21479. .append($content)
  21480. ;
  21481. $toast.css('opacity', settings.opacity);
  21482. if (settings.closeIcon) {
  21483. $close = $('<i/>', {class: className.close + ' ' + (typeof settings.closeIcon === 'string' ? settings.closeIcon : '')});
  21484. if($close.hasClass(className.left)) {
  21485. $toast.prepend($close);
  21486. } else {
  21487. $toast.append($close);
  21488. }
  21489. }
  21490. } else {
  21491. $toast = settings.cloneModule ? $module.clone().removeAttr('id') : $module;
  21492. $close = $toast.find('> i'+module.helpers.toClass(className.close));
  21493. settings.closeIcon = ($close.length > 0);
  21494. }
  21495. if ($toast.hasClass(className.compact)) {
  21496. settings.compact = true;
  21497. }
  21498. if ($toast.hasClass('card')) {
  21499. settings.compact = false;
  21500. }
  21501. $actions = $toast.find('.actions');
  21502. if (module.has.configActions()) {
  21503. if ($actions.length === 0) {
  21504. $actions = $('<div/>', {class: className.actions + ' ' + (settings.classActions || '')}).appendTo($toast);
  21505. }
  21506. if($toast.hasClass('card') && !$actions.hasClass(className.attached)) {
  21507. $actions.addClass(className.extraContent);
  21508. if($actions.hasClass(className.vertical)) {
  21509. $actions.removeClass(className.vertical);
  21510. module.error(error.verticalCard);
  21511. }
  21512. }
  21513. settings.actions.forEach(function (el) {
  21514. var icon = el[fields.icon] ? '<i class="' + module.helpers.deQuote(el[fields.icon]) + ' icon"></i>' : '',
  21515. text = module.helpers.escape(el[fields.text] || '', settings.preserveHTML),
  21516. cls = module.helpers.deQuote(el[fields.class] || ''),
  21517. click = el[fields.click] && $.isFunction(el[fields.click]) ? el[fields.click] : function () {};
  21518. $actions.append($('<button/>', {
  21519. html: icon + text,
  21520. class: className.button + ' ' + cls,
  21521. click: function () {
  21522. if (click.call(element, $module) === false) {
  21523. return;
  21524. }
  21525. module.close();
  21526. }
  21527. }));
  21528. });
  21529. }
  21530. if ($actions && $actions.hasClass(className.vertical)) {
  21531. $toast.addClass(className.vertical);
  21532. }
  21533. if($actions.length > 0 && !$actions.hasClass(className.attached)) {
  21534. if ($actions && (!$actions.hasClass(className.basic) || $actions.hasClass(className.left))) {
  21535. $toast.addClass(className.actions);
  21536. }
  21537. }
  21538. if(settings.displayTime === 'auto'){
  21539. settings.displayTime = Math.max(settings.minDisplayTime, $toast.text().split(" ").length / settings.wordsPerMinute * 60000);
  21540. }
  21541. $toastBox.append($toast);
  21542. if($actions.length > 0 && $actions.hasClass(className.attached)) {
  21543. $actions.addClass(className.buttons);
  21544. $actions.detach();
  21545. $toast.addClass(className.attached);
  21546. if (!$actions.hasClass(className.vertical)) {
  21547. if ($actions.hasClass(className.top)) {
  21548. $toastBox.prepend($actions);
  21549. $toast.addClass(className.bottom);
  21550. } else {
  21551. $toastBox.append($actions);
  21552. $toast.addClass(className.top);
  21553. }
  21554. } else {
  21555. $toast.wrap(
  21556. $('<div/>',{
  21557. class:className.vertical + ' ' +
  21558. className.attached + ' ' +
  21559. (settings.compact ? className.compact : '')
  21560. })
  21561. );
  21562. if($actions.hasClass(className.left)) {
  21563. $toast.addClass(className.left).parent().addClass(className.left).prepend($actions);
  21564. } else {
  21565. $toast.parent().append($actions);
  21566. }
  21567. }
  21568. }
  21569. if($module !== $toast) {
  21570. $module = $toast;
  21571. element = $toast[0];
  21572. }
  21573. if(settings.displayTime > 0) {
  21574. var progressingClass = className.progressing+' '+(settings.pauseOnHover ? className.pausable:'');
  21575. if (!!settings.showProgress) {
  21576. $progress = $('<div/>', {
  21577. class: className.progress + ' ' + (settings.classProgress || settings.class),
  21578. 'data-percent': ''
  21579. });
  21580. if(!settings.classProgress) {
  21581. if ($toast.hasClass('toast') && !$toast.hasClass(className.inverted)) {
  21582. $progress.addClass(className.inverted);
  21583. } else {
  21584. $progress.removeClass(className.inverted);
  21585. }
  21586. }
  21587. $progressBar = $('<div/>', {class: 'bar '+(settings.progressUp ? 'up ' : 'down ')+progressingClass});
  21588. $progress
  21589. .addClass(settings.showProgress)
  21590. .append($progressBar);
  21591. if ($progress.hasClass(className.top)) {
  21592. $toastBox.prepend($progress);
  21593. } else {
  21594. $toastBox.append($progress);
  21595. }
  21596. $progressBar.css('animation-duration', settings.displayTime / 1000 + 's');
  21597. }
  21598. $animationObject = $('<span/>',{class:'wait '+progressingClass});
  21599. $animationObject.css('animation-duration', settings.displayTime / 1000 + 's');
  21600. $animationObject.appendTo($toast);
  21601. }
  21602. if (settings.compact) {
  21603. $toastBox.addClass(className.compact);
  21604. $toast.addClass(className.compact);
  21605. if($progress) {
  21606. $progress.addClass(className.compact);
  21607. }
  21608. }
  21609. if (settings.newestOnTop) {
  21610. $toastBox.prependTo(module.get.container());
  21611. }
  21612. else {
  21613. $toastBox.appendTo(module.get.container());
  21614. }
  21615. }
  21616. },
  21617. bind: {
  21618. events: function() {
  21619. module.debug('Binding events to toast');
  21620. if(settings.closeOnClick || settings.closeIcon) {
  21621. (settings.closeIcon ? $close : $toast)
  21622. .on('click' + eventNamespace, module.event.click)
  21623. ;
  21624. }
  21625. if($animationObject) {
  21626. $animationObject.on('animationend' + eventNamespace, module.close);
  21627. }
  21628. $toastBox
  21629. .on('click' + eventNamespace, selector.approve, module.event.approve)
  21630. .on('click' + eventNamespace, selector.deny, module.event.deny)
  21631. ;
  21632. }
  21633. },
  21634. unbind: {
  21635. events: function() {
  21636. module.debug('Unbinding events to toast');
  21637. if(settings.closeOnClick || settings.closeIcon) {
  21638. (settings.closeIcon ? $close : $toast)
  21639. .off('click' + eventNamespace)
  21640. ;
  21641. }
  21642. if($animationObject) {
  21643. $animationObject.off('animationend' + eventNamespace);
  21644. }
  21645. $toastBox
  21646. .off('click' + eventNamespace)
  21647. ;
  21648. }
  21649. },
  21650. animate: {
  21651. show: function(callback) {
  21652. callback = $.isFunction(callback) ? callback : function(){};
  21653. if(settings.transition && module.can.useElement('transition') && $module.transition('is supported')) {
  21654. module.set.visible();
  21655. $toastBox
  21656. .transition({
  21657. animation : settings.transition.showMethod + ' in',
  21658. queue : false,
  21659. debug : settings.debug,
  21660. verbose : settings.verbose,
  21661. duration : settings.transition.showDuration,
  21662. onComplete : function() {
  21663. callback.call($toastBox, element);
  21664. settings.onVisible.call($toastBox, element);
  21665. }
  21666. })
  21667. ;
  21668. }
  21669. },
  21670. close: function(callback) {
  21671. callback = $.isFunction(callback) ? callback : function(){};
  21672. module.debug('Closing toast');
  21673. if(settings.onHide.call($toastBox, element) === false) {
  21674. module.debug('onHide callback returned false, cancelling toast animation');
  21675. return;
  21676. }
  21677. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  21678. $toastBox
  21679. .transition({
  21680. animation : settings.transition.hideMethod + ' out',
  21681. queue : false,
  21682. duration : settings.transition.hideDuration,
  21683. debug : settings.debug,
  21684. verbose : settings.verbose,
  21685. interval : 50,
  21686. onBeforeHide: function(callback){
  21687. callback = $.isFunction(callback)?callback : function(){};
  21688. if(settings.transition.closeEasing !== ''){
  21689. if($toastBox) {
  21690. $toastBox.css('opacity', 0);
  21691. $toastBox.wrap('<div/>').parent().slideUp(500, settings.transition.closeEasing, function () {
  21692. if ($toastBox) {
  21693. $toastBox.parent().remove();
  21694. callback.call($toastBox);
  21695. }
  21696. });
  21697. }
  21698. } else {
  21699. callback.call($toastBox);
  21700. }
  21701. },
  21702. onComplete : function() {
  21703. callback.call($toastBox, element);
  21704. settings.onHidden.call($toastBox, element);
  21705. module.destroy();
  21706. }
  21707. })
  21708. ;
  21709. }
  21710. else {
  21711. module.error(error.noTransition);
  21712. }
  21713. },
  21714. pause: function() {
  21715. $animationObject.css('animationPlayState','paused');
  21716. if($progressBar) {
  21717. $progressBar.css('animationPlayState', 'paused');
  21718. }
  21719. },
  21720. continue: function() {
  21721. $animationObject.css('animationPlayState','running');
  21722. if($progressBar) {
  21723. $progressBar.css('animationPlayState', 'running');
  21724. }
  21725. }
  21726. },
  21727. has: {
  21728. container: function() {
  21729. module.verbose('Determining if there is already a container');
  21730. return ($context.find(module.helpers.toClass(settings.position) + selector.container).length > 0);
  21731. },
  21732. toast: function(){
  21733. return !!module.get.toast();
  21734. },
  21735. toasts: function(){
  21736. return module.get.toasts().length > 0;
  21737. },
  21738. configActions: function () {
  21739. return Array.isArray(settings.actions) && settings.actions.length > 0;
  21740. }
  21741. },
  21742. get: {
  21743. container: function() {
  21744. return ($context.find(module.helpers.toClass(settings.position) + selector.container)[0]);
  21745. },
  21746. toastBox: function() {
  21747. return $toastBox || null;
  21748. },
  21749. toast: function() {
  21750. return $toast || null;
  21751. },
  21752. toasts: function() {
  21753. return $(module.get.container()).find(selector.box);
  21754. },
  21755. iconClass: function() {
  21756. return typeof settings.showIcon === 'string' ? settings.showIcon : settings.showIcon && settings.icons[settings.class] ? settings.icons[settings.class] : '';
  21757. },
  21758. remainingTime: function() {
  21759. return $animationObject ? $animationObject.css('opacity') * settings.displayTime : 0;
  21760. }
  21761. },
  21762. set: {
  21763. visible: function() {
  21764. $toast.addClass(className.visible);
  21765. }
  21766. },
  21767. remove: {
  21768. visible: function() {
  21769. $toast.removeClass(className.visible);
  21770. }
  21771. },
  21772. event: {
  21773. click: function(event) {
  21774. if($(event.target).closest('a').length === 0) {
  21775. settings.onClick.call($toastBox, element);
  21776. module.close();
  21777. }
  21778. },
  21779. approve: function() {
  21780. if(settings.onApprove.call(element, $module) === false) {
  21781. module.verbose('Approve callback returned false cancelling close');
  21782. return;
  21783. }
  21784. module.close();
  21785. },
  21786. deny: function() {
  21787. if(settings.onDeny.call(element, $module) === false) {
  21788. module.verbose('Deny callback returned false cancelling close');
  21789. return;
  21790. }
  21791. module.close();
  21792. }
  21793. },
  21794. helpers: {
  21795. toClass: function(selector) {
  21796. var
  21797. classes = selector.split(' '),
  21798. result = ''
  21799. ;
  21800. classes.forEach(function (element) {
  21801. result += '.' + element;
  21802. });
  21803. return result;
  21804. },
  21805. deQuote: function(string) {
  21806. return String(string).replace(/"/g,"");
  21807. },
  21808. escape: function(string, preserveHTML) {
  21809. if (preserveHTML){
  21810. return string;
  21811. }
  21812. var
  21813. badChars = /[<>"'`]/g,
  21814. shouldEscape = /[&<>"'`]/,
  21815. escape = {
  21816. "<": "&lt;",
  21817. ">": "&gt;",
  21818. '"': "&quot;",
  21819. "'": "&#x27;",
  21820. "`": "&#x60;"
  21821. },
  21822. escapedChar = function(chr) {
  21823. return escape[chr];
  21824. }
  21825. ;
  21826. if(shouldEscape.test(string)) {
  21827. string = string.replace(/&(?![a-z0-9#]{1,6};)/, "&amp;");
  21828. return string.replace(badChars, escapedChar);
  21829. }
  21830. return string;
  21831. }
  21832. },
  21833. can: {
  21834. useElement: function(element){
  21835. if ($.fn[element] !== undefined) {
  21836. return true;
  21837. }
  21838. module.error(error.noElement.replace('{element}',element));
  21839. return false;
  21840. }
  21841. },
  21842. setting: function(name, value) {
  21843. module.debug('Changing setting', name, value);
  21844. if( $.isPlainObject(name) ) {
  21845. $.extend(true, settings, name);
  21846. }
  21847. else if(value !== undefined) {
  21848. if($.isPlainObject(settings[name])) {
  21849. $.extend(true, settings[name], value);
  21850. }
  21851. else {
  21852. settings[name] = value;
  21853. }
  21854. }
  21855. else {
  21856. return settings[name];
  21857. }
  21858. },
  21859. internal: function(name, value) {
  21860. if( $.isPlainObject(name) ) {
  21861. $.extend(true, module, name);
  21862. }
  21863. else if(value !== undefined) {
  21864. module[name] = value;
  21865. }
  21866. else {
  21867. return module[name];
  21868. }
  21869. },
  21870. debug: function() {
  21871. if(!settings.silent && settings.debug) {
  21872. if(settings.performance) {
  21873. module.performance.log(arguments);
  21874. }
  21875. else {
  21876. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21877. module.debug.apply(console, arguments);
  21878. }
  21879. }
  21880. },
  21881. verbose: function() {
  21882. if(!settings.silent && settings.verbose && settings.debug) {
  21883. if(settings.performance) {
  21884. module.performance.log(arguments);
  21885. }
  21886. else {
  21887. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21888. module.verbose.apply(console, arguments);
  21889. }
  21890. }
  21891. },
  21892. error: function() {
  21893. if(!settings.silent) {
  21894. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  21895. module.error.apply(console, arguments);
  21896. }
  21897. },
  21898. performance: {
  21899. log: function(message) {
  21900. var
  21901. currentTime,
  21902. executionTime,
  21903. previousTime
  21904. ;
  21905. if(settings.performance) {
  21906. currentTime = new Date().getTime();
  21907. previousTime = time || currentTime;
  21908. executionTime = currentTime - previousTime;
  21909. time = currentTime;
  21910. performance.push({
  21911. 'Name' : message[0],
  21912. 'Arguments' : [].slice.call(message, 1) || '',
  21913. 'Element' : element,
  21914. 'Execution Time' : executionTime
  21915. });
  21916. }
  21917. clearTimeout(module.performance.timer);
  21918. module.performance.timer = setTimeout(module.performance.display, 500);
  21919. },
  21920. display: function() {
  21921. var
  21922. title = settings.name + ':',
  21923. totalTime = 0
  21924. ;
  21925. time = false;
  21926. clearTimeout(module.performance.timer);
  21927. $.each(performance, function(index, data) {
  21928. totalTime += data['Execution Time'];
  21929. });
  21930. title += ' ' + totalTime + 'ms';
  21931. if(moduleSelector) {
  21932. title += ' \'' + moduleSelector + '\'';
  21933. }
  21934. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  21935. console.groupCollapsed(title);
  21936. if(console.table) {
  21937. console.table(performance);
  21938. }
  21939. else {
  21940. $.each(performance, function(index, data) {
  21941. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  21942. });
  21943. }
  21944. console.groupEnd();
  21945. }
  21946. performance = [];
  21947. }
  21948. },
  21949. invoke: function(query, passedArguments, context) {
  21950. var
  21951. object = instance,
  21952. maxDepth,
  21953. found,
  21954. response
  21955. ;
  21956. passedArguments = passedArguments || queryArguments;
  21957. context = element || context;
  21958. if(typeof query == 'string' && object !== undefined) {
  21959. query = query.split(/[\. ]/);
  21960. maxDepth = query.length - 1;
  21961. $.each(query, function(depth, value) {
  21962. var camelCaseValue = (depth != maxDepth)
  21963. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  21964. : query
  21965. ;
  21966. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  21967. object = object[camelCaseValue];
  21968. }
  21969. else if( object[camelCaseValue] !== undefined ) {
  21970. found = object[camelCaseValue];
  21971. return false;
  21972. }
  21973. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  21974. object = object[value];
  21975. }
  21976. else if( object[value] !== undefined ) {
  21977. found = object[value];
  21978. return false;
  21979. }
  21980. else {
  21981. module.error(error.method, query);
  21982. return false;
  21983. }
  21984. });
  21985. }
  21986. if ( $.isFunction( found ) ) {
  21987. response = found.apply(context, passedArguments);
  21988. }
  21989. else if(found !== undefined) {
  21990. response = found;
  21991. }
  21992. if(Array.isArray(returnedValue)) {
  21993. returnedValue.push(response);
  21994. }
  21995. else if(returnedValue !== undefined) {
  21996. returnedValue = [returnedValue, response];
  21997. }
  21998. else if(response !== undefined) {
  21999. returnedValue = response;
  22000. }
  22001. return found;
  22002. }
  22003. };
  22004. if(methodInvoked) {
  22005. if(instance === undefined) {
  22006. module.initialize();
  22007. }
  22008. module.invoke(query);
  22009. }
  22010. else {
  22011. if(instance !== undefined) {
  22012. instance.invoke('destroy');
  22013. }
  22014. module.initialize();
  22015. returnedValue = $module;
  22016. }
  22017. })
  22018. ;
  22019. return (returnedValue !== undefined)
  22020. ? returnedValue
  22021. : this
  22022. ;
  22023. };
  22024. $.fn.toast.settings = {
  22025. name : 'Toast',
  22026. namespace : 'toast',
  22027. silent : false,
  22028. debug : false,
  22029. verbose : false,
  22030. performance : true,
  22031. context : 'body',
  22032. position : 'top right',
  22033. class : 'neutral',
  22034. classProgress : false,
  22035. classActions : false,
  22036. classImage : 'mini',
  22037. title : '',
  22038. message : '',
  22039. displayTime : 3000, // set to zero to require manually dismissal, otherwise hides on its own
  22040. minDisplayTime : 1000, // minimum displaytime in case displayTime is set to 'auto'
  22041. wordsPerMinute : 120,
  22042. showIcon : false,
  22043. newestOnTop : false,
  22044. showProgress : false,
  22045. pauseOnHover : true,
  22046. progressUp : false, //if true, the bar will start at 0% and increase to 100%
  22047. opacity : 1,
  22048. compact : true,
  22049. closeIcon : false,
  22050. closeOnClick : true,
  22051. cloneModule : true,
  22052. actions : false,
  22053. preserveHTML : true,
  22054. showImage : false,
  22055. // transition settings
  22056. transition : {
  22057. showMethod : 'scale',
  22058. showDuration : 500,
  22059. hideMethod : 'scale',
  22060. hideDuration : 500,
  22061. closeEasing : 'easeOutCubic' //Set to empty string to stack the closed toast area immediately (old behaviour)
  22062. },
  22063. error: {
  22064. method : 'The method you called is not defined.',
  22065. noElement : 'This module requires ui {element}',
  22066. verticalCard : 'Vertical but not attached actions are not supported for card layout'
  22067. },
  22068. className : {
  22069. container : 'ui toast-container',
  22070. box : 'floating toast-box',
  22071. progress : 'ui attached active progress',
  22072. toast : 'ui toast',
  22073. icon : 'centered icon',
  22074. visible : 'visible',
  22075. content : 'content',
  22076. title : 'ui header',
  22077. actions : 'actions',
  22078. extraContent : 'extra content',
  22079. button : 'ui button',
  22080. buttons : 'ui buttons',
  22081. close : 'close icon',
  22082. image : 'ui image',
  22083. vertical : 'vertical',
  22084. attached : 'attached',
  22085. inverted : 'inverted',
  22086. compact : 'compact',
  22087. pausable : 'pausable',
  22088. progressing : 'progressing',
  22089. top : 'top',
  22090. bottom : 'bottom',
  22091. left : 'left',
  22092. basic : 'basic',
  22093. unclickable : 'unclickable'
  22094. },
  22095. icons : {
  22096. info : 'info',
  22097. success : 'checkmark',
  22098. warning : 'warning',
  22099. error : 'times'
  22100. },
  22101. selector : {
  22102. container : '.ui.toast-container',
  22103. box : '.toast-box',
  22104. toast : '.ui.toast',
  22105. input : 'input:not([type="hidden"]), textarea, select, button, .ui.button, ui.dropdown',
  22106. approve : '.actions .positive, .actions .approve, .actions .ok',
  22107. deny : '.actions .negative, .actions .deny, .actions .cancel'
  22108. },
  22109. fields : {
  22110. class : 'class',
  22111. text : 'text',
  22112. icon : 'icon',
  22113. click : 'click'
  22114. },
  22115. // callbacks
  22116. onShow : function(){},
  22117. onVisible : function(){},
  22118. onClick : function(){},
  22119. onHide : function(){},
  22120. onHidden : function(){},
  22121. onRemove : function(){},
  22122. onApprove : function(){},
  22123. onDeny : function(){}
  22124. };
  22125. $.extend( $.easing, {
  22126. easeOutBounce: function (x, t, b, c, d) {
  22127. if ((t/=d) < (1/2.75)) {
  22128. return c*(7.5625*t*t) + b;
  22129. } else if (t < (2/2.75)) {
  22130. return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
  22131. } else if (t < (2.5/2.75)) {
  22132. return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
  22133. } else {
  22134. return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
  22135. }
  22136. },
  22137. easeOutCubic: function (t) {
  22138. return (--t)*t*t+1;
  22139. }
  22140. });
  22141. })( jQuery, window, document );
  22142. /*!
  22143. * # Fomantic-UI - Transition
  22144. * http://github.com/fomantic/Fomantic-UI/
  22145. *
  22146. *
  22147. * Released under the MIT license
  22148. * http://opensource.org/licenses/MIT
  22149. *
  22150. */
  22151. ;(function ($, window, document, undefined) {
  22152. 'use strict';
  22153. $.isFunction = $.isFunction || function(obj) {
  22154. return typeof obj === "function" && typeof obj.nodeType !== "number";
  22155. };
  22156. window = (typeof window != 'undefined' && window.Math == Math)
  22157. ? window
  22158. : (typeof self != 'undefined' && self.Math == Math)
  22159. ? self
  22160. : Function('return this')()
  22161. ;
  22162. $.fn.transition = function() {
  22163. var
  22164. $allModules = $(this),
  22165. moduleSelector = $allModules.selector || '',
  22166. time = new Date().getTime(),
  22167. performance = [],
  22168. moduleArguments = arguments,
  22169. query = moduleArguments[0],
  22170. queryArguments = [].slice.call(arguments, 1),
  22171. methodInvoked = (typeof query === 'string'),
  22172. returnedValue
  22173. ;
  22174. $allModules
  22175. .each(function(index) {
  22176. var
  22177. $module = $(this),
  22178. element = this,
  22179. // set at run time
  22180. settings,
  22181. instance,
  22182. error,
  22183. className,
  22184. metadata,
  22185. animationEnd,
  22186. moduleNamespace,
  22187. eventNamespace,
  22188. module
  22189. ;
  22190. module = {
  22191. initialize: function() {
  22192. // get full settings
  22193. settings = module.get.settings.apply(element, moduleArguments);
  22194. // shorthand
  22195. className = settings.className;
  22196. error = settings.error;
  22197. metadata = settings.metadata;
  22198. // define namespace
  22199. eventNamespace = '.' + settings.namespace;
  22200. moduleNamespace = 'module-' + settings.namespace;
  22201. instance = $module.data(moduleNamespace) || module;
  22202. // get vendor specific events
  22203. animationEnd = module.get.animationEndEvent();
  22204. if(methodInvoked) {
  22205. methodInvoked = module.invoke(query);
  22206. }
  22207. // method not invoked, lets run an animation
  22208. if(methodInvoked === false) {
  22209. module.verbose('Converted arguments into settings object', settings);
  22210. if(settings.interval) {
  22211. module.delay(settings.animate);
  22212. }
  22213. else {
  22214. module.animate();
  22215. }
  22216. module.instantiate();
  22217. }
  22218. },
  22219. instantiate: function() {
  22220. module.verbose('Storing instance of module', module);
  22221. instance = module;
  22222. $module
  22223. .data(moduleNamespace, instance)
  22224. ;
  22225. },
  22226. destroy: function() {
  22227. module.verbose('Destroying previous module for', element);
  22228. $module
  22229. .removeData(moduleNamespace)
  22230. ;
  22231. },
  22232. refresh: function() {
  22233. module.verbose('Refreshing display type on next animation');
  22234. delete module.displayType;
  22235. },
  22236. forceRepaint: function() {
  22237. module.verbose('Forcing element repaint');
  22238. var
  22239. $parentElement = $module.parent(),
  22240. $nextElement = $module.next()
  22241. ;
  22242. if($nextElement.length === 0) {
  22243. $module.detach().appendTo($parentElement);
  22244. }
  22245. else {
  22246. $module.detach().insertBefore($nextElement);
  22247. }
  22248. },
  22249. repaint: function() {
  22250. module.verbose('Repainting element');
  22251. var
  22252. fakeAssignment = element.offsetWidth
  22253. ;
  22254. },
  22255. delay: function(interval) {
  22256. var
  22257. direction = module.get.animationDirection(),
  22258. shouldReverse,
  22259. delay
  22260. ;
  22261. if(!direction) {
  22262. direction = module.can.transition()
  22263. ? module.get.direction()
  22264. : 'static'
  22265. ;
  22266. }
  22267. interval = (interval !== undefined)
  22268. ? interval
  22269. : settings.interval
  22270. ;
  22271. shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
  22272. delay = (shouldReverse || settings.reverse == true)
  22273. ? ($allModules.length - index) * settings.interval
  22274. : index * settings.interval
  22275. ;
  22276. module.debug('Delaying animation by', delay);
  22277. setTimeout(module.animate, delay);
  22278. },
  22279. animate: function(overrideSettings) {
  22280. settings = overrideSettings || settings;
  22281. if(!module.is.supported()) {
  22282. module.error(error.support);
  22283. return false;
  22284. }
  22285. module.debug('Preparing animation', settings.animation);
  22286. if(module.is.animating()) {
  22287. if(settings.queue) {
  22288. if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
  22289. module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
  22290. }
  22291. else {
  22292. module.queue(settings.animation);
  22293. }
  22294. return false;
  22295. }
  22296. else if(!settings.allowRepeats && module.is.occurring()) {
  22297. module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
  22298. return false;
  22299. }
  22300. else {
  22301. module.debug('New animation started, completing previous early', settings.animation);
  22302. instance.complete();
  22303. }
  22304. }
  22305. if( module.can.animate() ) {
  22306. module.set.animating(settings.animation);
  22307. }
  22308. else {
  22309. module.error(error.noAnimation, settings.animation, element);
  22310. }
  22311. },
  22312. reset: function() {
  22313. module.debug('Resetting animation to beginning conditions');
  22314. module.remove.animationCallbacks();
  22315. module.restore.conditions();
  22316. module.remove.animating();
  22317. },
  22318. queue: function(animation) {
  22319. module.debug('Queueing animation of', animation);
  22320. module.queuing = true;
  22321. $module
  22322. .one(animationEnd + '.queue' + eventNamespace, function() {
  22323. module.queuing = false;
  22324. module.repaint();
  22325. module.animate.apply(this, settings);
  22326. })
  22327. ;
  22328. },
  22329. complete: function (event) {
  22330. if(event && event.target === element) {
  22331. event.stopPropagation();
  22332. }
  22333. module.debug('Animation complete', settings.animation);
  22334. module.remove.completeCallback();
  22335. module.remove.failSafe();
  22336. if(!module.is.looping()) {
  22337. if( module.is.outward() ) {
  22338. module.verbose('Animation is outward, hiding element');
  22339. module.restore.conditions();
  22340. module.hide();
  22341. }
  22342. else if( module.is.inward() ) {
  22343. module.verbose('Animation is outward, showing element');
  22344. module.restore.conditions();
  22345. module.show();
  22346. }
  22347. else {
  22348. module.verbose('Static animation completed');
  22349. module.restore.conditions();
  22350. settings.onComplete.call(element);
  22351. }
  22352. }
  22353. },
  22354. force: {
  22355. visible: function() {
  22356. var
  22357. style = $module.attr('style'),
  22358. userStyle = module.get.userStyle(style),
  22359. displayType = module.get.displayType(),
  22360. overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
  22361. inlineDisplay = $module[0].style.display,
  22362. mustStayHidden = !displayType || (inlineDisplay === 'none' && settings.skipInlineHidden) || $module[0].tagName.match(/(script|link|style)/i)
  22363. ;
  22364. if (mustStayHidden){
  22365. module.remove.transition();
  22366. return false;
  22367. }
  22368. module.verbose('Overriding default display to show element', displayType);
  22369. $module
  22370. .attr('style', overrideStyle)
  22371. ;
  22372. return true;
  22373. },
  22374. hidden: function() {
  22375. var
  22376. style = $module.attr('style'),
  22377. currentDisplay = $module.css('display'),
  22378. emptyStyle = (style === undefined || style === '')
  22379. ;
  22380. if(currentDisplay !== 'none' && !module.is.hidden()) {
  22381. module.verbose('Overriding default display to hide element');
  22382. $module
  22383. .css('display', 'none')
  22384. ;
  22385. }
  22386. else if(emptyStyle) {
  22387. $module
  22388. .removeAttr('style')
  22389. ;
  22390. }
  22391. }
  22392. },
  22393. has: {
  22394. direction: function(animation) {
  22395. var
  22396. hasDirection = false
  22397. ;
  22398. animation = animation || settings.animation;
  22399. if(typeof animation === 'string') {
  22400. animation = animation.split(' ');
  22401. $.each(animation, function(index, word){
  22402. if(word === className.inward || word === className.outward) {
  22403. hasDirection = true;
  22404. }
  22405. });
  22406. }
  22407. return hasDirection;
  22408. },
  22409. inlineDisplay: function() {
  22410. var
  22411. style = $module.attr('style') || ''
  22412. ;
  22413. return Array.isArray(style.match(/display.*?;/, ''));
  22414. }
  22415. },
  22416. set: {
  22417. animating: function(animation) {
  22418. // remove previous callbacks
  22419. module.remove.completeCallback();
  22420. // determine exact animation
  22421. animation = animation || settings.animation;
  22422. var animationClass = module.get.animationClass(animation);
  22423. // save animation class in cache to restore class names
  22424. module.save.animation(animationClass);
  22425. if(module.force.visible()) {
  22426. module.remove.hidden();
  22427. module.remove.direction();
  22428. module.start.animation(animationClass);
  22429. }
  22430. },
  22431. duration: function(animationName, duration) {
  22432. duration = duration || settings.duration;
  22433. duration = (typeof duration == 'number')
  22434. ? duration + 'ms'
  22435. : duration
  22436. ;
  22437. if(duration || duration === 0) {
  22438. module.verbose('Setting animation duration', duration);
  22439. $module
  22440. .css({
  22441. 'animation-duration': duration
  22442. })
  22443. ;
  22444. }
  22445. },
  22446. direction: function(direction) {
  22447. direction = direction || module.get.direction();
  22448. if(direction == className.inward) {
  22449. module.set.inward();
  22450. }
  22451. else {
  22452. module.set.outward();
  22453. }
  22454. },
  22455. looping: function() {
  22456. module.debug('Transition set to loop');
  22457. $module
  22458. .addClass(className.looping)
  22459. ;
  22460. },
  22461. hidden: function() {
  22462. $module
  22463. .addClass(className.transition)
  22464. .addClass(className.hidden)
  22465. ;
  22466. },
  22467. inward: function() {
  22468. module.debug('Setting direction to inward');
  22469. $module
  22470. .removeClass(className.outward)
  22471. .addClass(className.inward)
  22472. ;
  22473. },
  22474. outward: function() {
  22475. module.debug('Setting direction to outward');
  22476. $module
  22477. .removeClass(className.inward)
  22478. .addClass(className.outward)
  22479. ;
  22480. },
  22481. visible: function() {
  22482. $module
  22483. .addClass(className.transition)
  22484. .addClass(className.visible)
  22485. ;
  22486. }
  22487. },
  22488. start: {
  22489. animation: function(animationClass) {
  22490. animationClass = animationClass || module.get.animationClass();
  22491. module.debug('Starting tween', animationClass);
  22492. $module
  22493. .addClass(animationClass)
  22494. .one(animationEnd + '.complete' + eventNamespace, module.complete)
  22495. ;
  22496. if(settings.useFailSafe) {
  22497. module.add.failSafe();
  22498. }
  22499. module.set.duration(settings.duration);
  22500. settings.onStart.call(element);
  22501. }
  22502. },
  22503. save: {
  22504. animation: function(animation) {
  22505. if(!module.cache) {
  22506. module.cache = {};
  22507. }
  22508. module.cache.animation = animation;
  22509. },
  22510. displayType: function(displayType) {
  22511. if(displayType !== 'none') {
  22512. $module.data(metadata.displayType, displayType);
  22513. }
  22514. },
  22515. transitionExists: function(animation, exists) {
  22516. $.fn.transition.exists[animation] = exists;
  22517. module.verbose('Saving existence of transition', animation, exists);
  22518. }
  22519. },
  22520. restore: {
  22521. conditions: function() {
  22522. var
  22523. animation = module.get.currentAnimation()
  22524. ;
  22525. if(animation) {
  22526. $module
  22527. .removeClass(animation)
  22528. ;
  22529. module.verbose('Removing animation class', module.cache);
  22530. }
  22531. module.remove.duration();
  22532. }
  22533. },
  22534. add: {
  22535. failSafe: function() {
  22536. var
  22537. duration = module.get.duration()
  22538. ;
  22539. module.timer = setTimeout(function() {
  22540. $module.triggerHandler(animationEnd);
  22541. }, duration + settings.failSafeDelay);
  22542. module.verbose('Adding fail safe timer', module.timer);
  22543. }
  22544. },
  22545. remove: {
  22546. animating: function() {
  22547. $module.removeClass(className.animating);
  22548. },
  22549. animationCallbacks: function() {
  22550. module.remove.queueCallback();
  22551. module.remove.completeCallback();
  22552. },
  22553. queueCallback: function() {
  22554. $module.off('.queue' + eventNamespace);
  22555. },
  22556. completeCallback: function() {
  22557. $module.off('.complete' + eventNamespace);
  22558. },
  22559. display: function() {
  22560. $module.css('display', '');
  22561. },
  22562. direction: function() {
  22563. $module
  22564. .removeClass(className.inward)
  22565. .removeClass(className.outward)
  22566. ;
  22567. },
  22568. duration: function() {
  22569. $module
  22570. .css('animation-duration', '')
  22571. ;
  22572. },
  22573. failSafe: function() {
  22574. module.verbose('Removing fail safe timer', module.timer);
  22575. if(module.timer) {
  22576. clearTimeout(module.timer);
  22577. }
  22578. },
  22579. hidden: function() {
  22580. $module.removeClass(className.hidden);
  22581. },
  22582. visible: function() {
  22583. $module.removeClass(className.visible);
  22584. },
  22585. looping: function() {
  22586. module.debug('Transitions are no longer looping');
  22587. if( module.is.looping() ) {
  22588. module.reset();
  22589. $module
  22590. .removeClass(className.looping)
  22591. ;
  22592. }
  22593. },
  22594. transition: function() {
  22595. $module
  22596. .removeClass(className.transition)
  22597. .removeClass(className.visible)
  22598. .removeClass(className.hidden)
  22599. ;
  22600. }
  22601. },
  22602. get: {
  22603. settings: function(animation, duration, onComplete) {
  22604. // single settings object
  22605. if(typeof animation == 'object') {
  22606. return $.extend(true, {}, $.fn.transition.settings, animation);
  22607. }
  22608. // all arguments provided
  22609. else if(typeof onComplete == 'function') {
  22610. return $.extend({}, $.fn.transition.settings, {
  22611. animation : animation,
  22612. onComplete : onComplete,
  22613. duration : duration
  22614. });
  22615. }
  22616. // only duration provided
  22617. else if(typeof duration == 'string' || typeof duration == 'number') {
  22618. return $.extend({}, $.fn.transition.settings, {
  22619. animation : animation,
  22620. duration : duration
  22621. });
  22622. }
  22623. // duration is actually settings object
  22624. else if(typeof duration == 'object') {
  22625. return $.extend({}, $.fn.transition.settings, duration, {
  22626. animation : animation
  22627. });
  22628. }
  22629. // duration is actually callback
  22630. else if(typeof duration == 'function') {
  22631. return $.extend({}, $.fn.transition.settings, {
  22632. animation : animation,
  22633. onComplete : duration
  22634. });
  22635. }
  22636. // only animation provided
  22637. else {
  22638. return $.extend({}, $.fn.transition.settings, {
  22639. animation : animation
  22640. });
  22641. }
  22642. },
  22643. animationClass: function(animation) {
  22644. var
  22645. animationClass = animation || settings.animation,
  22646. directionClass = (module.can.transition() && !module.has.direction())
  22647. ? module.get.direction() + ' '
  22648. : ''
  22649. ;
  22650. return className.animating + ' '
  22651. + className.transition + ' '
  22652. + directionClass
  22653. + animationClass
  22654. ;
  22655. },
  22656. currentAnimation: function() {
  22657. return (module.cache && module.cache.animation !== undefined)
  22658. ? module.cache.animation
  22659. : false
  22660. ;
  22661. },
  22662. currentDirection: function() {
  22663. return module.is.inward()
  22664. ? className.inward
  22665. : className.outward
  22666. ;
  22667. },
  22668. direction: function() {
  22669. return module.is.hidden() || !module.is.visible()
  22670. ? className.inward
  22671. : className.outward
  22672. ;
  22673. },
  22674. animationDirection: function(animation) {
  22675. var
  22676. direction
  22677. ;
  22678. animation = animation || settings.animation;
  22679. if(typeof animation === 'string') {
  22680. animation = animation.split(' ');
  22681. // search animation name for out/in class
  22682. $.each(animation, function(index, word){
  22683. if(word === className.inward) {
  22684. direction = className.inward;
  22685. }
  22686. else if(word === className.outward) {
  22687. direction = className.outward;
  22688. }
  22689. });
  22690. }
  22691. // return found direction
  22692. if(direction) {
  22693. return direction;
  22694. }
  22695. return false;
  22696. },
  22697. duration: function(duration) {
  22698. duration = duration || settings.duration;
  22699. if(duration === false) {
  22700. duration = $module.css('animation-duration') || 0;
  22701. }
  22702. return (typeof duration === 'string')
  22703. ? (duration.indexOf('ms') > -1)
  22704. ? parseFloat(duration)
  22705. : parseFloat(duration) * 1000
  22706. : duration
  22707. ;
  22708. },
  22709. displayType: function(shouldDetermine) {
  22710. shouldDetermine = (shouldDetermine !== undefined)
  22711. ? shouldDetermine
  22712. : true
  22713. ;
  22714. if(settings.displayType) {
  22715. return settings.displayType;
  22716. }
  22717. if(shouldDetermine && $module.data(metadata.displayType) === undefined) {
  22718. var currentDisplay = $module.css('display');
  22719. if(currentDisplay === '' || currentDisplay === 'none'){
  22720. // create fake element to determine display state
  22721. module.can.transition(true);
  22722. } else {
  22723. module.save.displayType(currentDisplay);
  22724. }
  22725. }
  22726. return $module.data(metadata.displayType);
  22727. },
  22728. userStyle: function(style) {
  22729. style = style || $module.attr('style') || '';
  22730. return style.replace(/display.*?;/, '');
  22731. },
  22732. transitionExists: function(animation) {
  22733. return $.fn.transition.exists[animation];
  22734. },
  22735. animationStartEvent: function() {
  22736. var
  22737. element = document.createElement('div'),
  22738. animations = {
  22739. 'animation' :'animationstart',
  22740. 'OAnimation' :'oAnimationStart',
  22741. 'MozAnimation' :'mozAnimationStart',
  22742. 'WebkitAnimation' :'webkitAnimationStart'
  22743. },
  22744. animation
  22745. ;
  22746. for(animation in animations){
  22747. if( element.style[animation] !== undefined ){
  22748. return animations[animation];
  22749. }
  22750. }
  22751. return false;
  22752. },
  22753. animationEndEvent: function() {
  22754. var
  22755. element = document.createElement('div'),
  22756. animations = {
  22757. 'animation' :'animationend',
  22758. 'OAnimation' :'oAnimationEnd',
  22759. 'MozAnimation' :'mozAnimationEnd',
  22760. 'WebkitAnimation' :'webkitAnimationEnd'
  22761. },
  22762. animation
  22763. ;
  22764. for(animation in animations){
  22765. if( element.style[animation] !== undefined ){
  22766. return animations[animation];
  22767. }
  22768. }
  22769. return false;
  22770. }
  22771. },
  22772. can: {
  22773. transition: function(forced) {
  22774. var
  22775. animation = settings.animation,
  22776. transitionExists = module.get.transitionExists(animation),
  22777. displayType = module.get.displayType(false),
  22778. elementClass,
  22779. tagName,
  22780. $clone,
  22781. currentAnimation,
  22782. inAnimation,
  22783. directionExists
  22784. ;
  22785. if( transitionExists === undefined || forced) {
  22786. module.verbose('Determining whether animation exists');
  22787. elementClass = $module.attr('class');
  22788. tagName = $module.prop('tagName');
  22789. $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
  22790. currentAnimation = $clone
  22791. .addClass(animation)
  22792. .removeClass(className.inward)
  22793. .removeClass(className.outward)
  22794. .addClass(className.animating)
  22795. .addClass(className.transition)
  22796. .css('animationName')
  22797. ;
  22798. inAnimation = $clone
  22799. .addClass(className.inward)
  22800. .css('animationName')
  22801. ;
  22802. if(!displayType) {
  22803. displayType = $clone
  22804. .attr('class', elementClass)
  22805. .removeAttr('style')
  22806. .removeClass(className.hidden)
  22807. .removeClass(className.visible)
  22808. .show()
  22809. .css('display')
  22810. ;
  22811. module.verbose('Determining final display state', displayType);
  22812. module.save.displayType(displayType);
  22813. }
  22814. $clone.remove();
  22815. if(currentAnimation != inAnimation) {
  22816. module.debug('Direction exists for animation', animation);
  22817. directionExists = true;
  22818. }
  22819. else if(currentAnimation == 'none' || !currentAnimation) {
  22820. module.debug('No animation defined in css', animation);
  22821. return;
  22822. }
  22823. else {
  22824. module.debug('Static animation found', animation, displayType);
  22825. directionExists = false;
  22826. }
  22827. module.save.transitionExists(animation, directionExists);
  22828. }
  22829. return (transitionExists !== undefined)
  22830. ? transitionExists
  22831. : directionExists
  22832. ;
  22833. },
  22834. animate: function() {
  22835. // can transition does not return a value if animation does not exist
  22836. return (module.can.transition() !== undefined);
  22837. }
  22838. },
  22839. is: {
  22840. animating: function() {
  22841. return $module.hasClass(className.animating);
  22842. },
  22843. inward: function() {
  22844. return $module.hasClass(className.inward);
  22845. },
  22846. outward: function() {
  22847. return $module.hasClass(className.outward);
  22848. },
  22849. looping: function() {
  22850. return $module.hasClass(className.looping);
  22851. },
  22852. occurring: function(animation) {
  22853. animation = animation || settings.animation;
  22854. animation = '.' + animation.replace(' ', '.');
  22855. return ( $module.filter(animation).length > 0 );
  22856. },
  22857. visible: function() {
  22858. return $module.is(':visible');
  22859. },
  22860. hidden: function() {
  22861. return $module.css('visibility') === 'hidden';
  22862. },
  22863. supported: function() {
  22864. return(animationEnd !== false);
  22865. }
  22866. },
  22867. hide: function() {
  22868. module.verbose('Hiding element');
  22869. if( module.is.animating() ) {
  22870. module.reset();
  22871. }
  22872. element.blur(); // IE will trigger focus change if element is not blurred before hiding
  22873. module.remove.display();
  22874. module.remove.visible();
  22875. if($.isFunction(settings.onBeforeHide)){
  22876. settings.onBeforeHide.call(element,function(){
  22877. module.hideNow();
  22878. });
  22879. } else {
  22880. module.hideNow();
  22881. }
  22882. },
  22883. hideNow: function() {
  22884. module.set.hidden();
  22885. module.force.hidden();
  22886. settings.onHide.call(element);
  22887. settings.onComplete.call(element);
  22888. // module.repaint();
  22889. },
  22890. show: function(display) {
  22891. module.verbose('Showing element', display);
  22892. if(module.force.visible()) {
  22893. module.remove.hidden();
  22894. module.set.visible();
  22895. settings.onShow.call(element);
  22896. settings.onComplete.call(element);
  22897. // module.repaint();
  22898. }
  22899. },
  22900. toggle: function() {
  22901. if( module.is.visible() ) {
  22902. module.hide();
  22903. }
  22904. else {
  22905. module.show();
  22906. }
  22907. },
  22908. stop: function() {
  22909. module.debug('Stopping current animation');
  22910. $module.triggerHandler(animationEnd);
  22911. },
  22912. stopAll: function() {
  22913. module.debug('Stopping all animation');
  22914. module.remove.queueCallback();
  22915. $module.triggerHandler(animationEnd);
  22916. },
  22917. clear: {
  22918. queue: function() {
  22919. module.debug('Clearing animation queue');
  22920. module.remove.queueCallback();
  22921. }
  22922. },
  22923. enable: function() {
  22924. module.verbose('Starting animation');
  22925. $module.removeClass(className.disabled);
  22926. },
  22927. disable: function() {
  22928. module.debug('Stopping animation');
  22929. $module.addClass(className.disabled);
  22930. },
  22931. setting: function(name, value) {
  22932. module.debug('Changing setting', name, value);
  22933. if( $.isPlainObject(name) ) {
  22934. $.extend(true, settings, name);
  22935. }
  22936. else if(value !== undefined) {
  22937. if($.isPlainObject(settings[name])) {
  22938. $.extend(true, settings[name], value);
  22939. }
  22940. else {
  22941. settings[name] = value;
  22942. }
  22943. }
  22944. else {
  22945. return settings[name];
  22946. }
  22947. },
  22948. internal: function(name, value) {
  22949. if( $.isPlainObject(name) ) {
  22950. $.extend(true, module, name);
  22951. }
  22952. else if(value !== undefined) {
  22953. module[name] = value;
  22954. }
  22955. else {
  22956. return module[name];
  22957. }
  22958. },
  22959. debug: function() {
  22960. if(!settings.silent && settings.debug) {
  22961. if(settings.performance) {
  22962. module.performance.log(arguments);
  22963. }
  22964. else {
  22965. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  22966. module.debug.apply(console, arguments);
  22967. }
  22968. }
  22969. },
  22970. verbose: function() {
  22971. if(!settings.silent && settings.verbose && settings.debug) {
  22972. if(settings.performance) {
  22973. module.performance.log(arguments);
  22974. }
  22975. else {
  22976. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  22977. module.verbose.apply(console, arguments);
  22978. }
  22979. }
  22980. },
  22981. error: function() {
  22982. if(!settings.silent) {
  22983. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  22984. module.error.apply(console, arguments);
  22985. }
  22986. },
  22987. performance: {
  22988. log: function(message) {
  22989. var
  22990. currentTime,
  22991. executionTime,
  22992. previousTime
  22993. ;
  22994. if(settings.performance) {
  22995. currentTime = new Date().getTime();
  22996. previousTime = time || currentTime;
  22997. executionTime = currentTime - previousTime;
  22998. time = currentTime;
  22999. performance.push({
  23000. 'Name' : message[0],
  23001. 'Arguments' : [].slice.call(message, 1) || '',
  23002. 'Element' : element,
  23003. 'Execution Time' : executionTime
  23004. });
  23005. }
  23006. clearTimeout(module.performance.timer);
  23007. module.performance.timer = setTimeout(module.performance.display, 500);
  23008. },
  23009. display: function() {
  23010. var
  23011. title = settings.name + ':',
  23012. totalTime = 0
  23013. ;
  23014. time = false;
  23015. clearTimeout(module.performance.timer);
  23016. $.each(performance, function(index, data) {
  23017. totalTime += data['Execution Time'];
  23018. });
  23019. title += ' ' + totalTime + 'ms';
  23020. if(moduleSelector) {
  23021. title += ' \'' + moduleSelector + '\'';
  23022. }
  23023. if($allModules.length > 1) {
  23024. title += ' ' + '(' + $allModules.length + ')';
  23025. }
  23026. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  23027. console.groupCollapsed(title);
  23028. if(console.table) {
  23029. console.table(performance);
  23030. }
  23031. else {
  23032. $.each(performance, function(index, data) {
  23033. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  23034. });
  23035. }
  23036. console.groupEnd();
  23037. }
  23038. performance = [];
  23039. }
  23040. },
  23041. // modified for transition to return invoke success
  23042. invoke: function(query, passedArguments, context) {
  23043. var
  23044. object = instance,
  23045. maxDepth,
  23046. found,
  23047. response
  23048. ;
  23049. passedArguments = passedArguments || queryArguments;
  23050. context = element || context;
  23051. if(typeof query == 'string' && object !== undefined) {
  23052. query = query.split(/[\. ]/);
  23053. maxDepth = query.length - 1;
  23054. $.each(query, function(depth, value) {
  23055. var camelCaseValue = (depth != maxDepth)
  23056. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  23057. : query
  23058. ;
  23059. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  23060. object = object[camelCaseValue];
  23061. }
  23062. else if( object[camelCaseValue] !== undefined ) {
  23063. found = object[camelCaseValue];
  23064. return false;
  23065. }
  23066. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  23067. object = object[value];
  23068. }
  23069. else if( object[value] !== undefined ) {
  23070. found = object[value];
  23071. return false;
  23072. }
  23073. else {
  23074. return false;
  23075. }
  23076. });
  23077. }
  23078. if ( $.isFunction( found ) ) {
  23079. response = found.apply(context, passedArguments);
  23080. }
  23081. else if(found !== undefined) {
  23082. response = found;
  23083. }
  23084. if(Array.isArray(returnedValue)) {
  23085. returnedValue.push(response);
  23086. }
  23087. else if(returnedValue !== undefined) {
  23088. returnedValue = [returnedValue, response];
  23089. }
  23090. else if(response !== undefined) {
  23091. returnedValue = response;
  23092. }
  23093. return (found !== undefined)
  23094. ? found
  23095. : false
  23096. ;
  23097. }
  23098. };
  23099. module.initialize();
  23100. })
  23101. ;
  23102. return (returnedValue !== undefined)
  23103. ? returnedValue
  23104. : this
  23105. ;
  23106. };
  23107. // Records if CSS transition is available
  23108. $.fn.transition.exists = {};
  23109. $.fn.transition.settings = {
  23110. // module info
  23111. name : 'Transition',
  23112. // hide all output from this component regardless of other settings
  23113. silent : false,
  23114. // debug content outputted to console
  23115. debug : false,
  23116. // verbose debug output
  23117. verbose : false,
  23118. // performance data output
  23119. performance : true,
  23120. // event namespace
  23121. namespace : 'transition',
  23122. // delay between animations in group
  23123. interval : 0,
  23124. // whether group animations should be reversed
  23125. reverse : 'auto',
  23126. // animation callback event
  23127. onStart : function() {},
  23128. onComplete : function() {},
  23129. onShow : function() {},
  23130. onHide : function() {},
  23131. // whether timeout should be used to ensure callback fires in cases animationend does not
  23132. useFailSafe : true,
  23133. // delay in ms for fail safe
  23134. failSafeDelay : 100,
  23135. // whether EXACT animation can occur twice in a row
  23136. allowRepeats : false,
  23137. // Override final display type on visible
  23138. displayType : false,
  23139. // animation duration
  23140. animation : 'fade',
  23141. duration : false,
  23142. // new animations will occur after previous ones
  23143. queue : true,
  23144. // whether initially inline hidden objects should be skipped for transition
  23145. skipInlineHidden: false,
  23146. metadata : {
  23147. displayType: 'display'
  23148. },
  23149. className : {
  23150. animating : 'animating',
  23151. disabled : 'disabled',
  23152. hidden : 'hidden',
  23153. inward : 'in',
  23154. loading : 'loading',
  23155. looping : 'looping',
  23156. outward : 'out',
  23157. transition : 'transition',
  23158. visible : 'visible'
  23159. },
  23160. // possible errors
  23161. error: {
  23162. noAnimation : 'Element is no longer attached to DOM. Unable to animate. Use silent setting to surpress this warning in production.',
  23163. repeated : 'That animation is already occurring, cancelling repeated animation',
  23164. method : 'The method you called is not defined',
  23165. support : 'This browser does not support CSS animations'
  23166. }
  23167. };
  23168. })( jQuery, window, document );
  23169. /*!
  23170. * # Fomantic-UI - API
  23171. * http://github.com/fomantic/Fomantic-UI/
  23172. *
  23173. *
  23174. * Released under the MIT license
  23175. * http://opensource.org/licenses/MIT
  23176. *
  23177. */
  23178. ;(function ($, window, document, undefined) {
  23179. 'use strict';
  23180. $.isWindow = $.isWindow || function(obj) {
  23181. return obj != null && obj === obj.window;
  23182. };
  23183. window = (typeof window != 'undefined' && window.Math == Math)
  23184. ? window
  23185. : (typeof self != 'undefined' && self.Math == Math)
  23186. ? self
  23187. : Function('return this')()
  23188. ;
  23189. $.api = $.fn.api = function(parameters) {
  23190. var
  23191. // use window context if none specified
  23192. $allModules = $.isFunction(this)
  23193. ? $(window)
  23194. : $(this),
  23195. moduleSelector = $allModules.selector || '',
  23196. time = new Date().getTime(),
  23197. performance = [],
  23198. query = arguments[0],
  23199. methodInvoked = (typeof query == 'string'),
  23200. queryArguments = [].slice.call(arguments, 1),
  23201. returnedValue
  23202. ;
  23203. $allModules
  23204. .each(function() {
  23205. var
  23206. settings = ( $.isPlainObject(parameters) )
  23207. ? $.extend(true, {}, $.fn.api.settings, parameters)
  23208. : $.extend({}, $.fn.api.settings),
  23209. // internal aliases
  23210. namespace = settings.namespace,
  23211. metadata = settings.metadata,
  23212. selector = settings.selector,
  23213. error = settings.error,
  23214. className = settings.className,
  23215. // define namespaces for modules
  23216. eventNamespace = '.' + namespace,
  23217. moduleNamespace = 'module-' + namespace,
  23218. // element that creates request
  23219. $module = $(this),
  23220. $form = $module.closest(selector.form),
  23221. // context used for state
  23222. $context = (settings.stateContext)
  23223. ? $(settings.stateContext)
  23224. : $module,
  23225. // request details
  23226. ajaxSettings,
  23227. requestSettings,
  23228. url,
  23229. data,
  23230. requestStartTime,
  23231. // standard module
  23232. element = this,
  23233. context = $context[0],
  23234. instance = $module.data(moduleNamespace),
  23235. module
  23236. ;
  23237. module = {
  23238. initialize: function() {
  23239. if(!methodInvoked) {
  23240. module.bind.events();
  23241. }
  23242. module.instantiate();
  23243. },
  23244. instantiate: function() {
  23245. module.verbose('Storing instance of module', module);
  23246. instance = module;
  23247. $module
  23248. .data(moduleNamespace, instance)
  23249. ;
  23250. },
  23251. destroy: function() {
  23252. module.verbose('Destroying previous module for', element);
  23253. $module
  23254. .removeData(moduleNamespace)
  23255. .off(eventNamespace)
  23256. ;
  23257. },
  23258. bind: {
  23259. events: function() {
  23260. var
  23261. triggerEvent = module.get.event()
  23262. ;
  23263. if( triggerEvent ) {
  23264. module.verbose('Attaching API events to element', triggerEvent);
  23265. $module
  23266. .on(triggerEvent + eventNamespace, module.event.trigger)
  23267. ;
  23268. }
  23269. else if(settings.on == 'now') {
  23270. module.debug('Querying API endpoint immediately');
  23271. module.query();
  23272. }
  23273. }
  23274. },
  23275. decode: {
  23276. json: function(response) {
  23277. if(response !== undefined && typeof response == 'string') {
  23278. try {
  23279. response = JSON.parse(response);
  23280. }
  23281. catch(e) {
  23282. // isnt json string
  23283. }
  23284. }
  23285. return response;
  23286. }
  23287. },
  23288. read: {
  23289. cachedResponse: function(url) {
  23290. var
  23291. response
  23292. ;
  23293. if(window.Storage === undefined) {
  23294. module.error(error.noStorage);
  23295. return;
  23296. }
  23297. response = sessionStorage.getItem(url);
  23298. module.debug('Using cached response', url, response);
  23299. response = module.decode.json(response);
  23300. return response;
  23301. }
  23302. },
  23303. write: {
  23304. cachedResponse: function(url, response) {
  23305. if(response && response === '') {
  23306. module.debug('Response empty, not caching', response);
  23307. return;
  23308. }
  23309. if(window.Storage === undefined) {
  23310. module.error(error.noStorage);
  23311. return;
  23312. }
  23313. if( $.isPlainObject(response) ) {
  23314. response = JSON.stringify(response);
  23315. }
  23316. sessionStorage.setItem(url, response);
  23317. module.verbose('Storing cached response for url', url, response);
  23318. }
  23319. },
  23320. query: function() {
  23321. if(module.is.disabled()) {
  23322. module.debug('Element is disabled API request aborted');
  23323. return;
  23324. }
  23325. if(module.is.loading()) {
  23326. if(settings.interruptRequests) {
  23327. module.debug('Interrupting previous request');
  23328. module.abort();
  23329. }
  23330. else {
  23331. module.debug('Cancelling request, previous request is still pending');
  23332. return;
  23333. }
  23334. }
  23335. // pass element metadata to url (value, text)
  23336. if(settings.defaultData) {
  23337. $.extend(true, settings.urlData, module.get.defaultData());
  23338. }
  23339. // Add form content
  23340. if(settings.serializeForm) {
  23341. settings.data = module.add.formData(settings.data);
  23342. }
  23343. // call beforesend and get any settings changes
  23344. requestSettings = module.get.settings();
  23345. // check if before send cancelled request
  23346. if(requestSettings === false) {
  23347. module.cancelled = true;
  23348. module.error(error.beforeSend);
  23349. return;
  23350. }
  23351. else {
  23352. module.cancelled = false;
  23353. }
  23354. // get url
  23355. url = module.get.templatedURL();
  23356. if(!url && !module.is.mocked()) {
  23357. module.error(error.missingURL);
  23358. return;
  23359. }
  23360. // replace variables
  23361. url = module.add.urlData( url );
  23362. // missing url parameters
  23363. if( !url && !module.is.mocked()) {
  23364. return;
  23365. }
  23366. requestSettings.url = settings.base + url;
  23367. // look for jQuery ajax parameters in settings
  23368. ajaxSettings = $.extend(true, {}, settings, {
  23369. type : settings.method || settings.type,
  23370. data : data,
  23371. url : settings.base + url,
  23372. beforeSend : settings.beforeXHR,
  23373. success : function() {},
  23374. failure : function() {},
  23375. complete : function() {}
  23376. });
  23377. module.debug('Querying URL', ajaxSettings.url);
  23378. module.verbose('Using AJAX settings', ajaxSettings);
  23379. if(settings.cache === 'local' && module.read.cachedResponse(url)) {
  23380. module.debug('Response returned from local cache');
  23381. module.request = module.create.request();
  23382. module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
  23383. return;
  23384. }
  23385. if( !settings.throttle ) {
  23386. module.debug('Sending request', data, ajaxSettings.method);
  23387. module.send.request();
  23388. }
  23389. else {
  23390. if(!settings.throttleFirstRequest && !module.timer) {
  23391. module.debug('Sending request', data, ajaxSettings.method);
  23392. module.send.request();
  23393. module.timer = setTimeout(function(){}, settings.throttle);
  23394. }
  23395. else {
  23396. module.debug('Throttling request', settings.throttle);
  23397. clearTimeout(module.timer);
  23398. module.timer = setTimeout(function() {
  23399. if(module.timer) {
  23400. delete module.timer;
  23401. }
  23402. module.debug('Sending throttled request', data, ajaxSettings.method);
  23403. module.send.request();
  23404. }, settings.throttle);
  23405. }
  23406. }
  23407. },
  23408. should: {
  23409. removeError: function() {
  23410. return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
  23411. }
  23412. },
  23413. is: {
  23414. disabled: function() {
  23415. return ($module.filter(selector.disabled).length > 0);
  23416. },
  23417. expectingJSON: function() {
  23418. return settings.dataType === 'json' || settings.dataType === 'jsonp';
  23419. },
  23420. form: function() {
  23421. return $module.is('form') || $context.is('form');
  23422. },
  23423. mocked: function() {
  23424. return (settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync);
  23425. },
  23426. input: function() {
  23427. return $module.is('input');
  23428. },
  23429. loading: function() {
  23430. return (module.request)
  23431. ? (module.request.state() == 'pending')
  23432. : false
  23433. ;
  23434. },
  23435. abortedRequest: function(xhr) {
  23436. if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
  23437. module.verbose('XHR request determined to be aborted');
  23438. return true;
  23439. }
  23440. else {
  23441. module.verbose('XHR request was not aborted');
  23442. return false;
  23443. }
  23444. },
  23445. validResponse: function(response) {
  23446. if( (!module.is.expectingJSON()) || !$.isFunction(settings.successTest) ) {
  23447. module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
  23448. return true;
  23449. }
  23450. module.debug('Checking JSON returned success', settings.successTest, response);
  23451. if( settings.successTest(response) ) {
  23452. module.debug('Response passed success test', response);
  23453. return true;
  23454. }
  23455. else {
  23456. module.debug('Response failed success test', response);
  23457. return false;
  23458. }
  23459. }
  23460. },
  23461. was: {
  23462. cancelled: function() {
  23463. return (module.cancelled || false);
  23464. },
  23465. succesful: function() {
  23466. module.verbose('This behavior will be deleted due to typo. Use "was successful" instead.');
  23467. return module.was.successful();
  23468. },
  23469. successful: function() {
  23470. return (module.request && module.request.state() == 'resolved');
  23471. },
  23472. failure: function() {
  23473. return (module.request && module.request.state() == 'rejected');
  23474. },
  23475. complete: function() {
  23476. return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
  23477. }
  23478. },
  23479. add: {
  23480. urlData: function(url, urlData) {
  23481. var
  23482. requiredVariables,
  23483. optionalVariables
  23484. ;
  23485. if(url) {
  23486. requiredVariables = url.match(settings.regExp.required);
  23487. optionalVariables = url.match(settings.regExp.optional);
  23488. urlData = urlData || settings.urlData;
  23489. if(requiredVariables) {
  23490. module.debug('Looking for required URL variables', requiredVariables);
  23491. $.each(requiredVariables, function(index, templatedString) {
  23492. var
  23493. // allow legacy {$var} style
  23494. variable = (templatedString.indexOf('$') !== -1)
  23495. ? templatedString.substr(2, templatedString.length - 3)
  23496. : templatedString.substr(1, templatedString.length - 2),
  23497. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  23498. ? urlData[variable]
  23499. : ($module.data(variable) !== undefined)
  23500. ? $module.data(variable)
  23501. : ($context.data(variable) !== undefined)
  23502. ? $context.data(variable)
  23503. : urlData[variable]
  23504. ;
  23505. // remove value
  23506. if(value === undefined) {
  23507. module.error(error.requiredParameter, variable, url);
  23508. url = false;
  23509. return false;
  23510. }
  23511. else {
  23512. module.verbose('Found required variable', variable, value);
  23513. value = (settings.encodeParameters)
  23514. ? module.get.urlEncodedValue(value)
  23515. : value
  23516. ;
  23517. url = url.replace(templatedString, value);
  23518. }
  23519. });
  23520. }
  23521. if(optionalVariables) {
  23522. module.debug('Looking for optional URL variables', requiredVariables);
  23523. $.each(optionalVariables, function(index, templatedString) {
  23524. var
  23525. // allow legacy {/$var} style
  23526. variable = (templatedString.indexOf('$') !== -1)
  23527. ? templatedString.substr(3, templatedString.length - 4)
  23528. : templatedString.substr(2, templatedString.length - 3),
  23529. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  23530. ? urlData[variable]
  23531. : ($module.data(variable) !== undefined)
  23532. ? $module.data(variable)
  23533. : ($context.data(variable) !== undefined)
  23534. ? $context.data(variable)
  23535. : urlData[variable]
  23536. ;
  23537. // optional replacement
  23538. if(value !== undefined) {
  23539. module.verbose('Optional variable Found', variable, value);
  23540. url = url.replace(templatedString, value);
  23541. }
  23542. else {
  23543. module.verbose('Optional variable not found', variable);
  23544. // remove preceding slash if set
  23545. if(url.indexOf('/' + templatedString) !== -1) {
  23546. url = url.replace('/' + templatedString, '');
  23547. }
  23548. else {
  23549. url = url.replace(templatedString, '');
  23550. }
  23551. }
  23552. });
  23553. }
  23554. }
  23555. return url;
  23556. },
  23557. formData: function(data) {
  23558. var
  23559. canSerialize = ($.fn.serializeObject !== undefined),
  23560. formData = (canSerialize)
  23561. ? $form.serializeObject()
  23562. : $form.serialize(),
  23563. hasOtherData
  23564. ;
  23565. data = data || settings.data;
  23566. hasOtherData = $.isPlainObject(data);
  23567. if(hasOtherData) {
  23568. if(canSerialize) {
  23569. module.debug('Extending existing data with form data', data, formData);
  23570. data = $.extend(true, {}, data, formData);
  23571. }
  23572. else {
  23573. module.error(error.missingSerialize);
  23574. module.debug('Cant extend data. Replacing data with form data', data, formData);
  23575. data = formData;
  23576. }
  23577. }
  23578. else {
  23579. module.debug('Adding form data', formData);
  23580. data = formData;
  23581. }
  23582. return data;
  23583. }
  23584. },
  23585. send: {
  23586. request: function() {
  23587. module.set.loading();
  23588. module.request = module.create.request();
  23589. if( module.is.mocked() ) {
  23590. module.mockedXHR = module.create.mockedXHR();
  23591. }
  23592. else {
  23593. module.xhr = module.create.xhr();
  23594. }
  23595. settings.onRequest.call(context, module.request, module.xhr);
  23596. }
  23597. },
  23598. event: {
  23599. trigger: function(event) {
  23600. module.query();
  23601. if(event.type == 'submit' || event.type == 'click') {
  23602. event.preventDefault();
  23603. }
  23604. },
  23605. xhr: {
  23606. always: function() {
  23607. // nothing special
  23608. },
  23609. done: function(response, textStatus, xhr) {
  23610. var
  23611. context = this,
  23612. elapsedTime = (new Date().getTime() - requestStartTime),
  23613. timeLeft = (settings.loadingDuration - elapsedTime),
  23614. translatedResponse = ( $.isFunction(settings.onResponse) )
  23615. ? module.is.expectingJSON() && !settings.rawResponse
  23616. ? settings.onResponse.call(context, $.extend(true, {}, response))
  23617. : settings.onResponse.call(context, response)
  23618. : false
  23619. ;
  23620. timeLeft = (timeLeft > 0)
  23621. ? timeLeft
  23622. : 0
  23623. ;
  23624. if(translatedResponse) {
  23625. module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
  23626. response = translatedResponse;
  23627. }
  23628. if(timeLeft > 0) {
  23629. module.debug('Response completed early delaying state change by', timeLeft);
  23630. }
  23631. setTimeout(function() {
  23632. if( module.is.validResponse(response) ) {
  23633. module.request.resolveWith(context, [response, xhr]);
  23634. }
  23635. else {
  23636. module.request.rejectWith(context, [xhr, 'invalid']);
  23637. }
  23638. }, timeLeft);
  23639. },
  23640. fail: function(xhr, status, httpMessage) {
  23641. var
  23642. context = this,
  23643. elapsedTime = (new Date().getTime() - requestStartTime),
  23644. timeLeft = (settings.loadingDuration - elapsedTime)
  23645. ;
  23646. timeLeft = (timeLeft > 0)
  23647. ? timeLeft
  23648. : 0
  23649. ;
  23650. if(timeLeft > 0) {
  23651. module.debug('Response completed early delaying state change by', timeLeft);
  23652. }
  23653. setTimeout(function() {
  23654. if( module.is.abortedRequest(xhr) ) {
  23655. module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
  23656. }
  23657. else {
  23658. module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
  23659. }
  23660. }, timeLeft);
  23661. }
  23662. },
  23663. request: {
  23664. done: function(response, xhr) {
  23665. module.debug('Successful API Response', response);
  23666. if(settings.cache === 'local' && url) {
  23667. module.write.cachedResponse(url, response);
  23668. module.debug('Saving server response locally', module.cache);
  23669. }
  23670. settings.onSuccess.call(context, response, $module, xhr);
  23671. },
  23672. complete: function(firstParameter, secondParameter) {
  23673. var
  23674. xhr,
  23675. response
  23676. ;
  23677. // have to guess callback parameters based on request success
  23678. if( module.was.successful() ) {
  23679. response = firstParameter;
  23680. xhr = secondParameter;
  23681. }
  23682. else {
  23683. xhr = firstParameter;
  23684. response = module.get.responseFromXHR(xhr);
  23685. }
  23686. module.remove.loading();
  23687. settings.onComplete.call(context, response, $module, xhr);
  23688. },
  23689. fail: function(xhr, status, httpMessage) {
  23690. var
  23691. // pull response from xhr if available
  23692. response = module.get.responseFromXHR(xhr),
  23693. errorMessage = module.get.errorFromRequest(response, status, httpMessage)
  23694. ;
  23695. if(status == 'aborted') {
  23696. module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
  23697. settings.onAbort.call(context, status, $module, xhr);
  23698. return true;
  23699. }
  23700. else if(status == 'invalid') {
  23701. module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
  23702. }
  23703. else if(status == 'error') {
  23704. if(xhr !== undefined) {
  23705. module.debug('XHR produced a server error', status, httpMessage);
  23706. // make sure we have an error to display to console
  23707. if( (xhr.status < 200 || xhr.status >= 300) && httpMessage !== undefined && httpMessage !== '') {
  23708. module.error(error.statusMessage + httpMessage, ajaxSettings.url);
  23709. }
  23710. settings.onError.call(context, errorMessage, $module, xhr);
  23711. }
  23712. }
  23713. if(settings.errorDuration && status !== 'aborted') {
  23714. module.debug('Adding error state');
  23715. module.set.error();
  23716. if( module.should.removeError() ) {
  23717. setTimeout(module.remove.error, settings.errorDuration);
  23718. }
  23719. }
  23720. module.debug('API Request failed', errorMessage, xhr);
  23721. settings.onFailure.call(context, response, $module, xhr);
  23722. }
  23723. }
  23724. },
  23725. create: {
  23726. request: function() {
  23727. // api request promise
  23728. return $.Deferred()
  23729. .always(module.event.request.complete)
  23730. .done(module.event.request.done)
  23731. .fail(module.event.request.fail)
  23732. ;
  23733. },
  23734. mockedXHR: function () {
  23735. var
  23736. // xhr does not simulate these properties of xhr but must return them
  23737. textStatus = false,
  23738. status = false,
  23739. httpMessage = false,
  23740. responder = settings.mockResponse || settings.response,
  23741. asyncResponder = settings.mockResponseAsync || settings.responseAsync,
  23742. asyncCallback,
  23743. response,
  23744. mockedXHR
  23745. ;
  23746. mockedXHR = $.Deferred()
  23747. .always(module.event.xhr.complete)
  23748. .done(module.event.xhr.done)
  23749. .fail(module.event.xhr.fail)
  23750. ;
  23751. if(responder) {
  23752. if( $.isFunction(responder) ) {
  23753. module.debug('Using specified synchronous callback', responder);
  23754. response = responder.call(context, requestSettings);
  23755. }
  23756. else {
  23757. module.debug('Using settings specified response', responder);
  23758. response = responder;
  23759. }
  23760. // simulating response
  23761. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  23762. }
  23763. else if( $.isFunction(asyncResponder) ) {
  23764. asyncCallback = function(response) {
  23765. module.debug('Async callback returned response', response);
  23766. if(response) {
  23767. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  23768. }
  23769. else {
  23770. mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
  23771. }
  23772. };
  23773. module.debug('Using specified async response callback', asyncResponder);
  23774. asyncResponder.call(context, requestSettings, asyncCallback);
  23775. }
  23776. return mockedXHR;
  23777. },
  23778. xhr: function() {
  23779. var
  23780. xhr
  23781. ;
  23782. // ajax request promise
  23783. xhr = $.ajax(ajaxSettings)
  23784. .always(module.event.xhr.always)
  23785. .done(module.event.xhr.done)
  23786. .fail(module.event.xhr.fail)
  23787. ;
  23788. module.verbose('Created server request', xhr, ajaxSettings);
  23789. return xhr;
  23790. }
  23791. },
  23792. set: {
  23793. error: function() {
  23794. module.verbose('Adding error state to element', $context);
  23795. $context.addClass(className.error);
  23796. },
  23797. loading: function() {
  23798. module.verbose('Adding loading state to element', $context);
  23799. $context.addClass(className.loading);
  23800. requestStartTime = new Date().getTime();
  23801. }
  23802. },
  23803. remove: {
  23804. error: function() {
  23805. module.verbose('Removing error state from element', $context);
  23806. $context.removeClass(className.error);
  23807. },
  23808. loading: function() {
  23809. module.verbose('Removing loading state from element', $context);
  23810. $context.removeClass(className.loading);
  23811. }
  23812. },
  23813. get: {
  23814. responseFromXHR: function(xhr) {
  23815. return $.isPlainObject(xhr)
  23816. ? (module.is.expectingJSON())
  23817. ? module.decode.json(xhr.responseText)
  23818. : xhr.responseText
  23819. : false
  23820. ;
  23821. },
  23822. errorFromRequest: function(response, status, httpMessage) {
  23823. return ($.isPlainObject(response) && response.error !== undefined)
  23824. ? response.error // use json error message
  23825. : (settings.error[status] !== undefined) // use server error message
  23826. ? settings.error[status]
  23827. : httpMessage
  23828. ;
  23829. },
  23830. request: function() {
  23831. return module.request || false;
  23832. },
  23833. xhr: function() {
  23834. return module.xhr || false;
  23835. },
  23836. settings: function() {
  23837. var
  23838. runSettings
  23839. ;
  23840. runSettings = settings.beforeSend.call($module, settings);
  23841. if(runSettings) {
  23842. if(runSettings.success !== undefined) {
  23843. module.debug('Legacy success callback detected', runSettings);
  23844. module.error(error.legacyParameters, runSettings.success);
  23845. runSettings.onSuccess = runSettings.success;
  23846. }
  23847. if(runSettings.failure !== undefined) {
  23848. module.debug('Legacy failure callback detected', runSettings);
  23849. module.error(error.legacyParameters, runSettings.failure);
  23850. runSettings.onFailure = runSettings.failure;
  23851. }
  23852. if(runSettings.complete !== undefined) {
  23853. module.debug('Legacy complete callback detected', runSettings);
  23854. module.error(error.legacyParameters, runSettings.complete);
  23855. runSettings.onComplete = runSettings.complete;
  23856. }
  23857. }
  23858. if(runSettings === undefined) {
  23859. module.error(error.noReturnedValue);
  23860. }
  23861. if(runSettings === false) {
  23862. return runSettings;
  23863. }
  23864. return (runSettings !== undefined)
  23865. ? $.extend(true, {}, runSettings)
  23866. : $.extend(true, {}, settings)
  23867. ;
  23868. },
  23869. urlEncodedValue: function(value) {
  23870. var
  23871. decodedValue = window.decodeURIComponent(value),
  23872. encodedValue = window.encodeURIComponent(value),
  23873. alreadyEncoded = (decodedValue !== value)
  23874. ;
  23875. if(alreadyEncoded) {
  23876. module.debug('URL value is already encoded, avoiding double encoding', value);
  23877. return value;
  23878. }
  23879. module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
  23880. return encodedValue;
  23881. },
  23882. defaultData: function() {
  23883. var
  23884. data = {}
  23885. ;
  23886. if( !$.isWindow(element) ) {
  23887. if( module.is.input() ) {
  23888. data.value = $module.val();
  23889. }
  23890. else if( module.is.form() ) {
  23891. }
  23892. else {
  23893. data.text = $module.text();
  23894. }
  23895. }
  23896. return data;
  23897. },
  23898. event: function() {
  23899. if( $.isWindow(element) || settings.on == 'now' ) {
  23900. module.debug('API called without element, no events attached');
  23901. return false;
  23902. }
  23903. else if(settings.on == 'auto') {
  23904. if( $module.is('input') ) {
  23905. return (element.oninput !== undefined)
  23906. ? 'input'
  23907. : (element.onpropertychange !== undefined)
  23908. ? 'propertychange'
  23909. : 'keyup'
  23910. ;
  23911. }
  23912. else if( $module.is('form') ) {
  23913. return 'submit';
  23914. }
  23915. else {
  23916. return 'click';
  23917. }
  23918. }
  23919. else {
  23920. return settings.on;
  23921. }
  23922. },
  23923. templatedURL: function(action) {
  23924. action = action || $module.data(metadata.action) || settings.action || false;
  23925. url = $module.data(metadata.url) || settings.url || false;
  23926. if(url) {
  23927. module.debug('Using specified url', url);
  23928. return url;
  23929. }
  23930. if(action) {
  23931. module.debug('Looking up url for action', action, settings.api);
  23932. if(settings.api[action] === undefined && !module.is.mocked()) {
  23933. module.error(error.missingAction, settings.action, settings.api);
  23934. return;
  23935. }
  23936. url = settings.api[action];
  23937. }
  23938. else if( module.is.form() ) {
  23939. url = $module.attr('action') || $context.attr('action') || false;
  23940. module.debug('No url or action specified, defaulting to form action', url);
  23941. }
  23942. return url;
  23943. }
  23944. },
  23945. abort: function() {
  23946. var
  23947. xhr = module.get.xhr()
  23948. ;
  23949. if( xhr && xhr.state() !== 'resolved') {
  23950. module.debug('Cancelling API request');
  23951. xhr.abort();
  23952. }
  23953. },
  23954. // reset state
  23955. reset: function() {
  23956. module.remove.error();
  23957. module.remove.loading();
  23958. },
  23959. setting: function(name, value) {
  23960. module.debug('Changing setting', name, value);
  23961. if( $.isPlainObject(name) ) {
  23962. $.extend(true, settings, name);
  23963. }
  23964. else if(value !== undefined) {
  23965. if($.isPlainObject(settings[name])) {
  23966. $.extend(true, settings[name], value);
  23967. }
  23968. else {
  23969. settings[name] = value;
  23970. }
  23971. }
  23972. else {
  23973. return settings[name];
  23974. }
  23975. },
  23976. internal: function(name, value) {
  23977. if( $.isPlainObject(name) ) {
  23978. $.extend(true, module, name);
  23979. }
  23980. else if(value !== undefined) {
  23981. module[name] = value;
  23982. }
  23983. else {
  23984. return module[name];
  23985. }
  23986. },
  23987. debug: function() {
  23988. if(!settings.silent && settings.debug) {
  23989. if(settings.performance) {
  23990. module.performance.log(arguments);
  23991. }
  23992. else {
  23993. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  23994. module.debug.apply(console, arguments);
  23995. }
  23996. }
  23997. },
  23998. verbose: function() {
  23999. if(!settings.silent && settings.verbose && settings.debug) {
  24000. if(settings.performance) {
  24001. module.performance.log(arguments);
  24002. }
  24003. else {
  24004. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  24005. module.verbose.apply(console, arguments);
  24006. }
  24007. }
  24008. },
  24009. error: function() {
  24010. if(!settings.silent) {
  24011. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  24012. module.error.apply(console, arguments);
  24013. }
  24014. },
  24015. performance: {
  24016. log: function(message) {
  24017. var
  24018. currentTime,
  24019. executionTime,
  24020. previousTime
  24021. ;
  24022. if(settings.performance) {
  24023. currentTime = new Date().getTime();
  24024. previousTime = time || currentTime;
  24025. executionTime = currentTime - previousTime;
  24026. time = currentTime;
  24027. performance.push({
  24028. 'Name' : message[0],
  24029. 'Arguments' : [].slice.call(message, 1) || '',
  24030. //'Element' : element,
  24031. 'Execution Time' : executionTime
  24032. });
  24033. }
  24034. clearTimeout(module.performance.timer);
  24035. module.performance.timer = setTimeout(module.performance.display, 500);
  24036. },
  24037. display: function() {
  24038. var
  24039. title = settings.name + ':',
  24040. totalTime = 0
  24041. ;
  24042. time = false;
  24043. clearTimeout(module.performance.timer);
  24044. $.each(performance, function(index, data) {
  24045. totalTime += data['Execution Time'];
  24046. });
  24047. title += ' ' + totalTime + 'ms';
  24048. if(moduleSelector) {
  24049. title += ' \'' + moduleSelector + '\'';
  24050. }
  24051. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  24052. console.groupCollapsed(title);
  24053. if(console.table) {
  24054. console.table(performance);
  24055. }
  24056. else {
  24057. $.each(performance, function(index, data) {
  24058. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  24059. });
  24060. }
  24061. console.groupEnd();
  24062. }
  24063. performance = [];
  24064. }
  24065. },
  24066. invoke: function(query, passedArguments, context) {
  24067. var
  24068. object = instance,
  24069. maxDepth,
  24070. found,
  24071. response
  24072. ;
  24073. passedArguments = passedArguments || queryArguments;
  24074. context = element || context;
  24075. if(typeof query == 'string' && object !== undefined) {
  24076. query = query.split(/[\. ]/);
  24077. maxDepth = query.length - 1;
  24078. $.each(query, function(depth, value) {
  24079. var camelCaseValue = (depth != maxDepth)
  24080. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  24081. : query
  24082. ;
  24083. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  24084. object = object[camelCaseValue];
  24085. }
  24086. else if( object[camelCaseValue] !== undefined ) {
  24087. found = object[camelCaseValue];
  24088. return false;
  24089. }
  24090. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  24091. object = object[value];
  24092. }
  24093. else if( object[value] !== undefined ) {
  24094. found = object[value];
  24095. return false;
  24096. }
  24097. else {
  24098. module.error(error.method, query);
  24099. return false;
  24100. }
  24101. });
  24102. }
  24103. if ( $.isFunction( found ) ) {
  24104. response = found.apply(context, passedArguments);
  24105. }
  24106. else if(found !== undefined) {
  24107. response = found;
  24108. }
  24109. if(Array.isArray(returnedValue)) {
  24110. returnedValue.push(response);
  24111. }
  24112. else if(returnedValue !== undefined) {
  24113. returnedValue = [returnedValue, response];
  24114. }
  24115. else if(response !== undefined) {
  24116. returnedValue = response;
  24117. }
  24118. return found;
  24119. }
  24120. };
  24121. if(methodInvoked) {
  24122. if(instance === undefined) {
  24123. module.initialize();
  24124. }
  24125. module.invoke(query);
  24126. }
  24127. else {
  24128. if(instance !== undefined) {
  24129. instance.invoke('destroy');
  24130. }
  24131. module.initialize();
  24132. }
  24133. })
  24134. ;
  24135. return (returnedValue !== undefined)
  24136. ? returnedValue
  24137. : this
  24138. ;
  24139. };
  24140. $.api.settings = {
  24141. name : 'API',
  24142. namespace : 'api',
  24143. debug : false,
  24144. verbose : false,
  24145. performance : true,
  24146. // object containing all templates endpoints
  24147. api : {},
  24148. // whether to cache responses
  24149. cache : true,
  24150. // whether new requests should abort previous requests
  24151. interruptRequests : true,
  24152. // event binding
  24153. on : 'auto',
  24154. // context for applying state classes
  24155. stateContext : false,
  24156. // duration for loading state
  24157. loadingDuration : 0,
  24158. // whether to hide errors after a period of time
  24159. hideError : 'auto',
  24160. // duration for error state
  24161. errorDuration : 2000,
  24162. // whether parameters should be encoded with encodeURIComponent
  24163. encodeParameters : true,
  24164. // API action to use
  24165. action : false,
  24166. // templated URL to use
  24167. url : false,
  24168. // base URL to apply to all endpoints
  24169. base : '',
  24170. // data that will
  24171. urlData : {},
  24172. // whether to add default data to url data
  24173. defaultData : true,
  24174. // whether to serialize closest form
  24175. serializeForm : false,
  24176. // how long to wait before request should occur
  24177. throttle : 0,
  24178. // whether to throttle first request or only repeated
  24179. throttleFirstRequest : true,
  24180. // standard ajax settings
  24181. method : 'get',
  24182. data : {},
  24183. dataType : 'json',
  24184. // mock response
  24185. mockResponse : false,
  24186. mockResponseAsync : false,
  24187. // aliases for mock
  24188. response : false,
  24189. responseAsync : false,
  24190. // whether onResponse should work with response value without force converting into an object
  24191. rawResponse : false,
  24192. // callbacks before request
  24193. beforeSend : function(settings) { return settings; },
  24194. beforeXHR : function(xhr) {},
  24195. onRequest : function(promise, xhr) {},
  24196. // after request
  24197. onResponse : false, // function(response) { },
  24198. // response was successful, if JSON passed validation
  24199. onSuccess : function(response, $module) {},
  24200. // request finished without aborting
  24201. onComplete : function(response, $module) {},
  24202. // failed JSON success test
  24203. onFailure : function(response, $module) {},
  24204. // server error
  24205. onError : function(errorMessage, $module) {},
  24206. // request aborted
  24207. onAbort : function(errorMessage, $module) {},
  24208. successTest : false,
  24209. // errors
  24210. error : {
  24211. beforeSend : 'The before send function has aborted the request',
  24212. error : 'There was an error with your request',
  24213. exitConditions : 'API Request Aborted. Exit conditions met',
  24214. JSONParse : 'JSON could not be parsed during error handling',
  24215. legacyParameters : 'You are using legacy API success callback names',
  24216. method : 'The method you called is not defined',
  24217. missingAction : 'API action used but no url was defined',
  24218. missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
  24219. missingURL : 'No URL specified for api event',
  24220. noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
  24221. noStorage : 'Caching responses locally requires session storage',
  24222. parseError : 'There was an error parsing your request',
  24223. requiredParameter : 'Missing a required URL parameter: ',
  24224. statusMessage : 'Server gave an error: ',
  24225. timeout : 'Your request timed out'
  24226. },
  24227. regExp : {
  24228. required : /\{\$*[A-z0-9]+\}/g,
  24229. optional : /\{\/\$*[A-z0-9]+\}/g,
  24230. },
  24231. className: {
  24232. loading : 'loading',
  24233. error : 'error'
  24234. },
  24235. selector: {
  24236. disabled : '.disabled',
  24237. form : 'form'
  24238. },
  24239. metadata: {
  24240. action : 'action',
  24241. url : 'url'
  24242. }
  24243. };
  24244. })( jQuery, window, document );
  24245. /*!
  24246. * # Fomantic-UI - State
  24247. * http://github.com/fomantic/Fomantic-UI/
  24248. *
  24249. *
  24250. * Released under the MIT license
  24251. * http://opensource.org/licenses/MIT
  24252. *
  24253. */
  24254. ;(function ($, window, document, undefined) {
  24255. "use strict";
  24256. $.isFunction = $.isFunction || function(obj) {
  24257. return typeof obj === "function" && typeof obj.nodeType !== "number";
  24258. };
  24259. window = (typeof window != 'undefined' && window.Math == Math)
  24260. ? window
  24261. : (typeof self != 'undefined' && self.Math == Math)
  24262. ? self
  24263. : Function('return this')()
  24264. ;
  24265. $.fn.state = function(parameters) {
  24266. var
  24267. $allModules = $(this),
  24268. moduleSelector = $allModules.selector || '',
  24269. time = new Date().getTime(),
  24270. performance = [],
  24271. query = arguments[0],
  24272. methodInvoked = (typeof query == 'string'),
  24273. queryArguments = [].slice.call(arguments, 1),
  24274. returnedValue
  24275. ;
  24276. $allModules
  24277. .each(function() {
  24278. var
  24279. settings = ( $.isPlainObject(parameters) )
  24280. ? $.extend(true, {}, $.fn.state.settings, parameters)
  24281. : $.extend({}, $.fn.state.settings),
  24282. error = settings.error,
  24283. metadata = settings.metadata,
  24284. className = settings.className,
  24285. namespace = settings.namespace,
  24286. states = settings.states,
  24287. text = settings.text,
  24288. eventNamespace = '.' + namespace,
  24289. moduleNamespace = namespace + '-module',
  24290. $module = $(this),
  24291. element = this,
  24292. instance = $module.data(moduleNamespace),
  24293. module
  24294. ;
  24295. module = {
  24296. initialize: function() {
  24297. module.verbose('Initializing module');
  24298. // allow module to guess desired state based on element
  24299. if(settings.automatic) {
  24300. module.add.defaults();
  24301. }
  24302. // bind events with delegated events
  24303. if(settings.context && moduleSelector !== '') {
  24304. $(settings.context)
  24305. .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text)
  24306. .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text)
  24307. .on(moduleSelector, 'click' + eventNamespace, module.toggle.state)
  24308. ;
  24309. }
  24310. else {
  24311. $module
  24312. .on('mouseenter' + eventNamespace, module.change.text)
  24313. .on('mouseleave' + eventNamespace, module.reset.text)
  24314. .on('click' + eventNamespace, module.toggle.state)
  24315. ;
  24316. }
  24317. module.instantiate();
  24318. },
  24319. instantiate: function() {
  24320. module.verbose('Storing instance of module', module);
  24321. instance = module;
  24322. $module
  24323. .data(moduleNamespace, module)
  24324. ;
  24325. },
  24326. destroy: function() {
  24327. module.verbose('Destroying previous module', instance);
  24328. $module
  24329. .off(eventNamespace)
  24330. .removeData(moduleNamespace)
  24331. ;
  24332. },
  24333. refresh: function() {
  24334. module.verbose('Refreshing selector cache');
  24335. $module = $(element);
  24336. },
  24337. add: {
  24338. defaults: function() {
  24339. var
  24340. userStates = parameters && $.isPlainObject(parameters.states)
  24341. ? parameters.states
  24342. : {}
  24343. ;
  24344. $.each(settings.defaults, function(type, typeStates) {
  24345. if( module.is[type] !== undefined && module.is[type]() ) {
  24346. module.verbose('Adding default states', type, element);
  24347. $.extend(settings.states, typeStates, userStates);
  24348. }
  24349. });
  24350. }
  24351. },
  24352. is: {
  24353. active: function() {
  24354. return $module.hasClass(className.active);
  24355. },
  24356. loading: function() {
  24357. return $module.hasClass(className.loading);
  24358. },
  24359. inactive: function() {
  24360. return !( $module.hasClass(className.active) );
  24361. },
  24362. state: function(state) {
  24363. if(className[state] === undefined) {
  24364. return false;
  24365. }
  24366. return $module.hasClass( className[state] );
  24367. },
  24368. enabled: function() {
  24369. return !( $module.is(settings.filter.active) );
  24370. },
  24371. disabled: function() {
  24372. return ( $module.is(settings.filter.active) );
  24373. },
  24374. textEnabled: function() {
  24375. return !( $module.is(settings.filter.text) );
  24376. },
  24377. // definitions for automatic type detection
  24378. button: function() {
  24379. return $module.is('.button:not(a, .submit)');
  24380. },
  24381. input: function() {
  24382. return $module.is('input');
  24383. },
  24384. progress: function() {
  24385. return $module.is('.ui.progress');
  24386. }
  24387. },
  24388. allow: function(state) {
  24389. module.debug('Now allowing state', state);
  24390. states[state] = true;
  24391. },
  24392. disallow: function(state) {
  24393. module.debug('No longer allowing', state);
  24394. states[state] = false;
  24395. },
  24396. allows: function(state) {
  24397. return states[state] || false;
  24398. },
  24399. enable: function() {
  24400. $module.removeClass(className.disabled);
  24401. },
  24402. disable: function() {
  24403. $module.addClass(className.disabled);
  24404. },
  24405. setState: function(state) {
  24406. if(module.allows(state)) {
  24407. $module.addClass( className[state] );
  24408. }
  24409. },
  24410. removeState: function(state) {
  24411. if(module.allows(state)) {
  24412. $module.removeClass( className[state] );
  24413. }
  24414. },
  24415. toggle: {
  24416. state: function() {
  24417. var
  24418. apiRequest,
  24419. requestCancelled
  24420. ;
  24421. if( module.allows('active') && module.is.enabled() ) {
  24422. module.refresh();
  24423. if($.fn.api !== undefined) {
  24424. apiRequest = $module.api('get request');
  24425. requestCancelled = $module.api('was cancelled');
  24426. if( requestCancelled ) {
  24427. module.debug('API Request cancelled by beforesend');
  24428. settings.activateTest = function(){ return false; };
  24429. settings.deactivateTest = function(){ return false; };
  24430. }
  24431. else if(apiRequest) {
  24432. module.listenTo(apiRequest);
  24433. return;
  24434. }
  24435. }
  24436. module.change.state();
  24437. }
  24438. }
  24439. },
  24440. listenTo: function(apiRequest) {
  24441. module.debug('API request detected, waiting for state signal', apiRequest);
  24442. if(apiRequest) {
  24443. if(text.loading) {
  24444. module.update.text(text.loading);
  24445. }
  24446. $.when(apiRequest)
  24447. .then(function() {
  24448. if(apiRequest.state() == 'resolved') {
  24449. module.debug('API request succeeded');
  24450. settings.activateTest = function(){ return true; };
  24451. settings.deactivateTest = function(){ return true; };
  24452. }
  24453. else {
  24454. module.debug('API request failed');
  24455. settings.activateTest = function(){ return false; };
  24456. settings.deactivateTest = function(){ return false; };
  24457. }
  24458. module.change.state();
  24459. })
  24460. ;
  24461. }
  24462. },
  24463. // checks whether active/inactive state can be given
  24464. change: {
  24465. state: function() {
  24466. module.debug('Determining state change direction');
  24467. // inactive to active change
  24468. if( module.is.inactive() ) {
  24469. module.activate();
  24470. }
  24471. else {
  24472. module.deactivate();
  24473. }
  24474. if(settings.sync) {
  24475. module.sync();
  24476. }
  24477. settings.onChange.call(element);
  24478. },
  24479. text: function() {
  24480. if( module.is.textEnabled() ) {
  24481. if(module.is.disabled() ) {
  24482. module.verbose('Changing text to disabled text', text.hover);
  24483. module.update.text(text.disabled);
  24484. }
  24485. else if( module.is.active() ) {
  24486. if(text.hover) {
  24487. module.verbose('Changing text to hover text', text.hover);
  24488. module.update.text(text.hover);
  24489. }
  24490. else if(text.deactivate) {
  24491. module.verbose('Changing text to deactivating text', text.deactivate);
  24492. module.update.text(text.deactivate);
  24493. }
  24494. }
  24495. else {
  24496. if(text.hover) {
  24497. module.verbose('Changing text to hover text', text.hover);
  24498. module.update.text(text.hover);
  24499. }
  24500. else if(text.activate){
  24501. module.verbose('Changing text to activating text', text.activate);
  24502. module.update.text(text.activate);
  24503. }
  24504. }
  24505. }
  24506. }
  24507. },
  24508. activate: function() {
  24509. if( settings.activateTest.call(element) ) {
  24510. module.debug('Setting state to active');
  24511. $module
  24512. .addClass(className.active)
  24513. ;
  24514. module.update.text(text.active);
  24515. settings.onActivate.call(element);
  24516. }
  24517. },
  24518. deactivate: function() {
  24519. if( settings.deactivateTest.call(element) ) {
  24520. module.debug('Setting state to inactive');
  24521. $module
  24522. .removeClass(className.active)
  24523. ;
  24524. module.update.text(text.inactive);
  24525. settings.onDeactivate.call(element);
  24526. }
  24527. },
  24528. sync: function() {
  24529. module.verbose('Syncing other buttons to current state');
  24530. if( module.is.active() ) {
  24531. $allModules
  24532. .not($module)
  24533. .state('activate');
  24534. }
  24535. else {
  24536. $allModules
  24537. .not($module)
  24538. .state('deactivate')
  24539. ;
  24540. }
  24541. },
  24542. get: {
  24543. text: function() {
  24544. return (settings.selector.text)
  24545. ? $module.find(settings.selector.text).text()
  24546. : $module.html()
  24547. ;
  24548. },
  24549. textFor: function(state) {
  24550. return text[state] || false;
  24551. }
  24552. },
  24553. flash: {
  24554. text: function(text, duration, callback) {
  24555. var
  24556. previousText = module.get.text()
  24557. ;
  24558. module.debug('Flashing text message', text, duration);
  24559. text = text || settings.text.flash;
  24560. duration = duration || settings.flashDuration;
  24561. callback = callback || function() {};
  24562. module.update.text(text);
  24563. setTimeout(function(){
  24564. module.update.text(previousText);
  24565. callback.call(element);
  24566. }, duration);
  24567. }
  24568. },
  24569. reset: {
  24570. // on mouseout sets text to previous value
  24571. text: function() {
  24572. var
  24573. activeText = text.active || $module.data(metadata.storedText),
  24574. inactiveText = text.inactive || $module.data(metadata.storedText)
  24575. ;
  24576. if( module.is.textEnabled() ) {
  24577. if( module.is.active() && activeText) {
  24578. module.verbose('Resetting active text', activeText);
  24579. module.update.text(activeText);
  24580. }
  24581. else if(inactiveText) {
  24582. module.verbose('Resetting inactive text', activeText);
  24583. module.update.text(inactiveText);
  24584. }
  24585. }
  24586. }
  24587. },
  24588. update: {
  24589. text: function(text) {
  24590. var
  24591. currentText = module.get.text()
  24592. ;
  24593. if(text && text !== currentText) {
  24594. module.debug('Updating text', text);
  24595. if(settings.selector.text) {
  24596. $module
  24597. .data(metadata.storedText, text)
  24598. .find(settings.selector.text)
  24599. .text(text)
  24600. ;
  24601. }
  24602. else {
  24603. $module
  24604. .data(metadata.storedText, text)
  24605. .html(text)
  24606. ;
  24607. }
  24608. }
  24609. else {
  24610. module.debug('Text is already set, ignoring update', text);
  24611. }
  24612. }
  24613. },
  24614. setting: function(name, value) {
  24615. module.debug('Changing setting', name, value);
  24616. if( $.isPlainObject(name) ) {
  24617. $.extend(true, settings, name);
  24618. }
  24619. else if(value !== undefined) {
  24620. if($.isPlainObject(settings[name])) {
  24621. $.extend(true, settings[name], value);
  24622. }
  24623. else {
  24624. settings[name] = value;
  24625. }
  24626. }
  24627. else {
  24628. return settings[name];
  24629. }
  24630. },
  24631. internal: function(name, value) {
  24632. if( $.isPlainObject(name) ) {
  24633. $.extend(true, module, name);
  24634. }
  24635. else if(value !== undefined) {
  24636. module[name] = value;
  24637. }
  24638. else {
  24639. return module[name];
  24640. }
  24641. },
  24642. debug: function() {
  24643. if(!settings.silent && settings.debug) {
  24644. if(settings.performance) {
  24645. module.performance.log(arguments);
  24646. }
  24647. else {
  24648. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  24649. module.debug.apply(console, arguments);
  24650. }
  24651. }
  24652. },
  24653. verbose: function() {
  24654. if(!settings.silent && settings.verbose && settings.debug) {
  24655. if(settings.performance) {
  24656. module.performance.log(arguments);
  24657. }
  24658. else {
  24659. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  24660. module.verbose.apply(console, arguments);
  24661. }
  24662. }
  24663. },
  24664. error: function() {
  24665. if(!settings.silent) {
  24666. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  24667. module.error.apply(console, arguments);
  24668. }
  24669. },
  24670. performance: {
  24671. log: function(message) {
  24672. var
  24673. currentTime,
  24674. executionTime,
  24675. previousTime
  24676. ;
  24677. if(settings.performance) {
  24678. currentTime = new Date().getTime();
  24679. previousTime = time || currentTime;
  24680. executionTime = currentTime - previousTime;
  24681. time = currentTime;
  24682. performance.push({
  24683. 'Name' : message[0],
  24684. 'Arguments' : [].slice.call(message, 1) || '',
  24685. 'Element' : element,
  24686. 'Execution Time' : executionTime
  24687. });
  24688. }
  24689. clearTimeout(module.performance.timer);
  24690. module.performance.timer = setTimeout(module.performance.display, 500);
  24691. },
  24692. display: function() {
  24693. var
  24694. title = settings.name + ':',
  24695. totalTime = 0
  24696. ;
  24697. time = false;
  24698. clearTimeout(module.performance.timer);
  24699. $.each(performance, function(index, data) {
  24700. totalTime += data['Execution Time'];
  24701. });
  24702. title += ' ' + totalTime + 'ms';
  24703. if(moduleSelector) {
  24704. title += ' \'' + moduleSelector + '\'';
  24705. }
  24706. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  24707. console.groupCollapsed(title);
  24708. if(console.table) {
  24709. console.table(performance);
  24710. }
  24711. else {
  24712. $.each(performance, function(index, data) {
  24713. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  24714. });
  24715. }
  24716. console.groupEnd();
  24717. }
  24718. performance = [];
  24719. }
  24720. },
  24721. invoke: function(query, passedArguments, context) {
  24722. var
  24723. object = instance,
  24724. maxDepth,
  24725. found,
  24726. response
  24727. ;
  24728. passedArguments = passedArguments || queryArguments;
  24729. context = element || context;
  24730. if(typeof query == 'string' && object !== undefined) {
  24731. query = query.split(/[\. ]/);
  24732. maxDepth = query.length - 1;
  24733. $.each(query, function(depth, value) {
  24734. var camelCaseValue = (depth != maxDepth)
  24735. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  24736. : query
  24737. ;
  24738. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  24739. object = object[camelCaseValue];
  24740. }
  24741. else if( object[camelCaseValue] !== undefined ) {
  24742. found = object[camelCaseValue];
  24743. return false;
  24744. }
  24745. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  24746. object = object[value];
  24747. }
  24748. else if( object[value] !== undefined ) {
  24749. found = object[value];
  24750. return false;
  24751. }
  24752. else {
  24753. module.error(error.method, query);
  24754. return false;
  24755. }
  24756. });
  24757. }
  24758. if ( $.isFunction( found ) ) {
  24759. response = found.apply(context, passedArguments);
  24760. }
  24761. else if(found !== undefined) {
  24762. response = found;
  24763. }
  24764. if(Array.isArray(returnedValue)) {
  24765. returnedValue.push(response);
  24766. }
  24767. else if(returnedValue !== undefined) {
  24768. returnedValue = [returnedValue, response];
  24769. }
  24770. else if(response !== undefined) {
  24771. returnedValue = response;
  24772. }
  24773. return found;
  24774. }
  24775. };
  24776. if(methodInvoked) {
  24777. if(instance === undefined) {
  24778. module.initialize();
  24779. }
  24780. module.invoke(query);
  24781. }
  24782. else {
  24783. if(instance !== undefined) {
  24784. instance.invoke('destroy');
  24785. }
  24786. module.initialize();
  24787. }
  24788. })
  24789. ;
  24790. return (returnedValue !== undefined)
  24791. ? returnedValue
  24792. : this
  24793. ;
  24794. };
  24795. $.fn.state.settings = {
  24796. // module info
  24797. name : 'State',
  24798. // debug output
  24799. debug : false,
  24800. // verbose debug output
  24801. verbose : false,
  24802. // namespace for events
  24803. namespace : 'state',
  24804. // debug data includes performance
  24805. performance : true,
  24806. // callback occurs on state change
  24807. onActivate : function() {},
  24808. onDeactivate : function() {},
  24809. onChange : function() {},
  24810. // state test functions
  24811. activateTest : function() { return true; },
  24812. deactivateTest : function() { return true; },
  24813. // whether to automatically map default states
  24814. automatic : true,
  24815. // activate / deactivate changes all elements instantiated at same time
  24816. sync : false,
  24817. // default flash text duration, used for temporarily changing text of an element
  24818. flashDuration : 1000,
  24819. // selector filter
  24820. filter : {
  24821. text : '.loading, .disabled',
  24822. active : '.disabled'
  24823. },
  24824. context : false,
  24825. // error
  24826. error: {
  24827. beforeSend : 'The before send function has cancelled state change',
  24828. method : 'The method you called is not defined.'
  24829. },
  24830. // metadata
  24831. metadata: {
  24832. promise : 'promise',
  24833. storedText : 'stored-text'
  24834. },
  24835. // change class on state
  24836. className: {
  24837. active : 'active',
  24838. disabled : 'disabled',
  24839. error : 'error',
  24840. loading : 'loading',
  24841. success : 'success',
  24842. warning : 'warning'
  24843. },
  24844. selector: {
  24845. // selector for text node
  24846. text: false
  24847. },
  24848. defaults : {
  24849. input: {
  24850. disabled : true,
  24851. loading : true,
  24852. active : true
  24853. },
  24854. button: {
  24855. disabled : true,
  24856. loading : true,
  24857. active : true,
  24858. },
  24859. progress: {
  24860. active : true,
  24861. success : true,
  24862. warning : true,
  24863. error : true
  24864. }
  24865. },
  24866. states : {
  24867. active : true,
  24868. disabled : true,
  24869. error : true,
  24870. loading : true,
  24871. success : true,
  24872. warning : true
  24873. },
  24874. text : {
  24875. disabled : false,
  24876. flash : false,
  24877. hover : false,
  24878. active : false,
  24879. inactive : false,
  24880. activate : false,
  24881. deactivate : false
  24882. }
  24883. };
  24884. })( jQuery, window, document );
  24885. /*!
  24886. * # Fomantic-UI - Visibility
  24887. * http://github.com/fomantic/Fomantic-UI/
  24888. *
  24889. *
  24890. * Released under the MIT license
  24891. * http://opensource.org/licenses/MIT
  24892. *
  24893. */
  24894. ;(function ($, window, document, undefined) {
  24895. 'use strict';
  24896. $.isFunction = $.isFunction || function(obj) {
  24897. return typeof obj === "function" && typeof obj.nodeType !== "number";
  24898. };
  24899. window = (typeof window != 'undefined' && window.Math == Math)
  24900. ? window
  24901. : (typeof self != 'undefined' && self.Math == Math)
  24902. ? self
  24903. : Function('return this')()
  24904. ;
  24905. $.fn.visibility = function(parameters) {
  24906. var
  24907. $allModules = $(this),
  24908. moduleSelector = $allModules.selector || '',
  24909. time = new Date().getTime(),
  24910. performance = [],
  24911. query = arguments[0],
  24912. methodInvoked = (typeof query == 'string'),
  24913. queryArguments = [].slice.call(arguments, 1),
  24914. returnedValue,
  24915. moduleCount = $allModules.length,
  24916. loadedCount = 0
  24917. ;
  24918. $allModules
  24919. .each(function() {
  24920. var
  24921. settings = ( $.isPlainObject(parameters) )
  24922. ? $.extend(true, {}, $.fn.visibility.settings, parameters)
  24923. : $.extend({}, $.fn.visibility.settings),
  24924. className = settings.className,
  24925. namespace = settings.namespace,
  24926. error = settings.error,
  24927. metadata = settings.metadata,
  24928. eventNamespace = '.' + namespace,
  24929. moduleNamespace = 'module-' + namespace,
  24930. $window = $(window),
  24931. $module = $(this),
  24932. $context = $(settings.context),
  24933. $placeholder,
  24934. instance = $module.data(moduleNamespace),
  24935. requestAnimationFrame = window.requestAnimationFrame
  24936. || window.mozRequestAnimationFrame
  24937. || window.webkitRequestAnimationFrame
  24938. || window.msRequestAnimationFrame
  24939. || function(callback) { setTimeout(callback, 0); },
  24940. element = this,
  24941. disabled = false,
  24942. contextObserver,
  24943. observer,
  24944. module
  24945. ;
  24946. module = {
  24947. initialize: function() {
  24948. module.debug('Initializing', settings);
  24949. module.setup.cache();
  24950. if( module.should.trackChanges() ) {
  24951. if(settings.type == 'image') {
  24952. module.setup.image();
  24953. }
  24954. if(settings.type == 'fixed') {
  24955. module.setup.fixed();
  24956. }
  24957. if(settings.observeChanges) {
  24958. module.observeChanges();
  24959. }
  24960. module.bind.events();
  24961. }
  24962. module.save.position();
  24963. if( !module.is.visible() ) {
  24964. module.error(error.visible, $module);
  24965. }
  24966. if(settings.initialCheck) {
  24967. module.checkVisibility();
  24968. }
  24969. module.instantiate();
  24970. },
  24971. instantiate: function() {
  24972. module.debug('Storing instance', module);
  24973. $module
  24974. .data(moduleNamespace, module)
  24975. ;
  24976. instance = module;
  24977. },
  24978. destroy: function() {
  24979. module.verbose('Destroying previous module');
  24980. if(observer) {
  24981. observer.disconnect();
  24982. }
  24983. if(contextObserver) {
  24984. contextObserver.disconnect();
  24985. }
  24986. $window
  24987. .off('load' + eventNamespace, module.event.load)
  24988. .off('resize' + eventNamespace, module.event.resize)
  24989. ;
  24990. $context
  24991. .off('scroll' + eventNamespace, module.event.scroll)
  24992. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  24993. ;
  24994. if(settings.type == 'fixed') {
  24995. module.resetFixed();
  24996. module.remove.placeholder();
  24997. }
  24998. $module
  24999. .off(eventNamespace)
  25000. .removeData(moduleNamespace)
  25001. ;
  25002. },
  25003. observeChanges: function() {
  25004. if('MutationObserver' in window) {
  25005. contextObserver = new MutationObserver(module.event.contextChanged);
  25006. observer = new MutationObserver(module.event.changed);
  25007. contextObserver.observe(document, {
  25008. childList : true,
  25009. subtree : true
  25010. });
  25011. observer.observe(element, {
  25012. childList : true,
  25013. subtree : true
  25014. });
  25015. module.debug('Setting up mutation observer', observer);
  25016. }
  25017. },
  25018. bind: {
  25019. events: function() {
  25020. module.verbose('Binding visibility events to scroll and resize');
  25021. if(settings.refreshOnLoad) {
  25022. $window
  25023. .on('load' + eventNamespace, module.event.load)
  25024. ;
  25025. }
  25026. $window
  25027. .on('resize' + eventNamespace, module.event.resize)
  25028. ;
  25029. // pub/sub pattern
  25030. $context
  25031. .off('scroll' + eventNamespace)
  25032. .on('scroll' + eventNamespace, module.event.scroll)
  25033. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  25034. ;
  25035. }
  25036. },
  25037. event: {
  25038. changed: function(mutations) {
  25039. module.verbose('DOM tree modified, updating visibility calculations');
  25040. module.timer = setTimeout(function() {
  25041. module.verbose('DOM tree modified, updating sticky menu');
  25042. module.refresh();
  25043. }, 100);
  25044. },
  25045. contextChanged: function(mutations) {
  25046. [].forEach.call(mutations, function(mutation) {
  25047. if(mutation.removedNodes) {
  25048. [].forEach.call(mutation.removedNodes, function(node) {
  25049. if(node == element || $(node).find(element).length > 0) {
  25050. module.debug('Element removed from DOM, tearing down events');
  25051. module.destroy();
  25052. }
  25053. });
  25054. }
  25055. });
  25056. },
  25057. resize: function() {
  25058. module.debug('Window resized');
  25059. if(settings.refreshOnResize) {
  25060. requestAnimationFrame(module.refresh);
  25061. }
  25062. },
  25063. load: function() {
  25064. module.debug('Page finished loading');
  25065. requestAnimationFrame(module.refresh);
  25066. },
  25067. // publishes scrollchange event on one scroll
  25068. scroll: function() {
  25069. if(settings.throttle) {
  25070. clearTimeout(module.timer);
  25071. module.timer = setTimeout(function() {
  25072. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  25073. }, settings.throttle);
  25074. }
  25075. else {
  25076. requestAnimationFrame(function() {
  25077. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  25078. });
  25079. }
  25080. },
  25081. // subscribes to scrollchange
  25082. scrollchange: function(event, scrollPosition) {
  25083. module.checkVisibility(scrollPosition);
  25084. },
  25085. },
  25086. precache: function(images, callback) {
  25087. if (!(images instanceof Array)) {
  25088. images = [images];
  25089. }
  25090. var
  25091. imagesLength = images.length,
  25092. loadedCounter = 0,
  25093. cache = [],
  25094. cacheImage = document.createElement('img'),
  25095. handleLoad = function() {
  25096. loadedCounter++;
  25097. if (loadedCounter >= images.length) {
  25098. if ($.isFunction(callback)) {
  25099. callback();
  25100. }
  25101. }
  25102. }
  25103. ;
  25104. while (imagesLength--) {
  25105. cacheImage = document.createElement('img');
  25106. cacheImage.onload = handleLoad;
  25107. cacheImage.onerror = handleLoad;
  25108. cacheImage.src = images[imagesLength];
  25109. cache.push(cacheImage);
  25110. }
  25111. },
  25112. enableCallbacks: function() {
  25113. module.debug('Allowing callbacks to occur');
  25114. disabled = false;
  25115. },
  25116. disableCallbacks: function() {
  25117. module.debug('Disabling all callbacks temporarily');
  25118. disabled = true;
  25119. },
  25120. should: {
  25121. trackChanges: function() {
  25122. if(methodInvoked) {
  25123. module.debug('One time query, no need to bind events');
  25124. return false;
  25125. }
  25126. module.debug('Callbacks being attached');
  25127. return true;
  25128. }
  25129. },
  25130. setup: {
  25131. cache: function() {
  25132. module.cache = {
  25133. occurred : {},
  25134. screen : {},
  25135. element : {},
  25136. };
  25137. },
  25138. image: function() {
  25139. var
  25140. src = $module.data(metadata.src)
  25141. ;
  25142. if(src) {
  25143. module.verbose('Lazy loading image', src);
  25144. settings.once = true;
  25145. settings.observeChanges = false;
  25146. // show when top visible
  25147. settings.onOnScreen = function() {
  25148. module.debug('Image on screen', element);
  25149. module.precache(src, function() {
  25150. module.set.image(src, function() {
  25151. loadedCount++;
  25152. if(loadedCount == moduleCount) {
  25153. settings.onAllLoaded.call(this);
  25154. }
  25155. settings.onLoad.call(this);
  25156. });
  25157. });
  25158. };
  25159. }
  25160. },
  25161. fixed: function() {
  25162. module.debug('Setting up fixed');
  25163. settings.once = false;
  25164. settings.observeChanges = false;
  25165. settings.initialCheck = true;
  25166. settings.refreshOnLoad = true;
  25167. if(!parameters.transition) {
  25168. settings.transition = false;
  25169. }
  25170. module.create.placeholder();
  25171. module.debug('Added placeholder', $placeholder);
  25172. settings.onTopPassed = function() {
  25173. module.debug('Element passed, adding fixed position', $module);
  25174. module.show.placeholder();
  25175. module.set.fixed();
  25176. if(settings.transition) {
  25177. if($.fn.transition !== undefined) {
  25178. $module.transition(settings.transition, settings.duration);
  25179. }
  25180. }
  25181. };
  25182. settings.onTopPassedReverse = function() {
  25183. module.debug('Element returned to position, removing fixed', $module);
  25184. module.hide.placeholder();
  25185. module.remove.fixed();
  25186. };
  25187. }
  25188. },
  25189. create: {
  25190. placeholder: function() {
  25191. module.verbose('Creating fixed position placeholder');
  25192. $placeholder = $module
  25193. .clone(false)
  25194. .css('display', 'none')
  25195. .addClass(className.placeholder)
  25196. .insertAfter($module)
  25197. ;
  25198. }
  25199. },
  25200. show: {
  25201. placeholder: function() {
  25202. module.verbose('Showing placeholder');
  25203. $placeholder
  25204. .css('display', 'block')
  25205. .css('visibility', 'hidden')
  25206. ;
  25207. }
  25208. },
  25209. hide: {
  25210. placeholder: function() {
  25211. module.verbose('Hiding placeholder');
  25212. $placeholder
  25213. .css('display', 'none')
  25214. .css('visibility', '')
  25215. ;
  25216. }
  25217. },
  25218. set: {
  25219. fixed: function() {
  25220. module.verbose('Setting element to fixed position');
  25221. $module
  25222. .addClass(className.fixed)
  25223. .css({
  25224. position : 'fixed',
  25225. top : settings.offset + 'px',
  25226. left : 'auto',
  25227. zIndex : settings.zIndex
  25228. })
  25229. ;
  25230. settings.onFixed.call(element);
  25231. },
  25232. image: function(src, callback) {
  25233. $module
  25234. .attr('src', src)
  25235. ;
  25236. if(settings.transition) {
  25237. if( $.fn.transition !== undefined) {
  25238. if($module.hasClass(className.visible)) {
  25239. module.debug('Transition already occurred on this image, skipping animation');
  25240. return;
  25241. }
  25242. $module.transition(settings.transition, settings.duration, callback);
  25243. }
  25244. else {
  25245. $module.fadeIn(settings.duration, callback);
  25246. }
  25247. }
  25248. else {
  25249. $module.show();
  25250. }
  25251. }
  25252. },
  25253. is: {
  25254. onScreen: function() {
  25255. var
  25256. calculations = module.get.elementCalculations()
  25257. ;
  25258. return calculations.onScreen;
  25259. },
  25260. offScreen: function() {
  25261. var
  25262. calculations = module.get.elementCalculations()
  25263. ;
  25264. return calculations.offScreen;
  25265. },
  25266. visible: function() {
  25267. if(module.cache && module.cache.element) {
  25268. return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
  25269. }
  25270. return false;
  25271. },
  25272. verticallyScrollableContext: function() {
  25273. var
  25274. overflowY = ($context.get(0) !== window)
  25275. ? $context.css('overflow-y')
  25276. : false
  25277. ;
  25278. return (overflowY == 'auto' || overflowY == 'scroll');
  25279. },
  25280. horizontallyScrollableContext: function() {
  25281. var
  25282. overflowX = ($context.get(0) !== window)
  25283. ? $context.css('overflow-x')
  25284. : false
  25285. ;
  25286. return (overflowX == 'auto' || overflowX == 'scroll');
  25287. }
  25288. },
  25289. refresh: function() {
  25290. module.debug('Refreshing constants (width/height)');
  25291. if(settings.type == 'fixed') {
  25292. module.resetFixed();
  25293. }
  25294. module.reset();
  25295. module.save.position();
  25296. if(settings.checkOnRefresh) {
  25297. module.checkVisibility();
  25298. }
  25299. settings.onRefresh.call(element);
  25300. },
  25301. resetFixed: function () {
  25302. module.remove.fixed();
  25303. module.remove.occurred();
  25304. },
  25305. reset: function() {
  25306. module.verbose('Resetting all cached values');
  25307. if( $.isPlainObject(module.cache) ) {
  25308. module.cache.screen = {};
  25309. module.cache.element = {};
  25310. }
  25311. },
  25312. checkVisibility: function(scroll) {
  25313. module.verbose('Checking visibility of element', module.cache.element);
  25314. if( !disabled && module.is.visible() ) {
  25315. // save scroll position
  25316. module.save.scroll(scroll);
  25317. // update calculations derived from scroll
  25318. module.save.calculations();
  25319. // percentage
  25320. module.passed();
  25321. // reverse (must be first)
  25322. module.passingReverse();
  25323. module.topVisibleReverse();
  25324. module.bottomVisibleReverse();
  25325. module.topPassedReverse();
  25326. module.bottomPassedReverse();
  25327. // one time
  25328. module.onScreen();
  25329. module.offScreen();
  25330. module.passing();
  25331. module.topVisible();
  25332. module.bottomVisible();
  25333. module.topPassed();
  25334. module.bottomPassed();
  25335. // on update callback
  25336. if(settings.onUpdate) {
  25337. settings.onUpdate.call(element, module.get.elementCalculations());
  25338. }
  25339. }
  25340. },
  25341. passed: function(amount, newCallback) {
  25342. var
  25343. calculations = module.get.elementCalculations()
  25344. ;
  25345. // assign callback
  25346. if(amount && newCallback) {
  25347. settings.onPassed[amount] = newCallback;
  25348. }
  25349. else if(amount !== undefined) {
  25350. return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
  25351. }
  25352. else if(calculations.passing) {
  25353. $.each(settings.onPassed, function(amount, callback) {
  25354. if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
  25355. module.execute(callback, amount);
  25356. }
  25357. else if(!settings.once) {
  25358. module.remove.occurred(callback);
  25359. }
  25360. });
  25361. }
  25362. },
  25363. onScreen: function(newCallback) {
  25364. var
  25365. calculations = module.get.elementCalculations(),
  25366. callback = newCallback || settings.onOnScreen,
  25367. callbackName = 'onScreen'
  25368. ;
  25369. if(newCallback) {
  25370. module.debug('Adding callback for onScreen', newCallback);
  25371. settings.onOnScreen = newCallback;
  25372. }
  25373. if(calculations.onScreen) {
  25374. module.execute(callback, callbackName);
  25375. }
  25376. else if(!settings.once) {
  25377. module.remove.occurred(callbackName);
  25378. }
  25379. if(newCallback !== undefined) {
  25380. return calculations.onOnScreen;
  25381. }
  25382. },
  25383. offScreen: function(newCallback) {
  25384. var
  25385. calculations = module.get.elementCalculations(),
  25386. callback = newCallback || settings.onOffScreen,
  25387. callbackName = 'offScreen'
  25388. ;
  25389. if(newCallback) {
  25390. module.debug('Adding callback for offScreen', newCallback);
  25391. settings.onOffScreen = newCallback;
  25392. }
  25393. if(calculations.offScreen) {
  25394. module.execute(callback, callbackName);
  25395. }
  25396. else if(!settings.once) {
  25397. module.remove.occurred(callbackName);
  25398. }
  25399. if(newCallback !== undefined) {
  25400. return calculations.onOffScreen;
  25401. }
  25402. },
  25403. passing: function(newCallback) {
  25404. var
  25405. calculations = module.get.elementCalculations(),
  25406. callback = newCallback || settings.onPassing,
  25407. callbackName = 'passing'
  25408. ;
  25409. if(newCallback) {
  25410. module.debug('Adding callback for passing', newCallback);
  25411. settings.onPassing = newCallback;
  25412. }
  25413. if(calculations.passing) {
  25414. module.execute(callback, callbackName);
  25415. }
  25416. else if(!settings.once) {
  25417. module.remove.occurred(callbackName);
  25418. }
  25419. if(newCallback !== undefined) {
  25420. return calculations.passing;
  25421. }
  25422. },
  25423. topVisible: function(newCallback) {
  25424. var
  25425. calculations = module.get.elementCalculations(),
  25426. callback = newCallback || settings.onTopVisible,
  25427. callbackName = 'topVisible'
  25428. ;
  25429. if(newCallback) {
  25430. module.debug('Adding callback for top visible', newCallback);
  25431. settings.onTopVisible = newCallback;
  25432. }
  25433. if(calculations.topVisible) {
  25434. module.execute(callback, callbackName);
  25435. }
  25436. else if(!settings.once) {
  25437. module.remove.occurred(callbackName);
  25438. }
  25439. if(newCallback === undefined) {
  25440. return calculations.topVisible;
  25441. }
  25442. },
  25443. bottomVisible: function(newCallback) {
  25444. var
  25445. calculations = module.get.elementCalculations(),
  25446. callback = newCallback || settings.onBottomVisible,
  25447. callbackName = 'bottomVisible'
  25448. ;
  25449. if(newCallback) {
  25450. module.debug('Adding callback for bottom visible', newCallback);
  25451. settings.onBottomVisible = newCallback;
  25452. }
  25453. if(calculations.bottomVisible) {
  25454. module.execute(callback, callbackName);
  25455. }
  25456. else if(!settings.once) {
  25457. module.remove.occurred(callbackName);
  25458. }
  25459. if(newCallback === undefined) {
  25460. return calculations.bottomVisible;
  25461. }
  25462. },
  25463. topPassed: function(newCallback) {
  25464. var
  25465. calculations = module.get.elementCalculations(),
  25466. callback = newCallback || settings.onTopPassed,
  25467. callbackName = 'topPassed'
  25468. ;
  25469. if(newCallback) {
  25470. module.debug('Adding callback for top passed', newCallback);
  25471. settings.onTopPassed = newCallback;
  25472. }
  25473. if(calculations.topPassed) {
  25474. module.execute(callback, callbackName);
  25475. }
  25476. else if(!settings.once) {
  25477. module.remove.occurred(callbackName);
  25478. }
  25479. if(newCallback === undefined) {
  25480. return calculations.topPassed;
  25481. }
  25482. },
  25483. bottomPassed: function(newCallback) {
  25484. var
  25485. calculations = module.get.elementCalculations(),
  25486. callback = newCallback || settings.onBottomPassed,
  25487. callbackName = 'bottomPassed'
  25488. ;
  25489. if(newCallback) {
  25490. module.debug('Adding callback for bottom passed', newCallback);
  25491. settings.onBottomPassed = newCallback;
  25492. }
  25493. if(calculations.bottomPassed) {
  25494. module.execute(callback, callbackName);
  25495. }
  25496. else if(!settings.once) {
  25497. module.remove.occurred(callbackName);
  25498. }
  25499. if(newCallback === undefined) {
  25500. return calculations.bottomPassed;
  25501. }
  25502. },
  25503. passingReverse: function(newCallback) {
  25504. var
  25505. calculations = module.get.elementCalculations(),
  25506. callback = newCallback || settings.onPassingReverse,
  25507. callbackName = 'passingReverse'
  25508. ;
  25509. if(newCallback) {
  25510. module.debug('Adding callback for passing reverse', newCallback);
  25511. settings.onPassingReverse = newCallback;
  25512. }
  25513. if(!calculations.passing) {
  25514. if(module.get.occurred('passing')) {
  25515. module.execute(callback, callbackName);
  25516. }
  25517. }
  25518. else if(!settings.once) {
  25519. module.remove.occurred(callbackName);
  25520. }
  25521. if(newCallback !== undefined) {
  25522. return !calculations.passing;
  25523. }
  25524. },
  25525. topVisibleReverse: function(newCallback) {
  25526. var
  25527. calculations = module.get.elementCalculations(),
  25528. callback = newCallback || settings.onTopVisibleReverse,
  25529. callbackName = 'topVisibleReverse'
  25530. ;
  25531. if(newCallback) {
  25532. module.debug('Adding callback for top visible reverse', newCallback);
  25533. settings.onTopVisibleReverse = newCallback;
  25534. }
  25535. if(!calculations.topVisible) {
  25536. if(module.get.occurred('topVisible')) {
  25537. module.execute(callback, callbackName);
  25538. }
  25539. }
  25540. else if(!settings.once) {
  25541. module.remove.occurred(callbackName);
  25542. }
  25543. if(newCallback === undefined) {
  25544. return !calculations.topVisible;
  25545. }
  25546. },
  25547. bottomVisibleReverse: function(newCallback) {
  25548. var
  25549. calculations = module.get.elementCalculations(),
  25550. callback = newCallback || settings.onBottomVisibleReverse,
  25551. callbackName = 'bottomVisibleReverse'
  25552. ;
  25553. if(newCallback) {
  25554. module.debug('Adding callback for bottom visible reverse', newCallback);
  25555. settings.onBottomVisibleReverse = newCallback;
  25556. }
  25557. if(!calculations.bottomVisible) {
  25558. if(module.get.occurred('bottomVisible')) {
  25559. module.execute(callback, callbackName);
  25560. }
  25561. }
  25562. else if(!settings.once) {
  25563. module.remove.occurred(callbackName);
  25564. }
  25565. if(newCallback === undefined) {
  25566. return !calculations.bottomVisible;
  25567. }
  25568. },
  25569. topPassedReverse: function(newCallback) {
  25570. var
  25571. calculations = module.get.elementCalculations(),
  25572. callback = newCallback || settings.onTopPassedReverse,
  25573. callbackName = 'topPassedReverse'
  25574. ;
  25575. if(newCallback) {
  25576. module.debug('Adding callback for top passed reverse', newCallback);
  25577. settings.onTopPassedReverse = newCallback;
  25578. }
  25579. if(!calculations.topPassed) {
  25580. if(module.get.occurred('topPassed')) {
  25581. module.execute(callback, callbackName);
  25582. }
  25583. }
  25584. else if(!settings.once) {
  25585. module.remove.occurred(callbackName);
  25586. }
  25587. if(newCallback === undefined) {
  25588. return !calculations.onTopPassed;
  25589. }
  25590. },
  25591. bottomPassedReverse: function(newCallback) {
  25592. var
  25593. calculations = module.get.elementCalculations(),
  25594. callback = newCallback || settings.onBottomPassedReverse,
  25595. callbackName = 'bottomPassedReverse'
  25596. ;
  25597. if(newCallback) {
  25598. module.debug('Adding callback for bottom passed reverse', newCallback);
  25599. settings.onBottomPassedReverse = newCallback;
  25600. }
  25601. if(!calculations.bottomPassed) {
  25602. if(module.get.occurred('bottomPassed')) {
  25603. module.execute(callback, callbackName);
  25604. }
  25605. }
  25606. else if(!settings.once) {
  25607. module.remove.occurred(callbackName);
  25608. }
  25609. if(newCallback === undefined) {
  25610. return !calculations.bottomPassed;
  25611. }
  25612. },
  25613. execute: function(callback, callbackName) {
  25614. var
  25615. calculations = module.get.elementCalculations(),
  25616. screen = module.get.screenCalculations()
  25617. ;
  25618. callback = callback || false;
  25619. if(callback) {
  25620. if(settings.continuous) {
  25621. module.debug('Callback being called continuously', callbackName, calculations);
  25622. callback.call(element, calculations, screen);
  25623. }
  25624. else if(!module.get.occurred(callbackName)) {
  25625. module.debug('Conditions met', callbackName, calculations);
  25626. callback.call(element, calculations, screen);
  25627. }
  25628. }
  25629. module.save.occurred(callbackName);
  25630. },
  25631. remove: {
  25632. fixed: function() {
  25633. module.debug('Removing fixed position');
  25634. $module
  25635. .removeClass(className.fixed)
  25636. .css({
  25637. position : '',
  25638. top : '',
  25639. left : '',
  25640. zIndex : ''
  25641. })
  25642. ;
  25643. settings.onUnfixed.call(element);
  25644. },
  25645. placeholder: function() {
  25646. module.debug('Removing placeholder content');
  25647. if($placeholder) {
  25648. $placeholder.remove();
  25649. }
  25650. },
  25651. occurred: function(callback) {
  25652. if(callback) {
  25653. var
  25654. occurred = module.cache.occurred
  25655. ;
  25656. if(occurred[callback] !== undefined && occurred[callback] === true) {
  25657. module.debug('Callback can now be called again', callback);
  25658. module.cache.occurred[callback] = false;
  25659. }
  25660. }
  25661. else {
  25662. module.cache.occurred = {};
  25663. }
  25664. }
  25665. },
  25666. save: {
  25667. calculations: function() {
  25668. module.verbose('Saving all calculations necessary to determine positioning');
  25669. module.save.direction();
  25670. module.save.screenCalculations();
  25671. module.save.elementCalculations();
  25672. },
  25673. occurred: function(callback) {
  25674. if(callback) {
  25675. if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
  25676. module.verbose('Saving callback occurred', callback);
  25677. module.cache.occurred[callback] = true;
  25678. }
  25679. }
  25680. },
  25681. scroll: function(scrollPosition) {
  25682. scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
  25683. module.cache.scroll = scrollPosition;
  25684. },
  25685. direction: function() {
  25686. var
  25687. scroll = module.get.scroll(),
  25688. lastScroll = module.get.lastScroll(),
  25689. direction
  25690. ;
  25691. if(scroll > lastScroll && lastScroll) {
  25692. direction = 'down';
  25693. }
  25694. else if(scroll < lastScroll && lastScroll) {
  25695. direction = 'up';
  25696. }
  25697. else {
  25698. direction = 'static';
  25699. }
  25700. module.cache.direction = direction;
  25701. return module.cache.direction;
  25702. },
  25703. elementPosition: function() {
  25704. var
  25705. element = module.cache.element,
  25706. screen = module.get.screenSize()
  25707. ;
  25708. module.verbose('Saving element position');
  25709. // (quicker than $.extend)
  25710. element.fits = (element.height < screen.height);
  25711. element.offset = $module.offset();
  25712. element.width = $module.outerWidth();
  25713. element.height = $module.outerHeight();
  25714. // compensate for scroll in context
  25715. if(module.is.verticallyScrollableContext()) {
  25716. element.offset.top += $context.scrollTop() - $context.offset().top;
  25717. }
  25718. if(module.is.horizontallyScrollableContext()) {
  25719. element.offset.left += $context.scrollLeft - $context.offset().left;
  25720. }
  25721. // store
  25722. module.cache.element = element;
  25723. return element;
  25724. },
  25725. elementCalculations: function() {
  25726. var
  25727. screen = module.get.screenCalculations(),
  25728. element = module.get.elementPosition()
  25729. ;
  25730. // offset
  25731. if(settings.includeMargin) {
  25732. element.margin = {};
  25733. element.margin.top = parseInt($module.css('margin-top'), 10);
  25734. element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
  25735. element.top = element.offset.top - element.margin.top;
  25736. element.bottom = element.offset.top + element.height + element.margin.bottom;
  25737. }
  25738. else {
  25739. element.top = element.offset.top;
  25740. element.bottom = element.offset.top + element.height;
  25741. }
  25742. // visibility
  25743. element.topPassed = (screen.top >= element.top);
  25744. element.bottomPassed = (screen.top >= element.bottom);
  25745. element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
  25746. element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
  25747. element.pixelsPassed = 0;
  25748. element.percentagePassed = 0;
  25749. // meta calculations
  25750. element.onScreen = ((element.topVisible || element.passing) && !element.bottomPassed);
  25751. element.passing = (element.topPassed && !element.bottomPassed);
  25752. element.offScreen = (!element.onScreen);
  25753. // passing calculations
  25754. if(element.passing) {
  25755. element.pixelsPassed = (screen.top - element.top);
  25756. element.percentagePassed = (screen.top - element.top) / element.height;
  25757. }
  25758. module.cache.element = element;
  25759. module.verbose('Updated element calculations', element);
  25760. return element;
  25761. },
  25762. screenCalculations: function() {
  25763. var
  25764. scroll = module.get.scroll()
  25765. ;
  25766. module.save.direction();
  25767. module.cache.screen.top = scroll;
  25768. module.cache.screen.bottom = scroll + module.cache.screen.height;
  25769. return module.cache.screen;
  25770. },
  25771. screenSize: function() {
  25772. module.verbose('Saving window position');
  25773. module.cache.screen = {
  25774. height: $context.height()
  25775. };
  25776. },
  25777. position: function() {
  25778. module.save.screenSize();
  25779. module.save.elementPosition();
  25780. }
  25781. },
  25782. get: {
  25783. pixelsPassed: function(amount) {
  25784. var
  25785. element = module.get.elementCalculations()
  25786. ;
  25787. if(amount.search('%') > -1) {
  25788. return ( element.height * (parseInt(amount, 10) / 100) );
  25789. }
  25790. return parseInt(amount, 10);
  25791. },
  25792. occurred: function(callback) {
  25793. return (module.cache.occurred !== undefined)
  25794. ? module.cache.occurred[callback] || false
  25795. : false
  25796. ;
  25797. },
  25798. direction: function() {
  25799. if(module.cache.direction === undefined) {
  25800. module.save.direction();
  25801. }
  25802. return module.cache.direction;
  25803. },
  25804. elementPosition: function() {
  25805. if(module.cache.element === undefined) {
  25806. module.save.elementPosition();
  25807. }
  25808. return module.cache.element;
  25809. },
  25810. elementCalculations: function() {
  25811. if(module.cache.element === undefined) {
  25812. module.save.elementCalculations();
  25813. }
  25814. return module.cache.element;
  25815. },
  25816. screenCalculations: function() {
  25817. if(module.cache.screen === undefined) {
  25818. module.save.screenCalculations();
  25819. }
  25820. return module.cache.screen;
  25821. },
  25822. screenSize: function() {
  25823. if(module.cache.screen === undefined) {
  25824. module.save.screenSize();
  25825. }
  25826. return module.cache.screen;
  25827. },
  25828. scroll: function() {
  25829. if(module.cache.scroll === undefined) {
  25830. module.save.scroll();
  25831. }
  25832. return module.cache.scroll;
  25833. },
  25834. lastScroll: function() {
  25835. if(module.cache.screen === undefined) {
  25836. module.debug('First scroll event, no last scroll could be found');
  25837. return false;
  25838. }
  25839. return module.cache.screen.top;
  25840. }
  25841. },
  25842. setting: function(name, value) {
  25843. if( $.isPlainObject(name) ) {
  25844. $.extend(true, settings, name);
  25845. }
  25846. else if(value !== undefined) {
  25847. settings[name] = value;
  25848. }
  25849. else {
  25850. return settings[name];
  25851. }
  25852. },
  25853. internal: function(name, value) {
  25854. if( $.isPlainObject(name) ) {
  25855. $.extend(true, module, name);
  25856. }
  25857. else if(value !== undefined) {
  25858. module[name] = value;
  25859. }
  25860. else {
  25861. return module[name];
  25862. }
  25863. },
  25864. debug: function() {
  25865. if(!settings.silent && settings.debug) {
  25866. if(settings.performance) {
  25867. module.performance.log(arguments);
  25868. }
  25869. else {
  25870. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  25871. module.debug.apply(console, arguments);
  25872. }
  25873. }
  25874. },
  25875. verbose: function() {
  25876. if(!settings.silent && settings.verbose && settings.debug) {
  25877. if(settings.performance) {
  25878. module.performance.log(arguments);
  25879. }
  25880. else {
  25881. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  25882. module.verbose.apply(console, arguments);
  25883. }
  25884. }
  25885. },
  25886. error: function() {
  25887. if(!settings.silent) {
  25888. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  25889. module.error.apply(console, arguments);
  25890. }
  25891. },
  25892. performance: {
  25893. log: function(message) {
  25894. var
  25895. currentTime,
  25896. executionTime,
  25897. previousTime
  25898. ;
  25899. if(settings.performance) {
  25900. currentTime = new Date().getTime();
  25901. previousTime = time || currentTime;
  25902. executionTime = currentTime - previousTime;
  25903. time = currentTime;
  25904. performance.push({
  25905. 'Name' : message[0],
  25906. 'Arguments' : [].slice.call(message, 1) || '',
  25907. 'Element' : element,
  25908. 'Execution Time' : executionTime
  25909. });
  25910. }
  25911. clearTimeout(module.performance.timer);
  25912. module.performance.timer = setTimeout(module.performance.display, 500);
  25913. },
  25914. display: function() {
  25915. var
  25916. title = settings.name + ':',
  25917. totalTime = 0
  25918. ;
  25919. time = false;
  25920. clearTimeout(module.performance.timer);
  25921. $.each(performance, function(index, data) {
  25922. totalTime += data['Execution Time'];
  25923. });
  25924. title += ' ' + totalTime + 'ms';
  25925. if(moduleSelector) {
  25926. title += ' \'' + moduleSelector + '\'';
  25927. }
  25928. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  25929. console.groupCollapsed(title);
  25930. if(console.table) {
  25931. console.table(performance);
  25932. }
  25933. else {
  25934. $.each(performance, function(index, data) {
  25935. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  25936. });
  25937. }
  25938. console.groupEnd();
  25939. }
  25940. performance = [];
  25941. }
  25942. },
  25943. invoke: function(query, passedArguments, context) {
  25944. var
  25945. object = instance,
  25946. maxDepth,
  25947. found,
  25948. response
  25949. ;
  25950. passedArguments = passedArguments || queryArguments;
  25951. context = element || context;
  25952. if(typeof query == 'string' && object !== undefined) {
  25953. query = query.split(/[\. ]/);
  25954. maxDepth = query.length - 1;
  25955. $.each(query, function(depth, value) {
  25956. var camelCaseValue = (depth != maxDepth)
  25957. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  25958. : query
  25959. ;
  25960. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  25961. object = object[camelCaseValue];
  25962. }
  25963. else if( object[camelCaseValue] !== undefined ) {
  25964. found = object[camelCaseValue];
  25965. return false;
  25966. }
  25967. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  25968. object = object[value];
  25969. }
  25970. else if( object[value] !== undefined ) {
  25971. found = object[value];
  25972. return false;
  25973. }
  25974. else {
  25975. module.error(error.method, query);
  25976. return false;
  25977. }
  25978. });
  25979. }
  25980. if ( $.isFunction( found ) ) {
  25981. response = found.apply(context, passedArguments);
  25982. }
  25983. else if(found !== undefined) {
  25984. response = found;
  25985. }
  25986. if(Array.isArray(returnedValue)) {
  25987. returnedValue.push(response);
  25988. }
  25989. else if(returnedValue !== undefined) {
  25990. returnedValue = [returnedValue, response];
  25991. }
  25992. else if(response !== undefined) {
  25993. returnedValue = response;
  25994. }
  25995. return found;
  25996. }
  25997. };
  25998. if(methodInvoked) {
  25999. if(instance === undefined) {
  26000. module.initialize();
  26001. }
  26002. instance.save.scroll();
  26003. instance.save.calculations();
  26004. module.invoke(query);
  26005. }
  26006. else {
  26007. if(instance !== undefined) {
  26008. instance.invoke('destroy');
  26009. }
  26010. module.initialize();
  26011. }
  26012. })
  26013. ;
  26014. return (returnedValue !== undefined)
  26015. ? returnedValue
  26016. : this
  26017. ;
  26018. };
  26019. $.fn.visibility.settings = {
  26020. name : 'Visibility',
  26021. namespace : 'visibility',
  26022. debug : false,
  26023. verbose : false,
  26024. performance : true,
  26025. // whether to use mutation observers to follow changes
  26026. observeChanges : true,
  26027. // check position immediately on init
  26028. initialCheck : true,
  26029. // whether to refresh calculations after all page images load
  26030. refreshOnLoad : true,
  26031. // whether to refresh calculations after page resize event
  26032. refreshOnResize : true,
  26033. // should call callbacks on refresh event (resize, etc)
  26034. checkOnRefresh : true,
  26035. // callback should only occur one time
  26036. once : true,
  26037. // callback should fire continuously whe evaluates to true
  26038. continuous : false,
  26039. // offset to use with scroll top
  26040. offset : 0,
  26041. // whether to include margin in elements position
  26042. includeMargin : false,
  26043. // scroll context for visibility checks
  26044. context : window,
  26045. // visibility check delay in ms (defaults to animationFrame)
  26046. throttle : false,
  26047. // special visibility type (image, fixed)
  26048. type : false,
  26049. // z-index to use with visibility 'fixed'
  26050. zIndex : '10',
  26051. // image only animation settings
  26052. transition : 'fade in',
  26053. duration : 1000,
  26054. // array of callbacks for percentage
  26055. onPassed : {},
  26056. // standard callbacks
  26057. onOnScreen : false,
  26058. onOffScreen : false,
  26059. onPassing : false,
  26060. onTopVisible : false,
  26061. onBottomVisible : false,
  26062. onTopPassed : false,
  26063. onBottomPassed : false,
  26064. // reverse callbacks
  26065. onPassingReverse : false,
  26066. onTopVisibleReverse : false,
  26067. onBottomVisibleReverse : false,
  26068. onTopPassedReverse : false,
  26069. onBottomPassedReverse : false,
  26070. // special callbacks for image
  26071. onLoad : function() {},
  26072. onAllLoaded : function() {},
  26073. // special callbacks for fixed position
  26074. onFixed : function() {},
  26075. onUnfixed : function() {},
  26076. // utility callbacks
  26077. onUpdate : false, // disabled by default for performance
  26078. onRefresh : function(){},
  26079. metadata : {
  26080. src: 'src'
  26081. },
  26082. className: {
  26083. fixed : 'fixed',
  26084. placeholder : 'constraint',
  26085. visible : 'visible'
  26086. },
  26087. error : {
  26088. method : 'The method you called is not defined.',
  26089. visible : 'Element is hidden, you must call refresh after element becomes visible'
  26090. }
  26091. };
  26092. })( jQuery, window, document );