semantic.js 715 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385
  1. /*
  2. * # Semantic UI - 2.3.3
  3. * https://github.com/Semantic-Org/Semantic-UI
  4. * http://www.semantic-ui.com/
  5. *
  6. * Copyright 2014 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. /*!
  12. * # Semantic UI 2.3.3 - Site
  13. * http://github.com/semantic-org/semantic-ui/
  14. *
  15. *
  16. * Released under the MIT license
  17. * http://opensource.org/licenses/MIT
  18. *
  19. */
  20. ;(function ($, window, document, undefined) {
  21. $.site = $.fn.site = function(parameters) {
  22. var
  23. time = new Date().getTime(),
  24. performance = [],
  25. query = arguments[0],
  26. methodInvoked = (typeof query == 'string'),
  27. queryArguments = [].slice.call(arguments, 1),
  28. settings = ( $.isPlainObject(parameters) )
  29. ? $.extend(true, {}, $.site.settings, parameters)
  30. : $.extend({}, $.site.settings),
  31. namespace = settings.namespace,
  32. error = settings.error,
  33. eventNamespace = '.' + namespace,
  34. moduleNamespace = 'module-' + namespace,
  35. $document = $(document),
  36. $module = $document,
  37. element = this,
  38. instance = $module.data(moduleNamespace),
  39. module,
  40. returnedValue
  41. ;
  42. module = {
  43. initialize: function() {
  44. module.instantiate();
  45. },
  46. instantiate: function() {
  47. module.verbose('Storing instance of site', module);
  48. instance = module;
  49. $module
  50. .data(moduleNamespace, module)
  51. ;
  52. },
  53. normalize: function() {
  54. module.fix.console();
  55. module.fix.requestAnimationFrame();
  56. },
  57. fix: {
  58. console: function() {
  59. module.debug('Normalizing window.console');
  60. if (console === undefined || console.log === undefined) {
  61. module.verbose('Console not available, normalizing events');
  62. module.disable.console();
  63. }
  64. if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
  65. module.verbose('Console group not available, normalizing events');
  66. window.console.group = function() {};
  67. window.console.groupEnd = function() {};
  68. window.console.groupCollapsed = function() {};
  69. }
  70. if (typeof console.markTimeline == 'undefined') {
  71. module.verbose('Mark timeline not available, normalizing events');
  72. window.console.markTimeline = function() {};
  73. }
  74. },
  75. consoleClear: function() {
  76. module.debug('Disabling programmatic console clearing');
  77. window.console.clear = function() {};
  78. },
  79. requestAnimationFrame: function() {
  80. module.debug('Normalizing requestAnimationFrame');
  81. if(window.requestAnimationFrame === undefined) {
  82. module.debug('RequestAnimationFrame not available, normalizing event');
  83. window.requestAnimationFrame = window.requestAnimationFrame
  84. || window.mozRequestAnimationFrame
  85. || window.webkitRequestAnimationFrame
  86. || window.msRequestAnimationFrame
  87. || function(callback) { setTimeout(callback, 0); }
  88. ;
  89. }
  90. }
  91. },
  92. moduleExists: function(name) {
  93. return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
  94. },
  95. enabled: {
  96. modules: function(modules) {
  97. var
  98. enabledModules = []
  99. ;
  100. modules = modules || settings.modules;
  101. $.each(modules, function(index, name) {
  102. if(module.moduleExists(name)) {
  103. enabledModules.push(name);
  104. }
  105. });
  106. return enabledModules;
  107. }
  108. },
  109. disabled: {
  110. modules: function(modules) {
  111. var
  112. disabledModules = []
  113. ;
  114. modules = modules || settings.modules;
  115. $.each(modules, function(index, name) {
  116. if(!module.moduleExists(name)) {
  117. disabledModules.push(name);
  118. }
  119. });
  120. return disabledModules;
  121. }
  122. },
  123. change: {
  124. setting: function(setting, value, modules, modifyExisting) {
  125. modules = (typeof modules === 'string')
  126. ? (modules === 'all')
  127. ? settings.modules
  128. : [modules]
  129. : modules || settings.modules
  130. ;
  131. modifyExisting = (modifyExisting !== undefined)
  132. ? modifyExisting
  133. : true
  134. ;
  135. $.each(modules, function(index, name) {
  136. var
  137. namespace = (module.moduleExists(name))
  138. ? $.fn[name].settings.namespace || false
  139. : true,
  140. $existingModules
  141. ;
  142. if(module.moduleExists(name)) {
  143. module.verbose('Changing default setting', setting, value, name);
  144. $.fn[name].settings[setting] = value;
  145. if(modifyExisting && namespace) {
  146. $existingModules = $(':data(module-' + namespace + ')');
  147. if($existingModules.length > 0) {
  148. module.verbose('Modifying existing settings', $existingModules);
  149. $existingModules[name]('setting', setting, value);
  150. }
  151. }
  152. }
  153. });
  154. },
  155. settings: function(newSettings, modules, modifyExisting) {
  156. modules = (typeof modules === 'string')
  157. ? [modules]
  158. : modules || settings.modules
  159. ;
  160. modifyExisting = (modifyExisting !== undefined)
  161. ? modifyExisting
  162. : true
  163. ;
  164. $.each(modules, function(index, name) {
  165. var
  166. $existingModules
  167. ;
  168. if(module.moduleExists(name)) {
  169. module.verbose('Changing default setting', newSettings, name);
  170. $.extend(true, $.fn[name].settings, newSettings);
  171. if(modifyExisting && namespace) {
  172. $existingModules = $(':data(module-' + namespace + ')');
  173. if($existingModules.length > 0) {
  174. module.verbose('Modifying existing settings', $existingModules);
  175. $existingModules[name]('setting', newSettings);
  176. }
  177. }
  178. }
  179. });
  180. }
  181. },
  182. enable: {
  183. console: function() {
  184. module.console(true);
  185. },
  186. debug: function(modules, modifyExisting) {
  187. modules = modules || settings.modules;
  188. module.debug('Enabling debug for modules', modules);
  189. module.change.setting('debug', true, modules, modifyExisting);
  190. },
  191. verbose: function(modules, modifyExisting) {
  192. modules = modules || settings.modules;
  193. module.debug('Enabling verbose debug for modules', modules);
  194. module.change.setting('verbose', true, modules, modifyExisting);
  195. }
  196. },
  197. disable: {
  198. console: function() {
  199. module.console(false);
  200. },
  201. debug: function(modules, modifyExisting) {
  202. modules = modules || settings.modules;
  203. module.debug('Disabling debug for modules', modules);
  204. module.change.setting('debug', false, modules, modifyExisting);
  205. },
  206. verbose: function(modules, modifyExisting) {
  207. modules = modules || settings.modules;
  208. module.debug('Disabling verbose debug for modules', modules);
  209. module.change.setting('verbose', false, modules, modifyExisting);
  210. }
  211. },
  212. console: function(enable) {
  213. if(enable) {
  214. if(instance.cache.console === undefined) {
  215. module.error(error.console);
  216. return;
  217. }
  218. module.debug('Restoring console function');
  219. window.console = instance.cache.console;
  220. }
  221. else {
  222. module.debug('Disabling console function');
  223. instance.cache.console = window.console;
  224. window.console = {
  225. clear : function(){},
  226. error : function(){},
  227. group : function(){},
  228. groupCollapsed : function(){},
  229. groupEnd : function(){},
  230. info : function(){},
  231. log : function(){},
  232. markTimeline : function(){},
  233. warn : function(){}
  234. };
  235. }
  236. },
  237. destroy: function() {
  238. module.verbose('Destroying previous site for', $module);
  239. $module
  240. .removeData(moduleNamespace)
  241. ;
  242. },
  243. cache: {},
  244. setting: function(name, value) {
  245. if( $.isPlainObject(name) ) {
  246. $.extend(true, settings, name);
  247. }
  248. else if(value !== undefined) {
  249. settings[name] = value;
  250. }
  251. else {
  252. return settings[name];
  253. }
  254. },
  255. internal: function(name, value) {
  256. if( $.isPlainObject(name) ) {
  257. $.extend(true, module, name);
  258. }
  259. else if(value !== undefined) {
  260. module[name] = value;
  261. }
  262. else {
  263. return module[name];
  264. }
  265. },
  266. debug: function() {
  267. if(settings.debug) {
  268. if(settings.performance) {
  269. module.performance.log(arguments);
  270. }
  271. else {
  272. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  273. module.debug.apply(console, arguments);
  274. }
  275. }
  276. },
  277. verbose: function() {
  278. if(settings.verbose && settings.debug) {
  279. if(settings.performance) {
  280. module.performance.log(arguments);
  281. }
  282. else {
  283. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  284. module.verbose.apply(console, arguments);
  285. }
  286. }
  287. },
  288. error: function() {
  289. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  290. module.error.apply(console, arguments);
  291. },
  292. performance: {
  293. log: function(message) {
  294. var
  295. currentTime,
  296. executionTime,
  297. previousTime
  298. ;
  299. if(settings.performance) {
  300. currentTime = new Date().getTime();
  301. previousTime = time || currentTime;
  302. executionTime = currentTime - previousTime;
  303. time = currentTime;
  304. performance.push({
  305. 'Element' : element,
  306. 'Name' : message[0],
  307. 'Arguments' : [].slice.call(message, 1) || '',
  308. 'Execution Time' : executionTime
  309. });
  310. }
  311. clearTimeout(module.performance.timer);
  312. module.performance.timer = setTimeout(module.performance.display, 500);
  313. },
  314. display: function() {
  315. var
  316. title = settings.name + ':',
  317. totalTime = 0
  318. ;
  319. time = false;
  320. clearTimeout(module.performance.timer);
  321. $.each(performance, function(index, data) {
  322. totalTime += data['Execution Time'];
  323. });
  324. title += ' ' + totalTime + 'ms';
  325. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  326. console.groupCollapsed(title);
  327. if(console.table) {
  328. console.table(performance);
  329. }
  330. else {
  331. $.each(performance, function(index, data) {
  332. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  333. });
  334. }
  335. console.groupEnd();
  336. }
  337. performance = [];
  338. }
  339. },
  340. invoke: function(query, passedArguments, context) {
  341. var
  342. object = instance,
  343. maxDepth,
  344. found,
  345. response
  346. ;
  347. passedArguments = passedArguments || queryArguments;
  348. context = element || context;
  349. if(typeof query == 'string' && object !== undefined) {
  350. query = query.split(/[\. ]/);
  351. maxDepth = query.length - 1;
  352. $.each(query, function(depth, value) {
  353. var camelCaseValue = (depth != maxDepth)
  354. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  355. : query
  356. ;
  357. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  358. object = object[camelCaseValue];
  359. }
  360. else if( object[camelCaseValue] !== undefined ) {
  361. found = object[camelCaseValue];
  362. return false;
  363. }
  364. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  365. object = object[value];
  366. }
  367. else if( object[value] !== undefined ) {
  368. found = object[value];
  369. return false;
  370. }
  371. else {
  372. module.error(error.method, query);
  373. return false;
  374. }
  375. });
  376. }
  377. if ( $.isFunction( found ) ) {
  378. response = found.apply(context, passedArguments);
  379. }
  380. else if(found !== undefined) {
  381. response = found;
  382. }
  383. if($.isArray(returnedValue)) {
  384. returnedValue.push(response);
  385. }
  386. else if(returnedValue !== undefined) {
  387. returnedValue = [returnedValue, response];
  388. }
  389. else if(response !== undefined) {
  390. returnedValue = response;
  391. }
  392. return found;
  393. }
  394. };
  395. if(methodInvoked) {
  396. if(instance === undefined) {
  397. module.initialize();
  398. }
  399. module.invoke(query);
  400. }
  401. else {
  402. if(instance !== undefined) {
  403. module.destroy();
  404. }
  405. module.initialize();
  406. }
  407. return (returnedValue !== undefined)
  408. ? returnedValue
  409. : this
  410. ;
  411. };
  412. $.site.settings = {
  413. name : 'Site',
  414. namespace : 'site',
  415. error : {
  416. console : 'Console cannot be restored, most likely it was overwritten outside of module',
  417. method : 'The method you called is not defined.'
  418. },
  419. debug : false,
  420. verbose : false,
  421. performance : true,
  422. modules: [
  423. 'accordion',
  424. 'api',
  425. 'checkbox',
  426. 'dimmer',
  427. 'dropdown',
  428. 'embed',
  429. 'form',
  430. 'modal',
  431. 'nag',
  432. 'popup',
  433. 'rating',
  434. 'shape',
  435. 'sidebar',
  436. 'state',
  437. 'sticky',
  438. 'tab',
  439. 'transition',
  440. 'visit',
  441. 'visibility'
  442. ],
  443. siteNamespace : 'site',
  444. namespaceStub : {
  445. cache : {},
  446. config : {},
  447. sections : {},
  448. section : {},
  449. utilities : {}
  450. }
  451. };
  452. // allows for selection of elements with data attributes
  453. $.extend($.expr[ ":" ], {
  454. data: ($.expr.createPseudo)
  455. ? $.expr.createPseudo(function(dataName) {
  456. return function(elem) {
  457. return !!$.data(elem, dataName);
  458. };
  459. })
  460. : function(elem, i, match) {
  461. // support: jQuery < 1.8
  462. return !!$.data(elem, match[ 3 ]);
  463. }
  464. });
  465. })( jQuery, window, document );
  466. /*!
  467. * # Semantic UI 2.3.3 - Form Validation
  468. * http://github.com/semantic-org/semantic-ui/
  469. *
  470. *
  471. * Released under the MIT license
  472. * http://opensource.org/licenses/MIT
  473. *
  474. */
  475. ;(function ($, window, document, undefined) {
  476. 'use strict';
  477. window = (typeof window != 'undefined' && window.Math == Math)
  478. ? window
  479. : (typeof self != 'undefined' && self.Math == Math)
  480. ? self
  481. : Function('return this')()
  482. ;
  483. $.fn.form = function(parameters) {
  484. var
  485. $allModules = $(this),
  486. moduleSelector = $allModules.selector || '',
  487. time = new Date().getTime(),
  488. performance = [],
  489. query = arguments[0],
  490. legacyParameters = arguments[1],
  491. methodInvoked = (typeof query == 'string'),
  492. queryArguments = [].slice.call(arguments, 1),
  493. returnedValue
  494. ;
  495. $allModules
  496. .each(function() {
  497. var
  498. $module = $(this),
  499. element = this,
  500. formErrors = [],
  501. keyHeldDown = false,
  502. // set at run-time
  503. $field,
  504. $group,
  505. $message,
  506. $prompt,
  507. $submit,
  508. $clear,
  509. $reset,
  510. settings,
  511. validation,
  512. metadata,
  513. selector,
  514. className,
  515. regExp,
  516. error,
  517. namespace,
  518. moduleNamespace,
  519. eventNamespace,
  520. instance,
  521. module
  522. ;
  523. module = {
  524. initialize: function() {
  525. // settings grabbed at run time
  526. module.get.settings();
  527. if(methodInvoked) {
  528. if(instance === undefined) {
  529. module.instantiate();
  530. }
  531. module.invoke(query);
  532. }
  533. else {
  534. if(instance !== undefined) {
  535. instance.invoke('destroy');
  536. }
  537. module.verbose('Initializing form validation', $module, settings);
  538. module.bindEvents();
  539. module.set.defaults();
  540. module.instantiate();
  541. }
  542. },
  543. instantiate: function() {
  544. module.verbose('Storing instance of module', module);
  545. instance = module;
  546. $module
  547. .data(moduleNamespace, module)
  548. ;
  549. },
  550. destroy: function() {
  551. module.verbose('Destroying previous module', instance);
  552. module.removeEvents();
  553. $module
  554. .removeData(moduleNamespace)
  555. ;
  556. },
  557. refresh: function() {
  558. module.verbose('Refreshing selector cache');
  559. $field = $module.find(selector.field);
  560. $group = $module.find(selector.group);
  561. $message = $module.find(selector.message);
  562. $prompt = $module.find(selector.prompt);
  563. $submit = $module.find(selector.submit);
  564. $clear = $module.find(selector.clear);
  565. $reset = $module.find(selector.reset);
  566. },
  567. submit: function() {
  568. module.verbose('Submitting form', $module);
  569. $module
  570. .submit()
  571. ;
  572. },
  573. attachEvents: function(selector, action) {
  574. action = action || 'submit';
  575. $(selector)
  576. .on('click' + eventNamespace, function(event) {
  577. module[action]();
  578. event.preventDefault();
  579. })
  580. ;
  581. },
  582. bindEvents: function() {
  583. module.verbose('Attaching form events');
  584. $module
  585. .on('submit' + eventNamespace, module.validate.form)
  586. .on('blur' + eventNamespace, selector.field, module.event.field.blur)
  587. .on('click' + eventNamespace, selector.submit, module.submit)
  588. .on('click' + eventNamespace, selector.reset, module.reset)
  589. .on('click' + eventNamespace, selector.clear, module.clear)
  590. ;
  591. if(settings.keyboardShortcuts) {
  592. $module
  593. .on('keydown' + eventNamespace, selector.field, module.event.field.keydown)
  594. ;
  595. }
  596. $field
  597. .each(function() {
  598. var
  599. $input = $(this),
  600. type = $input.prop('type'),
  601. inputEvent = module.get.changeEvent(type, $input)
  602. ;
  603. $(this)
  604. .on(inputEvent + eventNamespace, module.event.field.change)
  605. ;
  606. })
  607. ;
  608. },
  609. clear: function() {
  610. $field
  611. .each(function () {
  612. var
  613. $field = $(this),
  614. $element = $field.parent(),
  615. $fieldGroup = $field.closest($group),
  616. $prompt = $fieldGroup.find(selector.prompt),
  617. defaultValue = $field.data(metadata.defaultValue) || '',
  618. isCheckbox = $element.is(selector.uiCheckbox),
  619. isDropdown = $element.is(selector.uiDropdown),
  620. isErrored = $fieldGroup.hasClass(className.error)
  621. ;
  622. if(isErrored) {
  623. module.verbose('Resetting error on field', $fieldGroup);
  624. $fieldGroup.removeClass(className.error);
  625. $prompt.remove();
  626. }
  627. if(isDropdown) {
  628. module.verbose('Resetting dropdown value', $element, defaultValue);
  629. $element.dropdown('clear');
  630. }
  631. else if(isCheckbox) {
  632. $field.prop('checked', false);
  633. }
  634. else {
  635. module.verbose('Resetting field value', $field, defaultValue);
  636. $field.val('');
  637. }
  638. })
  639. ;
  640. },
  641. reset: function() {
  642. $field
  643. .each(function () {
  644. var
  645. $field = $(this),
  646. $element = $field.parent(),
  647. $fieldGroup = $field.closest($group),
  648. $prompt = $fieldGroup.find(selector.prompt),
  649. defaultValue = $field.data(metadata.defaultValue),
  650. isCheckbox = $element.is(selector.uiCheckbox),
  651. isDropdown = $element.is(selector.uiDropdown),
  652. isErrored = $fieldGroup.hasClass(className.error)
  653. ;
  654. if(defaultValue === undefined) {
  655. return;
  656. }
  657. if(isErrored) {
  658. module.verbose('Resetting error on field', $fieldGroup);
  659. $fieldGroup.removeClass(className.error);
  660. $prompt.remove();
  661. }
  662. if(isDropdown) {
  663. module.verbose('Resetting dropdown value', $element, defaultValue);
  664. $element.dropdown('restore defaults');
  665. }
  666. else if(isCheckbox) {
  667. module.verbose('Resetting checkbox value', $element, defaultValue);
  668. $field.prop('checked', defaultValue);
  669. }
  670. else {
  671. module.verbose('Resetting field value', $field, defaultValue);
  672. $field.val(defaultValue);
  673. }
  674. })
  675. ;
  676. },
  677. determine: {
  678. isValid: function() {
  679. var
  680. allValid = true
  681. ;
  682. $.each(validation, function(fieldName, field) {
  683. if( !( module.validate.field(field, fieldName, true) ) ) {
  684. allValid = false;
  685. }
  686. });
  687. return allValid;
  688. }
  689. },
  690. is: {
  691. bracketedRule: function(rule) {
  692. return (rule.type && rule.type.match(settings.regExp.bracket));
  693. },
  694. shorthandFields: function(fields) {
  695. var
  696. fieldKeys = Object.keys(fields),
  697. firstRule = fields[fieldKeys[0]]
  698. ;
  699. return module.is.shorthandRules(firstRule);
  700. },
  701. // duck type rule test
  702. shorthandRules: function(rules) {
  703. return (typeof rules == 'string' || $.isArray(rules));
  704. },
  705. empty: function($field) {
  706. if(!$field || $field.length === 0) {
  707. return true;
  708. }
  709. else if($field.is('input[type="checkbox"]')) {
  710. return !$field.is(':checked');
  711. }
  712. else {
  713. return module.is.blank($field);
  714. }
  715. },
  716. blank: function($field) {
  717. return $.trim($field.val()) === '';
  718. },
  719. valid: function(field) {
  720. var
  721. allValid = true
  722. ;
  723. if(field) {
  724. module.verbose('Checking if field is valid', field);
  725. return module.validate.field(validation[field], field, false);
  726. }
  727. else {
  728. module.verbose('Checking if form is valid');
  729. $.each(validation, function(fieldName, field) {
  730. if( !module.is.valid(fieldName) ) {
  731. allValid = false;
  732. }
  733. });
  734. return allValid;
  735. }
  736. }
  737. },
  738. removeEvents: function() {
  739. $module
  740. .off(eventNamespace)
  741. ;
  742. $field
  743. .off(eventNamespace)
  744. ;
  745. $submit
  746. .off(eventNamespace)
  747. ;
  748. $field
  749. .off(eventNamespace)
  750. ;
  751. },
  752. event: {
  753. field: {
  754. keydown: function(event) {
  755. var
  756. $field = $(this),
  757. key = event.which,
  758. isInput = $field.is(selector.input),
  759. isCheckbox = $field.is(selector.checkbox),
  760. isInDropdown = ($field.closest(selector.uiDropdown).length > 0),
  761. keyCode = {
  762. enter : 13,
  763. escape : 27
  764. }
  765. ;
  766. if( key == keyCode.escape) {
  767. module.verbose('Escape key pressed blurring field');
  768. $field
  769. .blur()
  770. ;
  771. }
  772. if(!event.ctrlKey && key == keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
  773. if(!keyHeldDown) {
  774. $field
  775. .one('keyup' + eventNamespace, module.event.field.keyup)
  776. ;
  777. module.submit();
  778. module.debug('Enter pressed on input submitting form');
  779. }
  780. keyHeldDown = true;
  781. }
  782. },
  783. keyup: function() {
  784. keyHeldDown = false;
  785. },
  786. blur: function(event) {
  787. var
  788. $field = $(this),
  789. $fieldGroup = $field.closest($group),
  790. validationRules = module.get.validation($field)
  791. ;
  792. if( $fieldGroup.hasClass(className.error) ) {
  793. module.debug('Revalidating field', $field, validationRules);
  794. if(validationRules) {
  795. module.validate.field( validationRules );
  796. }
  797. }
  798. else if(settings.on == 'blur') {
  799. if(validationRules) {
  800. module.validate.field( validationRules );
  801. }
  802. }
  803. },
  804. change: function(event) {
  805. var
  806. $field = $(this),
  807. $fieldGroup = $field.closest($group),
  808. validationRules = module.get.validation($field)
  809. ;
  810. if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
  811. clearTimeout(module.timer);
  812. module.timer = setTimeout(function() {
  813. module.debug('Revalidating field', $field, module.get.validation($field));
  814. module.validate.field( validationRules );
  815. }, settings.delay);
  816. }
  817. }
  818. }
  819. },
  820. get: {
  821. ancillaryValue: function(rule) {
  822. if(!rule.type || (!rule.value && !module.is.bracketedRule(rule))) {
  823. return false;
  824. }
  825. return (rule.value !== undefined)
  826. ? rule.value
  827. : rule.type.match(settings.regExp.bracket)[1] + ''
  828. ;
  829. },
  830. ruleName: function(rule) {
  831. if( module.is.bracketedRule(rule) ) {
  832. return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
  833. }
  834. return rule.type;
  835. },
  836. changeEvent: function(type, $input) {
  837. if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
  838. return 'change';
  839. }
  840. else {
  841. return module.get.inputEvent();
  842. }
  843. },
  844. inputEvent: function() {
  845. return (document.createElement('input').oninput !== undefined)
  846. ? 'input'
  847. : (document.createElement('input').onpropertychange !== undefined)
  848. ? 'propertychange'
  849. : 'keyup'
  850. ;
  851. },
  852. fieldsFromShorthand: function(fields) {
  853. var
  854. fullFields = {}
  855. ;
  856. $.each(fields, function(name, rules) {
  857. if(typeof rules == 'string') {
  858. rules = [rules];
  859. }
  860. fullFields[name] = {
  861. rules: []
  862. };
  863. $.each(rules, function(index, rule) {
  864. fullFields[name].rules.push({ type: rule });
  865. });
  866. });
  867. return fullFields;
  868. },
  869. prompt: function(rule, field) {
  870. var
  871. ruleName = module.get.ruleName(rule),
  872. ancillary = module.get.ancillaryValue(rule),
  873. $field = module.get.field(field.identifier),
  874. value = $field.val(),
  875. prompt = $.isFunction(rule.prompt)
  876. ? rule.prompt(value)
  877. : rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
  878. requiresValue = (prompt.search('{value}') !== -1),
  879. requiresName = (prompt.search('{name}') !== -1),
  880. $label,
  881. name
  882. ;
  883. if(requiresValue) {
  884. prompt = prompt.replace('{value}', $field.val());
  885. }
  886. if(requiresName) {
  887. $label = $field.closest(selector.group).find('label').eq(0);
  888. name = ($label.length == 1)
  889. ? $label.text()
  890. : $field.prop('placeholder') || settings.text.unspecifiedField
  891. ;
  892. prompt = prompt.replace('{name}', name);
  893. }
  894. prompt = prompt.replace('{identifier}', field.identifier);
  895. prompt = prompt.replace('{ruleValue}', ancillary);
  896. if(!rule.prompt) {
  897. module.verbose('Using default validation prompt for type', prompt, ruleName);
  898. }
  899. return prompt;
  900. },
  901. settings: function() {
  902. if($.isPlainObject(parameters)) {
  903. var
  904. keys = Object.keys(parameters),
  905. isLegacySettings = (keys.length > 0)
  906. ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
  907. : false,
  908. ruleKeys
  909. ;
  910. if(isLegacySettings) {
  911. // 1.x (ducktyped)
  912. settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
  913. validation = $.extend({}, $.fn.form.settings.defaults, parameters);
  914. module.error(settings.error.oldSyntax, element);
  915. module.verbose('Extending settings from legacy parameters', validation, settings);
  916. }
  917. else {
  918. // 2.x
  919. if(parameters.fields && module.is.shorthandFields(parameters.fields)) {
  920. parameters.fields = module.get.fieldsFromShorthand(parameters.fields);
  921. }
  922. settings = $.extend(true, {}, $.fn.form.settings, parameters);
  923. validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
  924. module.verbose('Extending settings', validation, settings);
  925. }
  926. }
  927. else {
  928. settings = $.fn.form.settings;
  929. validation = $.fn.form.settings.defaults;
  930. module.verbose('Using default form validation', validation, settings);
  931. }
  932. // shorthand
  933. namespace = settings.namespace;
  934. metadata = settings.metadata;
  935. selector = settings.selector;
  936. className = settings.className;
  937. regExp = settings.regExp;
  938. error = settings.error;
  939. moduleNamespace = 'module-' + namespace;
  940. eventNamespace = '.' + namespace;
  941. // grab instance
  942. instance = $module.data(moduleNamespace);
  943. // refresh selector cache
  944. module.refresh();
  945. },
  946. field: function(identifier) {
  947. module.verbose('Finding field with identifier', identifier);
  948. identifier = module.escape.string(identifier);
  949. if($field.filter('#' + identifier).length > 0 ) {
  950. return $field.filter('#' + identifier);
  951. }
  952. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  953. return $field.filter('[name="' + identifier +'"]');
  954. }
  955. else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) {
  956. return $field.filter('[name="' + identifier +'[]"]');
  957. }
  958. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  959. return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]');
  960. }
  961. return $('<input/>');
  962. },
  963. fields: function(fields) {
  964. var
  965. $fields = $()
  966. ;
  967. $.each(fields, function(index, name) {
  968. $fields = $fields.add( module.get.field(name) );
  969. });
  970. return $fields;
  971. },
  972. validation: function($field) {
  973. var
  974. fieldValidation,
  975. identifier
  976. ;
  977. if(!validation) {
  978. return false;
  979. }
  980. $.each(validation, function(fieldName, field) {
  981. identifier = field.identifier || fieldName;
  982. if( module.get.field(identifier)[0] == $field[0] ) {
  983. field.identifier = identifier;
  984. fieldValidation = field;
  985. }
  986. });
  987. return fieldValidation || false;
  988. },
  989. value: function (field) {
  990. var
  991. fields = [],
  992. results
  993. ;
  994. fields.push(field);
  995. results = module.get.values.call(element, fields);
  996. return results[field];
  997. },
  998. values: function (fields) {
  999. var
  1000. $fields = $.isArray(fields)
  1001. ? module.get.fields(fields)
  1002. : $field,
  1003. values = {}
  1004. ;
  1005. $fields.each(function(index, field) {
  1006. var
  1007. $field = $(field),
  1008. type = $field.prop('type'),
  1009. name = $field.prop('name'),
  1010. value = $field.val(),
  1011. isCheckbox = $field.is(selector.checkbox),
  1012. isRadio = $field.is(selector.radio),
  1013. isMultiple = (name.indexOf('[]') !== -1),
  1014. isChecked = (isCheckbox)
  1015. ? $field.is(':checked')
  1016. : false
  1017. ;
  1018. if(name) {
  1019. if(isMultiple) {
  1020. name = name.replace('[]', '');
  1021. if(!values[name]) {
  1022. values[name] = [];
  1023. }
  1024. if(isCheckbox) {
  1025. if(isChecked) {
  1026. values[name].push(value || true);
  1027. }
  1028. else {
  1029. values[name].push(false);
  1030. }
  1031. }
  1032. else {
  1033. values[name].push(value);
  1034. }
  1035. }
  1036. else {
  1037. if(isRadio) {
  1038. if(values[name] === undefined || values[name] == false) {
  1039. values[name] = (isChecked)
  1040. ? value || true
  1041. : false
  1042. ;
  1043. }
  1044. }
  1045. else if(isCheckbox) {
  1046. if(isChecked) {
  1047. values[name] = value || true;
  1048. }
  1049. else {
  1050. values[name] = false;
  1051. }
  1052. }
  1053. else {
  1054. values[name] = value;
  1055. }
  1056. }
  1057. }
  1058. });
  1059. return values;
  1060. }
  1061. },
  1062. has: {
  1063. field: function(identifier) {
  1064. module.verbose('Checking for existence of a field with identifier', identifier);
  1065. identifier = module.escape.string(identifier);
  1066. if(typeof identifier !== 'string') {
  1067. module.error(error.identifier, identifier);
  1068. }
  1069. if($field.filter('#' + identifier).length > 0 ) {
  1070. return true;
  1071. }
  1072. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  1073. return true;
  1074. }
  1075. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  1076. return true;
  1077. }
  1078. return false;
  1079. }
  1080. },
  1081. escape: {
  1082. string: function(text) {
  1083. text = String(text);
  1084. return text.replace(regExp.escape, '\\$&');
  1085. }
  1086. },
  1087. add: {
  1088. // alias
  1089. rule: function(name, rules) {
  1090. module.add.field(name, rules);
  1091. },
  1092. field: function(name, rules) {
  1093. var
  1094. newValidation = {}
  1095. ;
  1096. if(module.is.shorthandRules(rules)) {
  1097. rules = $.isArray(rules)
  1098. ? rules
  1099. : [rules]
  1100. ;
  1101. newValidation[name] = {
  1102. rules: []
  1103. };
  1104. $.each(rules, function(index, rule) {
  1105. newValidation[name].rules.push({ type: rule });
  1106. });
  1107. }
  1108. else {
  1109. newValidation[name] = rules;
  1110. }
  1111. validation = $.extend({}, validation, newValidation);
  1112. module.debug('Adding rules', newValidation, validation);
  1113. },
  1114. fields: function(fields) {
  1115. var
  1116. newValidation
  1117. ;
  1118. if(fields && module.is.shorthandFields(fields)) {
  1119. newValidation = module.get.fieldsFromShorthand(fields);
  1120. }
  1121. else {
  1122. newValidation = fields;
  1123. }
  1124. validation = $.extend({}, validation, newValidation);
  1125. },
  1126. prompt: function(identifier, errors) {
  1127. var
  1128. $field = module.get.field(identifier),
  1129. $fieldGroup = $field.closest($group),
  1130. $prompt = $fieldGroup.children(selector.prompt),
  1131. promptExists = ($prompt.length !== 0)
  1132. ;
  1133. errors = (typeof errors == 'string')
  1134. ? [errors]
  1135. : errors
  1136. ;
  1137. module.verbose('Adding field error state', identifier);
  1138. $fieldGroup
  1139. .addClass(className.error)
  1140. ;
  1141. if(settings.inline) {
  1142. if(!promptExists) {
  1143. $prompt = settings.templates.prompt(errors);
  1144. $prompt
  1145. .appendTo($fieldGroup)
  1146. ;
  1147. }
  1148. $prompt
  1149. .html(errors[0])
  1150. ;
  1151. if(!promptExists) {
  1152. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  1153. module.verbose('Displaying error with css transition', settings.transition);
  1154. $prompt.transition(settings.transition + ' in', settings.duration);
  1155. }
  1156. else {
  1157. module.verbose('Displaying error with fallback javascript animation');
  1158. $prompt
  1159. .fadeIn(settings.duration)
  1160. ;
  1161. }
  1162. }
  1163. else {
  1164. module.verbose('Inline errors are disabled, no inline error added', identifier);
  1165. }
  1166. }
  1167. },
  1168. errors: function(errors) {
  1169. module.debug('Adding form error messages', errors);
  1170. module.set.error();
  1171. $message
  1172. .html( settings.templates.error(errors) )
  1173. ;
  1174. }
  1175. },
  1176. remove: {
  1177. rule: function(field, rule) {
  1178. var
  1179. rules = $.isArray(rule)
  1180. ? rule
  1181. : [rule]
  1182. ;
  1183. if(rule == undefined) {
  1184. module.debug('Removed all rules');
  1185. validation[field].rules = [];
  1186. return;
  1187. }
  1188. if(validation[field] == undefined || !$.isArray(validation[field].rules)) {
  1189. return;
  1190. }
  1191. $.each(validation[field].rules, function(index, rule) {
  1192. if(rules.indexOf(rule.type) !== -1) {
  1193. module.debug('Removed rule', rule.type);
  1194. validation[field].rules.splice(index, 1);
  1195. }
  1196. });
  1197. },
  1198. field: function(field) {
  1199. var
  1200. fields = $.isArray(field)
  1201. ? field
  1202. : [field]
  1203. ;
  1204. $.each(fields, function(index, field) {
  1205. module.remove.rule(field);
  1206. });
  1207. },
  1208. // alias
  1209. rules: function(field, rules) {
  1210. if($.isArray(field)) {
  1211. $.each(fields, function(index, field) {
  1212. module.remove.rule(field, rules);
  1213. });
  1214. }
  1215. else {
  1216. module.remove.rule(field, rules);
  1217. }
  1218. },
  1219. fields: function(fields) {
  1220. module.remove.field(fields);
  1221. },
  1222. prompt: function(identifier) {
  1223. var
  1224. $field = module.get.field(identifier),
  1225. $fieldGroup = $field.closest($group),
  1226. $prompt = $fieldGroup.children(selector.prompt)
  1227. ;
  1228. $fieldGroup
  1229. .removeClass(className.error)
  1230. ;
  1231. if(settings.inline && $prompt.is(':visible')) {
  1232. module.verbose('Removing prompt for field', identifier);
  1233. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  1234. $prompt.transition(settings.transition + ' out', settings.duration, function() {
  1235. $prompt.remove();
  1236. });
  1237. }
  1238. else {
  1239. $prompt
  1240. .fadeOut(settings.duration, function(){
  1241. $prompt.remove();
  1242. })
  1243. ;
  1244. }
  1245. }
  1246. }
  1247. },
  1248. set: {
  1249. success: function() {
  1250. $module
  1251. .removeClass(className.error)
  1252. .addClass(className.success)
  1253. ;
  1254. },
  1255. defaults: function () {
  1256. $field
  1257. .each(function () {
  1258. var
  1259. $field = $(this),
  1260. isCheckbox = ($field.filter(selector.checkbox).length > 0),
  1261. value = (isCheckbox)
  1262. ? $field.is(':checked')
  1263. : $field.val()
  1264. ;
  1265. $field.data(metadata.defaultValue, value);
  1266. })
  1267. ;
  1268. },
  1269. error: function() {
  1270. $module
  1271. .removeClass(className.success)
  1272. .addClass(className.error)
  1273. ;
  1274. },
  1275. value: function (field, value) {
  1276. var
  1277. fields = {}
  1278. ;
  1279. fields[field] = value;
  1280. return module.set.values.call(element, fields);
  1281. },
  1282. values: function (fields) {
  1283. if($.isEmptyObject(fields)) {
  1284. return;
  1285. }
  1286. $.each(fields, function(key, value) {
  1287. var
  1288. $field = module.get.field(key),
  1289. $element = $field.parent(),
  1290. isMultiple = $.isArray(value),
  1291. isCheckbox = $element.is(selector.uiCheckbox),
  1292. isDropdown = $element.is(selector.uiDropdown),
  1293. isRadio = ($field.is(selector.radio) && isCheckbox),
  1294. fieldExists = ($field.length > 0),
  1295. $multipleField
  1296. ;
  1297. if(fieldExists) {
  1298. if(isMultiple && isCheckbox) {
  1299. module.verbose('Selecting multiple', value, $field);
  1300. $element.checkbox('uncheck');
  1301. $.each(value, function(index, value) {
  1302. $multipleField = $field.filter('[value="' + value + '"]');
  1303. $element = $multipleField.parent();
  1304. if($multipleField.length > 0) {
  1305. $element.checkbox('check');
  1306. }
  1307. });
  1308. }
  1309. else if(isRadio) {
  1310. module.verbose('Selecting radio value', value, $field);
  1311. $field.filter('[value="' + value + '"]')
  1312. .parent(selector.uiCheckbox)
  1313. .checkbox('check')
  1314. ;
  1315. }
  1316. else if(isCheckbox) {
  1317. module.verbose('Setting checkbox value', value, $element);
  1318. if(value === true) {
  1319. $element.checkbox('check');
  1320. }
  1321. else {
  1322. $element.checkbox('uncheck');
  1323. }
  1324. }
  1325. else if(isDropdown) {
  1326. module.verbose('Setting dropdown value', value, $element);
  1327. $element.dropdown('set selected', value);
  1328. }
  1329. else {
  1330. module.verbose('Setting field value', value, $field);
  1331. $field.val(value);
  1332. }
  1333. }
  1334. });
  1335. }
  1336. },
  1337. validate: {
  1338. form: function(event, ignoreCallbacks) {
  1339. var
  1340. values = module.get.values(),
  1341. apiRequest
  1342. ;
  1343. // input keydown event will fire submit repeatedly by browser default
  1344. if(keyHeldDown) {
  1345. return false;
  1346. }
  1347. // reset errors
  1348. formErrors = [];
  1349. if( module.determine.isValid() ) {
  1350. module.debug('Form has no validation errors, submitting');
  1351. module.set.success();
  1352. if(ignoreCallbacks !== true) {
  1353. return settings.onSuccess.call(element, event, values);
  1354. }
  1355. }
  1356. else {
  1357. module.debug('Form has errors');
  1358. module.set.error();
  1359. if(!settings.inline) {
  1360. module.add.errors(formErrors);
  1361. }
  1362. // prevent ajax submit
  1363. if($module.data('moduleApi') !== undefined) {
  1364. event.stopImmediatePropagation();
  1365. }
  1366. if(ignoreCallbacks !== true) {
  1367. return settings.onFailure.call(element, formErrors, values);
  1368. }
  1369. }
  1370. },
  1371. // takes a validation object and returns whether field passes validation
  1372. field: function(field, fieldName, showErrors) {
  1373. showErrors = (showErrors !== undefined)
  1374. ? showErrors
  1375. : true
  1376. ;
  1377. if(typeof field == 'string') {
  1378. module.verbose('Validating field', field);
  1379. fieldName = field;
  1380. field = validation[field];
  1381. }
  1382. var
  1383. identifier = field.identifier || fieldName,
  1384. $field = module.get.field(identifier),
  1385. $dependsField = (field.depends)
  1386. ? module.get.field(field.depends)
  1387. : false,
  1388. fieldValid = true,
  1389. fieldErrors = []
  1390. ;
  1391. if(!field.identifier) {
  1392. module.debug('Using field name as identifier', identifier);
  1393. field.identifier = identifier;
  1394. }
  1395. if($field.prop('disabled')) {
  1396. module.debug('Field is disabled. Skipping', identifier);
  1397. fieldValid = true;
  1398. }
  1399. else if(field.optional && module.is.blank($field)){
  1400. module.debug('Field is optional and blank. Skipping', identifier);
  1401. fieldValid = true;
  1402. }
  1403. else if(field.depends && module.is.empty($dependsField)) {
  1404. module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
  1405. fieldValid = true;
  1406. }
  1407. else if(field.rules !== undefined) {
  1408. $.each(field.rules, function(index, rule) {
  1409. if( module.has.field(identifier) && !( module.validate.rule(field, rule) ) ) {
  1410. module.debug('Field is invalid', identifier, rule.type);
  1411. fieldErrors.push(module.get.prompt(rule, field));
  1412. fieldValid = false;
  1413. }
  1414. });
  1415. }
  1416. if(fieldValid) {
  1417. if(showErrors) {
  1418. module.remove.prompt(identifier, fieldErrors);
  1419. settings.onValid.call($field);
  1420. }
  1421. }
  1422. else {
  1423. if(showErrors) {
  1424. formErrors = formErrors.concat(fieldErrors);
  1425. module.add.prompt(identifier, fieldErrors);
  1426. settings.onInvalid.call($field, fieldErrors);
  1427. }
  1428. return false;
  1429. }
  1430. return true;
  1431. },
  1432. // takes validation rule and returns whether field passes rule
  1433. rule: function(field, rule) {
  1434. var
  1435. $field = module.get.field(field.identifier),
  1436. type = rule.type,
  1437. value = $field.val(),
  1438. isValid = true,
  1439. ancillary = module.get.ancillaryValue(rule),
  1440. ruleName = module.get.ruleName(rule),
  1441. ruleFunction = settings.rules[ruleName]
  1442. ;
  1443. if( !$.isFunction(ruleFunction) ) {
  1444. module.error(error.noRule, ruleName);
  1445. return;
  1446. }
  1447. // cast to string avoiding encoding special values
  1448. value = (value === undefined || value === '' || value === null)
  1449. ? ''
  1450. : $.trim(value + '')
  1451. ;
  1452. return ruleFunction.call($field, value, ancillary);
  1453. }
  1454. },
  1455. setting: function(name, value) {
  1456. if( $.isPlainObject(name) ) {
  1457. $.extend(true, settings, name);
  1458. }
  1459. else if(value !== undefined) {
  1460. settings[name] = value;
  1461. }
  1462. else {
  1463. return settings[name];
  1464. }
  1465. },
  1466. internal: function(name, value) {
  1467. if( $.isPlainObject(name) ) {
  1468. $.extend(true, module, name);
  1469. }
  1470. else if(value !== undefined) {
  1471. module[name] = value;
  1472. }
  1473. else {
  1474. return module[name];
  1475. }
  1476. },
  1477. debug: function() {
  1478. if(!settings.silent && settings.debug) {
  1479. if(settings.performance) {
  1480. module.performance.log(arguments);
  1481. }
  1482. else {
  1483. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1484. module.debug.apply(console, arguments);
  1485. }
  1486. }
  1487. },
  1488. verbose: function() {
  1489. if(!settings.silent && settings.verbose && settings.debug) {
  1490. if(settings.performance) {
  1491. module.performance.log(arguments);
  1492. }
  1493. else {
  1494. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1495. module.verbose.apply(console, arguments);
  1496. }
  1497. }
  1498. },
  1499. error: function() {
  1500. if(!settings.silent) {
  1501. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  1502. module.error.apply(console, arguments);
  1503. }
  1504. },
  1505. performance: {
  1506. log: function(message) {
  1507. var
  1508. currentTime,
  1509. executionTime,
  1510. previousTime
  1511. ;
  1512. if(settings.performance) {
  1513. currentTime = new Date().getTime();
  1514. previousTime = time || currentTime;
  1515. executionTime = currentTime - previousTime;
  1516. time = currentTime;
  1517. performance.push({
  1518. 'Name' : message[0],
  1519. 'Arguments' : [].slice.call(message, 1) || '',
  1520. 'Element' : element,
  1521. 'Execution Time' : executionTime
  1522. });
  1523. }
  1524. clearTimeout(module.performance.timer);
  1525. module.performance.timer = setTimeout(module.performance.display, 500);
  1526. },
  1527. display: function() {
  1528. var
  1529. title = settings.name + ':',
  1530. totalTime = 0
  1531. ;
  1532. time = false;
  1533. clearTimeout(module.performance.timer);
  1534. $.each(performance, function(index, data) {
  1535. totalTime += data['Execution Time'];
  1536. });
  1537. title += ' ' + totalTime + 'ms';
  1538. if(moduleSelector) {
  1539. title += ' \'' + moduleSelector + '\'';
  1540. }
  1541. if($allModules.length > 1) {
  1542. title += ' ' + '(' + $allModules.length + ')';
  1543. }
  1544. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  1545. console.groupCollapsed(title);
  1546. if(console.table) {
  1547. console.table(performance);
  1548. }
  1549. else {
  1550. $.each(performance, function(index, data) {
  1551. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  1552. });
  1553. }
  1554. console.groupEnd();
  1555. }
  1556. performance = [];
  1557. }
  1558. },
  1559. invoke: function(query, passedArguments, context) {
  1560. var
  1561. object = instance,
  1562. maxDepth,
  1563. found,
  1564. response
  1565. ;
  1566. passedArguments = passedArguments || queryArguments;
  1567. context = element || context;
  1568. if(typeof query == 'string' && object !== undefined) {
  1569. query = query.split(/[\. ]/);
  1570. maxDepth = query.length - 1;
  1571. $.each(query, function(depth, value) {
  1572. var camelCaseValue = (depth != maxDepth)
  1573. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  1574. : query
  1575. ;
  1576. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  1577. object = object[camelCaseValue];
  1578. }
  1579. else if( object[camelCaseValue] !== undefined ) {
  1580. found = object[camelCaseValue];
  1581. return false;
  1582. }
  1583. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  1584. object = object[value];
  1585. }
  1586. else if( object[value] !== undefined ) {
  1587. found = object[value];
  1588. return false;
  1589. }
  1590. else {
  1591. return false;
  1592. }
  1593. });
  1594. }
  1595. if( $.isFunction( found ) ) {
  1596. response = found.apply(context, passedArguments);
  1597. }
  1598. else if(found !== undefined) {
  1599. response = found;
  1600. }
  1601. if($.isArray(returnedValue)) {
  1602. returnedValue.push(response);
  1603. }
  1604. else if(returnedValue !== undefined) {
  1605. returnedValue = [returnedValue, response];
  1606. }
  1607. else if(response !== undefined) {
  1608. returnedValue = response;
  1609. }
  1610. return found;
  1611. }
  1612. };
  1613. module.initialize();
  1614. })
  1615. ;
  1616. return (returnedValue !== undefined)
  1617. ? returnedValue
  1618. : this
  1619. ;
  1620. };
  1621. $.fn.form.settings = {
  1622. name : 'Form',
  1623. namespace : 'form',
  1624. debug : false,
  1625. verbose : false,
  1626. performance : true,
  1627. fields : false,
  1628. keyboardShortcuts : true,
  1629. on : 'submit',
  1630. inline : false,
  1631. delay : 200,
  1632. revalidate : true,
  1633. transition : 'scale',
  1634. duration : 200,
  1635. onValid : function() {},
  1636. onInvalid : function() {},
  1637. onSuccess : function() { return true; },
  1638. onFailure : function() { return false; },
  1639. metadata : {
  1640. defaultValue : 'default',
  1641. validate : 'validate'
  1642. },
  1643. regExp: {
  1644. htmlID : /^[a-zA-Z][\w:.-]*$/g,
  1645. bracket : /\[(.*)\]/i,
  1646. decimal : /^\d+\.?\d*$/,
  1647. email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
  1648. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  1649. flags : /^\/(.*)\/(.*)?/,
  1650. integer : /^\-?\d+$/,
  1651. number : /^\-?\d*(\.\d+)?$/,
  1652. url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
  1653. },
  1654. text: {
  1655. unspecifiedRule : 'Please enter a valid value',
  1656. unspecifiedField : 'This field'
  1657. },
  1658. prompt: {
  1659. empty : '{name} must have a value',
  1660. checked : '{name} must be checked',
  1661. email : '{name} must be a valid e-mail',
  1662. url : '{name} must be a valid url',
  1663. regExp : '{name} is not formatted correctly',
  1664. integer : '{name} must be an integer',
  1665. decimal : '{name} must be a decimal number',
  1666. number : '{name} must be set to a number',
  1667. is : '{name} must be "{ruleValue}"',
  1668. isExactly : '{name} must be exactly "{ruleValue}"',
  1669. not : '{name} cannot be set to "{ruleValue}"',
  1670. notExactly : '{name} cannot be set to exactly "{ruleValue}"',
  1671. contain : '{name} must contain "{ruleValue}"',
  1672. containExactly : '{name} must contain exactly "{ruleValue}"',
  1673. doesntContain : '{name} cannot contain "{ruleValue}"',
  1674. doesntContainExactly : '{name} cannot contain exactly "{ruleValue}"',
  1675. minLength : '{name} must be at least {ruleValue} characters',
  1676. length : '{name} must be at least {ruleValue} characters',
  1677. exactLength : '{name} must be exactly {ruleValue} characters',
  1678. maxLength : '{name} cannot be longer than {ruleValue} characters',
  1679. match : '{name} must match {ruleValue} field',
  1680. different : '{name} must have a different value than {ruleValue} field',
  1681. creditCard : '{name} must be a valid credit card number',
  1682. minCount : '{name} must have at least {ruleValue} choices',
  1683. exactCount : '{name} must have exactly {ruleValue} choices',
  1684. maxCount : '{name} must have {ruleValue} or less choices'
  1685. },
  1686. selector : {
  1687. checkbox : 'input[type="checkbox"], input[type="radio"]',
  1688. clear : '.clear',
  1689. field : 'input, textarea, select',
  1690. group : '.field',
  1691. input : 'input',
  1692. message : '.error.message',
  1693. prompt : '.prompt.label',
  1694. radio : 'input[type="radio"]',
  1695. reset : '.reset:not([type="reset"])',
  1696. submit : '.submit:not([type="submit"])',
  1697. uiCheckbox : '.ui.checkbox',
  1698. uiDropdown : '.ui.dropdown'
  1699. },
  1700. className : {
  1701. error : 'error',
  1702. label : 'ui prompt label',
  1703. pressed : 'down',
  1704. success : 'success'
  1705. },
  1706. error: {
  1707. identifier : 'You must specify a string identifier for each field',
  1708. method : 'The method you called is not defined.',
  1709. noRule : 'There is no rule matching the one you specified',
  1710. oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.'
  1711. },
  1712. templates: {
  1713. // template that produces error message
  1714. error: function(errors) {
  1715. var
  1716. html = '<ul class="list">'
  1717. ;
  1718. $.each(errors, function(index, value) {
  1719. html += '<li>' + value + '</li>';
  1720. });
  1721. html += '</ul>';
  1722. return $(html);
  1723. },
  1724. // template that produces label
  1725. prompt: function(errors) {
  1726. return $('<div/>')
  1727. .addClass('ui basic red pointing prompt label')
  1728. .html(errors[0])
  1729. ;
  1730. }
  1731. },
  1732. rules: {
  1733. // is not empty or blank string
  1734. empty: function(value) {
  1735. return !(value === undefined || '' === value || $.isArray(value) && value.length === 0);
  1736. },
  1737. // checkbox checked
  1738. checked: function() {
  1739. return ($(this).filter(':checked').length > 0);
  1740. },
  1741. // is most likely an email
  1742. email: function(value){
  1743. return $.fn.form.settings.regExp.email.test(value);
  1744. },
  1745. // value is most likely url
  1746. url: function(value) {
  1747. return $.fn.form.settings.regExp.url.test(value);
  1748. },
  1749. // matches specified regExp
  1750. regExp: function(value, regExp) {
  1751. if(regExp instanceof RegExp) {
  1752. return value.match(regExp);
  1753. }
  1754. var
  1755. regExpParts = regExp.match($.fn.form.settings.regExp.flags),
  1756. flags
  1757. ;
  1758. // regular expression specified as /baz/gi (flags)
  1759. if(regExpParts) {
  1760. regExp = (regExpParts.length >= 2)
  1761. ? regExpParts[1]
  1762. : regExp
  1763. ;
  1764. flags = (regExpParts.length >= 3)
  1765. ? regExpParts[2]
  1766. : ''
  1767. ;
  1768. }
  1769. return value.match( new RegExp(regExp, flags) );
  1770. },
  1771. // is valid integer or matches range
  1772. integer: function(value, range) {
  1773. var
  1774. intRegExp = $.fn.form.settings.regExp.integer,
  1775. min,
  1776. max,
  1777. parts
  1778. ;
  1779. if( !range || ['', '..'].indexOf(range) !== -1) {
  1780. // do nothing
  1781. }
  1782. else if(range.indexOf('..') == -1) {
  1783. if(intRegExp.test(range)) {
  1784. min = max = range - 0;
  1785. }
  1786. }
  1787. else {
  1788. parts = range.split('..', 2);
  1789. if(intRegExp.test(parts[0])) {
  1790. min = parts[0] - 0;
  1791. }
  1792. if(intRegExp.test(parts[1])) {
  1793. max = parts[1] - 0;
  1794. }
  1795. }
  1796. return (
  1797. intRegExp.test(value) &&
  1798. (min === undefined || value >= min) &&
  1799. (max === undefined || value <= max)
  1800. );
  1801. },
  1802. // is valid number (with decimal)
  1803. decimal: function(value) {
  1804. return $.fn.form.settings.regExp.decimal.test(value);
  1805. },
  1806. // is valid number
  1807. number: function(value) {
  1808. return $.fn.form.settings.regExp.number.test(value);
  1809. },
  1810. // is value (case insensitive)
  1811. is: function(value, text) {
  1812. text = (typeof text == 'string')
  1813. ? text.toLowerCase()
  1814. : text
  1815. ;
  1816. value = (typeof value == 'string')
  1817. ? value.toLowerCase()
  1818. : value
  1819. ;
  1820. return (value == text);
  1821. },
  1822. // is value
  1823. isExactly: function(value, text) {
  1824. return (value == text);
  1825. },
  1826. // value is not another value (case insensitive)
  1827. not: function(value, notValue) {
  1828. value = (typeof value == 'string')
  1829. ? value.toLowerCase()
  1830. : value
  1831. ;
  1832. notValue = (typeof notValue == 'string')
  1833. ? notValue.toLowerCase()
  1834. : notValue
  1835. ;
  1836. return (value != notValue);
  1837. },
  1838. // value is not another value (case sensitive)
  1839. notExactly: function(value, notValue) {
  1840. return (value != notValue);
  1841. },
  1842. // value contains text (insensitive)
  1843. contains: function(value, text) {
  1844. // escape regex characters
  1845. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1846. return (value.search( new RegExp(text, 'i') ) !== -1);
  1847. },
  1848. // value contains text (case sensitive)
  1849. containsExactly: function(value, text) {
  1850. // escape regex characters
  1851. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1852. return (value.search( new RegExp(text) ) !== -1);
  1853. },
  1854. // value contains text (insensitive)
  1855. doesntContain: function(value, text) {
  1856. // escape regex characters
  1857. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1858. return (value.search( new RegExp(text, 'i') ) === -1);
  1859. },
  1860. // value contains text (case sensitive)
  1861. doesntContainExactly: function(value, text) {
  1862. // escape regex characters
  1863. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1864. return (value.search( new RegExp(text) ) === -1);
  1865. },
  1866. // is at least string length
  1867. minLength: function(value, requiredLength) {
  1868. return (value !== undefined)
  1869. ? (value.length >= requiredLength)
  1870. : false
  1871. ;
  1872. },
  1873. // see rls notes for 2.0.6 (this is a duplicate of minLength)
  1874. length: function(value, requiredLength) {
  1875. return (value !== undefined)
  1876. ? (value.length >= requiredLength)
  1877. : false
  1878. ;
  1879. },
  1880. // is exactly length
  1881. exactLength: function(value, requiredLength) {
  1882. return (value !== undefined)
  1883. ? (value.length == requiredLength)
  1884. : false
  1885. ;
  1886. },
  1887. // is less than length
  1888. maxLength: function(value, maxLength) {
  1889. return (value !== undefined)
  1890. ? (value.length <= maxLength)
  1891. : false
  1892. ;
  1893. },
  1894. // matches another field
  1895. match: function(value, identifier) {
  1896. var
  1897. $form = $(this),
  1898. matchingValue
  1899. ;
  1900. if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
  1901. matchingValue = $('[data-validate="'+ identifier +'"]').val();
  1902. }
  1903. else if($('#' + identifier).length > 0) {
  1904. matchingValue = $('#' + identifier).val();
  1905. }
  1906. else if($('[name="' + identifier +'"]').length > 0) {
  1907. matchingValue = $('[name="' + identifier + '"]').val();
  1908. }
  1909. else if( $('[name="' + identifier +'[]"]').length > 0 ) {
  1910. matchingValue = $('[name="' + identifier +'[]"]');
  1911. }
  1912. return (matchingValue !== undefined)
  1913. ? ( value.toString() == matchingValue.toString() )
  1914. : false
  1915. ;
  1916. },
  1917. // different than another field
  1918. different: function(value, identifier) {
  1919. // use either id or name of field
  1920. var
  1921. $form = $(this),
  1922. matchingValue
  1923. ;
  1924. if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
  1925. matchingValue = $('[data-validate="'+ identifier +'"]').val();
  1926. }
  1927. else if($('#' + identifier).length > 0) {
  1928. matchingValue = $('#' + identifier).val();
  1929. }
  1930. else if($('[name="' + identifier +'"]').length > 0) {
  1931. matchingValue = $('[name="' + identifier + '"]').val();
  1932. }
  1933. else if( $('[name="' + identifier +'[]"]').length > 0 ) {
  1934. matchingValue = $('[name="' + identifier +'[]"]');
  1935. }
  1936. return (matchingValue !== undefined)
  1937. ? ( value.toString() !== matchingValue.toString() )
  1938. : false
  1939. ;
  1940. },
  1941. creditCard: function(cardNumber, cardTypes) {
  1942. var
  1943. cards = {
  1944. visa: {
  1945. pattern : /^4/,
  1946. length : [16]
  1947. },
  1948. amex: {
  1949. pattern : /^3[47]/,
  1950. length : [15]
  1951. },
  1952. mastercard: {
  1953. pattern : /^5[1-5]/,
  1954. length : [16]
  1955. },
  1956. discover: {
  1957. 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)/,
  1958. length : [16]
  1959. },
  1960. unionPay: {
  1961. pattern : /^(62|88)/,
  1962. length : [16, 17, 18, 19]
  1963. },
  1964. jcb: {
  1965. pattern : /^35(2[89]|[3-8][0-9])/,
  1966. length : [16]
  1967. },
  1968. maestro: {
  1969. pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
  1970. length : [12, 13, 14, 15, 16, 17, 18, 19]
  1971. },
  1972. dinersClub: {
  1973. pattern : /^(30[0-5]|^36)/,
  1974. length : [14]
  1975. },
  1976. laser: {
  1977. pattern : /^(6304|670[69]|6771)/,
  1978. length : [16, 17, 18, 19]
  1979. },
  1980. visaElectron: {
  1981. pattern : /^(4026|417500|4508|4844|491(3|7))/,
  1982. length : [16]
  1983. }
  1984. },
  1985. valid = {},
  1986. validCard = false,
  1987. requiredTypes = (typeof cardTypes == 'string')
  1988. ? cardTypes.split(',')
  1989. : false,
  1990. unionPay,
  1991. validation
  1992. ;
  1993. if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
  1994. return;
  1995. }
  1996. // allow dashes in card
  1997. cardNumber = cardNumber.replace(/[\-]/g, '');
  1998. // verify card types
  1999. if(requiredTypes) {
  2000. $.each(requiredTypes, function(index, type){
  2001. // verify each card type
  2002. validation = cards[type];
  2003. if(validation) {
  2004. valid = {
  2005. length : ($.inArray(cardNumber.length, validation.length) !== -1),
  2006. pattern : (cardNumber.search(validation.pattern) !== -1)
  2007. };
  2008. if(valid.length && valid.pattern) {
  2009. validCard = true;
  2010. }
  2011. }
  2012. });
  2013. if(!validCard) {
  2014. return false;
  2015. }
  2016. }
  2017. // skip luhn for UnionPay
  2018. unionPay = {
  2019. number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
  2020. pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
  2021. };
  2022. if(unionPay.number && unionPay.pattern) {
  2023. return true;
  2024. }
  2025. // verify luhn, adapted from <https://gist.github.com/2134376>
  2026. var
  2027. length = cardNumber.length,
  2028. multiple = 0,
  2029. producedValue = [
  2030. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
  2031. [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
  2032. ],
  2033. sum = 0
  2034. ;
  2035. while (length--) {
  2036. sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
  2037. multiple ^= 1;
  2038. }
  2039. return (sum % 10 === 0 && sum > 0);
  2040. },
  2041. minCount: function(value, minCount) {
  2042. if(minCount == 0) {
  2043. return true;
  2044. }
  2045. if(minCount == 1) {
  2046. return (value !== '');
  2047. }
  2048. return (value.split(',').length >= minCount);
  2049. },
  2050. exactCount: function(value, exactCount) {
  2051. if(exactCount == 0) {
  2052. return (value === '');
  2053. }
  2054. if(exactCount == 1) {
  2055. return (value !== '' && value.search(',') === -1);
  2056. }
  2057. return (value.split(',').length == exactCount);
  2058. },
  2059. maxCount: function(value, maxCount) {
  2060. if(maxCount == 0) {
  2061. return false;
  2062. }
  2063. if(maxCount == 1) {
  2064. return (value.search(',') === -1);
  2065. }
  2066. return (value.split(',').length <= maxCount);
  2067. }
  2068. }
  2069. };
  2070. })( jQuery, window, document );
  2071. /*!
  2072. * # Semantic UI 2.3.3 - Accordion
  2073. * http://github.com/semantic-org/semantic-ui/
  2074. *
  2075. *
  2076. * Released under the MIT license
  2077. * http://opensource.org/licenses/MIT
  2078. *
  2079. */
  2080. ;(function ($, window, document, undefined) {
  2081. 'use strict';
  2082. window = (typeof window != 'undefined' && window.Math == Math)
  2083. ? window
  2084. : (typeof self != 'undefined' && self.Math == Math)
  2085. ? self
  2086. : Function('return this')()
  2087. ;
  2088. $.fn.accordion = function(parameters) {
  2089. var
  2090. $allModules = $(this),
  2091. time = new Date().getTime(),
  2092. performance = [],
  2093. query = arguments[0],
  2094. methodInvoked = (typeof query == 'string'),
  2095. queryArguments = [].slice.call(arguments, 1),
  2096. requestAnimationFrame = window.requestAnimationFrame
  2097. || window.mozRequestAnimationFrame
  2098. || window.webkitRequestAnimationFrame
  2099. || window.msRequestAnimationFrame
  2100. || function(callback) { setTimeout(callback, 0); },
  2101. returnedValue
  2102. ;
  2103. $allModules
  2104. .each(function() {
  2105. var
  2106. settings = ( $.isPlainObject(parameters) )
  2107. ? $.extend(true, {}, $.fn.accordion.settings, parameters)
  2108. : $.extend({}, $.fn.accordion.settings),
  2109. className = settings.className,
  2110. namespace = settings.namespace,
  2111. selector = settings.selector,
  2112. error = settings.error,
  2113. eventNamespace = '.' + namespace,
  2114. moduleNamespace = 'module-' + namespace,
  2115. moduleSelector = $allModules.selector || '',
  2116. $module = $(this),
  2117. $title = $module.find(selector.title),
  2118. $content = $module.find(selector.content),
  2119. element = this,
  2120. instance = $module.data(moduleNamespace),
  2121. observer,
  2122. module
  2123. ;
  2124. module = {
  2125. initialize: function() {
  2126. module.debug('Initializing', $module);
  2127. module.bind.events();
  2128. if(settings.observeChanges) {
  2129. module.observeChanges();
  2130. }
  2131. module.instantiate();
  2132. },
  2133. instantiate: function() {
  2134. instance = module;
  2135. $module
  2136. .data(moduleNamespace, module)
  2137. ;
  2138. },
  2139. destroy: function() {
  2140. module.debug('Destroying previous instance', $module);
  2141. $module
  2142. .off(eventNamespace)
  2143. .removeData(moduleNamespace)
  2144. ;
  2145. },
  2146. refresh: function() {
  2147. $title = $module.find(selector.title);
  2148. $content = $module.find(selector.content);
  2149. },
  2150. observeChanges: function() {
  2151. if('MutationObserver' in window) {
  2152. observer = new MutationObserver(function(mutations) {
  2153. module.debug('DOM tree modified, updating selector cache');
  2154. module.refresh();
  2155. });
  2156. observer.observe(element, {
  2157. childList : true,
  2158. subtree : true
  2159. });
  2160. module.debug('Setting up mutation observer', observer);
  2161. }
  2162. },
  2163. bind: {
  2164. events: function() {
  2165. module.debug('Binding delegated events');
  2166. $module
  2167. .on(settings.on + eventNamespace, selector.trigger, module.event.click)
  2168. ;
  2169. }
  2170. },
  2171. event: {
  2172. click: function() {
  2173. module.toggle.call(this);
  2174. }
  2175. },
  2176. toggle: function(query) {
  2177. var
  2178. $activeTitle = (query !== undefined)
  2179. ? (typeof query === 'number')
  2180. ? $title.eq(query)
  2181. : $(query).closest(selector.title)
  2182. : $(this).closest(selector.title),
  2183. $activeContent = $activeTitle.next($content),
  2184. isAnimating = $activeContent.hasClass(className.animating),
  2185. isActive = $activeContent.hasClass(className.active),
  2186. isOpen = (isActive && !isAnimating),
  2187. isOpening = (!isActive && isAnimating)
  2188. ;
  2189. module.debug('Toggling visibility of content', $activeTitle);
  2190. if(isOpen || isOpening) {
  2191. if(settings.collapsible) {
  2192. module.close.call($activeTitle);
  2193. }
  2194. else {
  2195. module.debug('Cannot close accordion content collapsing is disabled');
  2196. }
  2197. }
  2198. else {
  2199. module.open.call($activeTitle);
  2200. }
  2201. },
  2202. open: function(query) {
  2203. var
  2204. $activeTitle = (query !== undefined)
  2205. ? (typeof query === 'number')
  2206. ? $title.eq(query)
  2207. : $(query).closest(selector.title)
  2208. : $(this).closest(selector.title),
  2209. $activeContent = $activeTitle.next($content),
  2210. isAnimating = $activeContent.hasClass(className.animating),
  2211. isActive = $activeContent.hasClass(className.active),
  2212. isOpen = (isActive || isAnimating)
  2213. ;
  2214. if(isOpen) {
  2215. module.debug('Accordion already open, skipping', $activeContent);
  2216. return;
  2217. }
  2218. module.debug('Opening accordion content', $activeTitle);
  2219. settings.onOpening.call($activeContent);
  2220. settings.onChanging.call($activeContent);
  2221. if(settings.exclusive) {
  2222. module.closeOthers.call($activeTitle);
  2223. }
  2224. $activeTitle
  2225. .addClass(className.active)
  2226. ;
  2227. $activeContent
  2228. .stop(true, true)
  2229. .addClass(className.animating)
  2230. ;
  2231. if(settings.animateChildren) {
  2232. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2233. $activeContent
  2234. .children()
  2235. .transition({
  2236. animation : 'fade in',
  2237. queue : false,
  2238. useFailSafe : true,
  2239. debug : settings.debug,
  2240. verbose : settings.verbose,
  2241. duration : settings.duration
  2242. })
  2243. ;
  2244. }
  2245. else {
  2246. $activeContent
  2247. .children()
  2248. .stop(true, true)
  2249. .animate({
  2250. opacity: 1
  2251. }, settings.duration, module.resetOpacity)
  2252. ;
  2253. }
  2254. }
  2255. $activeContent
  2256. .slideDown(settings.duration, settings.easing, function() {
  2257. $activeContent
  2258. .removeClass(className.animating)
  2259. .addClass(className.active)
  2260. ;
  2261. module.reset.display.call(this);
  2262. settings.onOpen.call(this);
  2263. settings.onChange.call(this);
  2264. })
  2265. ;
  2266. },
  2267. close: function(query) {
  2268. var
  2269. $activeTitle = (query !== undefined)
  2270. ? (typeof query === 'number')
  2271. ? $title.eq(query)
  2272. : $(query).closest(selector.title)
  2273. : $(this).closest(selector.title),
  2274. $activeContent = $activeTitle.next($content),
  2275. isAnimating = $activeContent.hasClass(className.animating),
  2276. isActive = $activeContent.hasClass(className.active),
  2277. isOpening = (!isActive && isAnimating),
  2278. isClosing = (isActive && isAnimating)
  2279. ;
  2280. if((isActive || isOpening) && !isClosing) {
  2281. module.debug('Closing accordion content', $activeContent);
  2282. settings.onClosing.call($activeContent);
  2283. settings.onChanging.call($activeContent);
  2284. $activeTitle
  2285. .removeClass(className.active)
  2286. ;
  2287. $activeContent
  2288. .stop(true, true)
  2289. .addClass(className.animating)
  2290. ;
  2291. if(settings.animateChildren) {
  2292. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2293. $activeContent
  2294. .children()
  2295. .transition({
  2296. animation : 'fade out',
  2297. queue : false,
  2298. useFailSafe : true,
  2299. debug : settings.debug,
  2300. verbose : settings.verbose,
  2301. duration : settings.duration
  2302. })
  2303. ;
  2304. }
  2305. else {
  2306. $activeContent
  2307. .children()
  2308. .stop(true, true)
  2309. .animate({
  2310. opacity: 0
  2311. }, settings.duration, module.resetOpacity)
  2312. ;
  2313. }
  2314. }
  2315. $activeContent
  2316. .slideUp(settings.duration, settings.easing, function() {
  2317. $activeContent
  2318. .removeClass(className.animating)
  2319. .removeClass(className.active)
  2320. ;
  2321. module.reset.display.call(this);
  2322. settings.onClose.call(this);
  2323. settings.onChange.call(this);
  2324. })
  2325. ;
  2326. }
  2327. },
  2328. closeOthers: function(index) {
  2329. var
  2330. $activeTitle = (index !== undefined)
  2331. ? $title.eq(index)
  2332. : $(this).closest(selector.title),
  2333. $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
  2334. $activeAccordion = $activeTitle.closest(selector.accordion),
  2335. activeSelector = selector.title + '.' + className.active + ':visible',
  2336. activeContent = selector.content + '.' + className.active + ':visible',
  2337. $openTitles,
  2338. $nestedTitles,
  2339. $openContents
  2340. ;
  2341. if(settings.closeNested) {
  2342. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2343. $openContents = $openTitles.next($content);
  2344. }
  2345. else {
  2346. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2347. $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
  2348. $openTitles = $openTitles.not($nestedTitles);
  2349. $openContents = $openTitles.next($content);
  2350. }
  2351. if( ($openTitles.length > 0) ) {
  2352. module.debug('Exclusive enabled, closing other content', $openTitles);
  2353. $openTitles
  2354. .removeClass(className.active)
  2355. ;
  2356. $openContents
  2357. .removeClass(className.animating)
  2358. .stop(true, true)
  2359. ;
  2360. if(settings.animateChildren) {
  2361. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2362. $openContents
  2363. .children()
  2364. .transition({
  2365. animation : 'fade out',
  2366. useFailSafe : true,
  2367. debug : settings.debug,
  2368. verbose : settings.verbose,
  2369. duration : settings.duration
  2370. })
  2371. ;
  2372. }
  2373. else {
  2374. $openContents
  2375. .children()
  2376. .stop(true, true)
  2377. .animate({
  2378. opacity: 0
  2379. }, settings.duration, module.resetOpacity)
  2380. ;
  2381. }
  2382. }
  2383. $openContents
  2384. .slideUp(settings.duration , settings.easing, function() {
  2385. $(this).removeClass(className.active);
  2386. module.reset.display.call(this);
  2387. })
  2388. ;
  2389. }
  2390. },
  2391. reset: {
  2392. display: function() {
  2393. module.verbose('Removing inline display from element', this);
  2394. $(this).css('display', '');
  2395. if( $(this).attr('style') === '') {
  2396. $(this)
  2397. .attr('style', '')
  2398. .removeAttr('style')
  2399. ;
  2400. }
  2401. },
  2402. opacity: function() {
  2403. module.verbose('Removing inline opacity from element', this);
  2404. $(this).css('opacity', '');
  2405. if( $(this).attr('style') === '') {
  2406. $(this)
  2407. .attr('style', '')
  2408. .removeAttr('style')
  2409. ;
  2410. }
  2411. },
  2412. },
  2413. setting: function(name, value) {
  2414. module.debug('Changing setting', name, value);
  2415. if( $.isPlainObject(name) ) {
  2416. $.extend(true, settings, name);
  2417. }
  2418. else if(value !== undefined) {
  2419. if($.isPlainObject(settings[name])) {
  2420. $.extend(true, settings[name], value);
  2421. }
  2422. else {
  2423. settings[name] = value;
  2424. }
  2425. }
  2426. else {
  2427. return settings[name];
  2428. }
  2429. },
  2430. internal: function(name, value) {
  2431. module.debug('Changing internal', name, value);
  2432. if(value !== undefined) {
  2433. if( $.isPlainObject(name) ) {
  2434. $.extend(true, module, name);
  2435. }
  2436. else {
  2437. module[name] = value;
  2438. }
  2439. }
  2440. else {
  2441. return module[name];
  2442. }
  2443. },
  2444. debug: function() {
  2445. if(!settings.silent && settings.debug) {
  2446. if(settings.performance) {
  2447. module.performance.log(arguments);
  2448. }
  2449. else {
  2450. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2451. module.debug.apply(console, arguments);
  2452. }
  2453. }
  2454. },
  2455. verbose: function() {
  2456. if(!settings.silent && settings.verbose && settings.debug) {
  2457. if(settings.performance) {
  2458. module.performance.log(arguments);
  2459. }
  2460. else {
  2461. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2462. module.verbose.apply(console, arguments);
  2463. }
  2464. }
  2465. },
  2466. error: function() {
  2467. if(!settings.silent) {
  2468. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  2469. module.error.apply(console, arguments);
  2470. }
  2471. },
  2472. performance: {
  2473. log: function(message) {
  2474. var
  2475. currentTime,
  2476. executionTime,
  2477. previousTime
  2478. ;
  2479. if(settings.performance) {
  2480. currentTime = new Date().getTime();
  2481. previousTime = time || currentTime;
  2482. executionTime = currentTime - previousTime;
  2483. time = currentTime;
  2484. performance.push({
  2485. 'Name' : message[0],
  2486. 'Arguments' : [].slice.call(message, 1) || '',
  2487. 'Element' : element,
  2488. 'Execution Time' : executionTime
  2489. });
  2490. }
  2491. clearTimeout(module.performance.timer);
  2492. module.performance.timer = setTimeout(module.performance.display, 500);
  2493. },
  2494. display: function() {
  2495. var
  2496. title = settings.name + ':',
  2497. totalTime = 0
  2498. ;
  2499. time = false;
  2500. clearTimeout(module.performance.timer);
  2501. $.each(performance, function(index, data) {
  2502. totalTime += data['Execution Time'];
  2503. });
  2504. title += ' ' + totalTime + 'ms';
  2505. if(moduleSelector) {
  2506. title += ' \'' + moduleSelector + '\'';
  2507. }
  2508. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  2509. console.groupCollapsed(title);
  2510. if(console.table) {
  2511. console.table(performance);
  2512. }
  2513. else {
  2514. $.each(performance, function(index, data) {
  2515. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  2516. });
  2517. }
  2518. console.groupEnd();
  2519. }
  2520. performance = [];
  2521. }
  2522. },
  2523. invoke: function(query, passedArguments, context) {
  2524. var
  2525. object = instance,
  2526. maxDepth,
  2527. found,
  2528. response
  2529. ;
  2530. passedArguments = passedArguments || queryArguments;
  2531. context = element || context;
  2532. if(typeof query == 'string' && object !== undefined) {
  2533. query = query.split(/[\. ]/);
  2534. maxDepth = query.length - 1;
  2535. $.each(query, function(depth, value) {
  2536. var camelCaseValue = (depth != maxDepth)
  2537. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  2538. : query
  2539. ;
  2540. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  2541. object = object[camelCaseValue];
  2542. }
  2543. else if( object[camelCaseValue] !== undefined ) {
  2544. found = object[camelCaseValue];
  2545. return false;
  2546. }
  2547. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  2548. object = object[value];
  2549. }
  2550. else if( object[value] !== undefined ) {
  2551. found = object[value];
  2552. return false;
  2553. }
  2554. else {
  2555. module.error(error.method, query);
  2556. return false;
  2557. }
  2558. });
  2559. }
  2560. if ( $.isFunction( found ) ) {
  2561. response = found.apply(context, passedArguments);
  2562. }
  2563. else if(found !== undefined) {
  2564. response = found;
  2565. }
  2566. if($.isArray(returnedValue)) {
  2567. returnedValue.push(response);
  2568. }
  2569. else if(returnedValue !== undefined) {
  2570. returnedValue = [returnedValue, response];
  2571. }
  2572. else if(response !== undefined) {
  2573. returnedValue = response;
  2574. }
  2575. return found;
  2576. }
  2577. };
  2578. if(methodInvoked) {
  2579. if(instance === undefined) {
  2580. module.initialize();
  2581. }
  2582. module.invoke(query);
  2583. }
  2584. else {
  2585. if(instance !== undefined) {
  2586. instance.invoke('destroy');
  2587. }
  2588. module.initialize();
  2589. }
  2590. })
  2591. ;
  2592. return (returnedValue !== undefined)
  2593. ? returnedValue
  2594. : this
  2595. ;
  2596. };
  2597. $.fn.accordion.settings = {
  2598. name : 'Accordion',
  2599. namespace : 'accordion',
  2600. silent : false,
  2601. debug : false,
  2602. verbose : false,
  2603. performance : true,
  2604. on : 'click', // event on title that opens accordion
  2605. observeChanges : true, // whether accordion should automatically refresh on DOM insertion
  2606. exclusive : true, // whether a single accordion content panel should be open at once
  2607. collapsible : true, // whether accordion content can be closed
  2608. closeNested : false, // whether nested content should be closed when a panel is closed
  2609. animateChildren : true, // whether children opacity should be animated
  2610. duration : 350, // duration of animation
  2611. easing : 'easeOutQuad', // easing equation for animation
  2612. onOpening : function(){}, // callback before open animation
  2613. onClosing : function(){}, // callback before closing animation
  2614. onChanging : function(){}, // callback before closing or opening animation
  2615. onOpen : function(){}, // callback after open animation
  2616. onClose : function(){}, // callback after closing animation
  2617. onChange : function(){}, // callback after closing or opening animation
  2618. error: {
  2619. method : 'The method you called is not defined'
  2620. },
  2621. className : {
  2622. active : 'active',
  2623. animating : 'animating'
  2624. },
  2625. selector : {
  2626. accordion : '.accordion',
  2627. title : '.title',
  2628. trigger : '.title',
  2629. content : '.content'
  2630. }
  2631. };
  2632. // Adds easing
  2633. $.extend( $.easing, {
  2634. easeOutQuad: function (x, t, b, c, d) {
  2635. return -c *(t/=d)*(t-2) + b;
  2636. }
  2637. });
  2638. })( jQuery, window, document );
  2639. /*!
  2640. * # Semantic UI 2.3.3 - Checkbox
  2641. * http://github.com/semantic-org/semantic-ui/
  2642. *
  2643. *
  2644. * Released under the MIT license
  2645. * http://opensource.org/licenses/MIT
  2646. *
  2647. */
  2648. ;(function ($, window, document, undefined) {
  2649. 'use strict';
  2650. window = (typeof window != 'undefined' && window.Math == Math)
  2651. ? window
  2652. : (typeof self != 'undefined' && self.Math == Math)
  2653. ? self
  2654. : Function('return this')()
  2655. ;
  2656. $.fn.checkbox = function(parameters) {
  2657. var
  2658. $allModules = $(this),
  2659. moduleSelector = $allModules.selector || '',
  2660. time = new Date().getTime(),
  2661. performance = [],
  2662. query = arguments[0],
  2663. methodInvoked = (typeof query == 'string'),
  2664. queryArguments = [].slice.call(arguments, 1),
  2665. returnedValue
  2666. ;
  2667. $allModules
  2668. .each(function() {
  2669. var
  2670. settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
  2671. className = settings.className,
  2672. namespace = settings.namespace,
  2673. selector = settings.selector,
  2674. error = settings.error,
  2675. eventNamespace = '.' + namespace,
  2676. moduleNamespace = 'module-' + namespace,
  2677. $module = $(this),
  2678. $label = $(this).children(selector.label),
  2679. $input = $(this).children(selector.input),
  2680. input = $input[0],
  2681. initialLoad = false,
  2682. shortcutPressed = false,
  2683. instance = $module.data(moduleNamespace),
  2684. observer,
  2685. element = this,
  2686. module
  2687. ;
  2688. module = {
  2689. initialize: function() {
  2690. module.verbose('Initializing checkbox', settings);
  2691. module.create.label();
  2692. module.bind.events();
  2693. module.set.tabbable();
  2694. module.hide.input();
  2695. module.observeChanges();
  2696. module.instantiate();
  2697. module.setup();
  2698. },
  2699. instantiate: function() {
  2700. module.verbose('Storing instance of module', module);
  2701. instance = module;
  2702. $module
  2703. .data(moduleNamespace, module)
  2704. ;
  2705. },
  2706. destroy: function() {
  2707. module.verbose('Destroying module');
  2708. module.unbind.events();
  2709. module.show.input();
  2710. $module.removeData(moduleNamespace);
  2711. },
  2712. fix: {
  2713. reference: function() {
  2714. if( $module.is(selector.input) ) {
  2715. module.debug('Behavior called on <input> adjusting invoked element');
  2716. $module = $module.closest(selector.checkbox);
  2717. module.refresh();
  2718. }
  2719. }
  2720. },
  2721. setup: function() {
  2722. module.set.initialLoad();
  2723. if( module.is.indeterminate() ) {
  2724. module.debug('Initial value is indeterminate');
  2725. module.indeterminate();
  2726. }
  2727. else if( module.is.checked() ) {
  2728. module.debug('Initial value is checked');
  2729. module.check();
  2730. }
  2731. else {
  2732. module.debug('Initial value is unchecked');
  2733. module.uncheck();
  2734. }
  2735. module.remove.initialLoad();
  2736. },
  2737. refresh: function() {
  2738. $label = $module.children(selector.label);
  2739. $input = $module.children(selector.input);
  2740. input = $input[0];
  2741. },
  2742. hide: {
  2743. input: function() {
  2744. module.verbose('Modifying <input> z-index to be unselectable');
  2745. $input.addClass(className.hidden);
  2746. }
  2747. },
  2748. show: {
  2749. input: function() {
  2750. module.verbose('Modifying <input> z-index to be selectable');
  2751. $input.removeClass(className.hidden);
  2752. }
  2753. },
  2754. observeChanges: function() {
  2755. if('MutationObserver' in window) {
  2756. observer = new MutationObserver(function(mutations) {
  2757. module.debug('DOM tree modified, updating selector cache');
  2758. module.refresh();
  2759. });
  2760. observer.observe(element, {
  2761. childList : true,
  2762. subtree : true
  2763. });
  2764. module.debug('Setting up mutation observer', observer);
  2765. }
  2766. },
  2767. attachEvents: function(selector, event) {
  2768. var
  2769. $element = $(selector)
  2770. ;
  2771. event = $.isFunction(module[event])
  2772. ? module[event]
  2773. : module.toggle
  2774. ;
  2775. if($element.length > 0) {
  2776. module.debug('Attaching checkbox events to element', selector, event);
  2777. $element
  2778. .on('click' + eventNamespace, event)
  2779. ;
  2780. }
  2781. else {
  2782. module.error(error.notFound);
  2783. }
  2784. },
  2785. event: {
  2786. click: function(event) {
  2787. var
  2788. $target = $(event.target)
  2789. ;
  2790. if( $target.is(selector.input) ) {
  2791. module.verbose('Using default check action on initialized checkbox');
  2792. return;
  2793. }
  2794. if( $target.is(selector.link) ) {
  2795. module.debug('Clicking link inside checkbox, skipping toggle');
  2796. return;
  2797. }
  2798. module.toggle();
  2799. $input.focus();
  2800. event.preventDefault();
  2801. },
  2802. keydown: function(event) {
  2803. var
  2804. key = event.which,
  2805. keyCode = {
  2806. enter : 13,
  2807. space : 32,
  2808. escape : 27
  2809. }
  2810. ;
  2811. if(key == keyCode.escape) {
  2812. module.verbose('Escape key pressed blurring field');
  2813. $input.blur();
  2814. shortcutPressed = true;
  2815. }
  2816. else if(!event.ctrlKey && ( key == keyCode.space || key == keyCode.enter) ) {
  2817. module.verbose('Enter/space key pressed, toggling checkbox');
  2818. module.toggle();
  2819. shortcutPressed = true;
  2820. }
  2821. else {
  2822. shortcutPressed = false;
  2823. }
  2824. },
  2825. keyup: function(event) {
  2826. if(shortcutPressed) {
  2827. event.preventDefault();
  2828. }
  2829. }
  2830. },
  2831. check: function() {
  2832. if( !module.should.allowCheck() ) {
  2833. return;
  2834. }
  2835. module.debug('Checking checkbox', $input);
  2836. module.set.checked();
  2837. if( !module.should.ignoreCallbacks() ) {
  2838. settings.onChecked.call(input);
  2839. settings.onChange.call(input);
  2840. }
  2841. },
  2842. uncheck: function() {
  2843. if( !module.should.allowUncheck() ) {
  2844. return;
  2845. }
  2846. module.debug('Unchecking checkbox');
  2847. module.set.unchecked();
  2848. if( !module.should.ignoreCallbacks() ) {
  2849. settings.onUnchecked.call(input);
  2850. settings.onChange.call(input);
  2851. }
  2852. },
  2853. indeterminate: function() {
  2854. if( module.should.allowIndeterminate() ) {
  2855. module.debug('Checkbox is already indeterminate');
  2856. return;
  2857. }
  2858. module.debug('Making checkbox indeterminate');
  2859. module.set.indeterminate();
  2860. if( !module.should.ignoreCallbacks() ) {
  2861. settings.onIndeterminate.call(input);
  2862. settings.onChange.call(input);
  2863. }
  2864. },
  2865. determinate: function() {
  2866. if( module.should.allowDeterminate() ) {
  2867. module.debug('Checkbox is already determinate');
  2868. return;
  2869. }
  2870. module.debug('Making checkbox determinate');
  2871. module.set.determinate();
  2872. if( !module.should.ignoreCallbacks() ) {
  2873. settings.onDeterminate.call(input);
  2874. settings.onChange.call(input);
  2875. }
  2876. },
  2877. enable: function() {
  2878. if( module.is.enabled() ) {
  2879. module.debug('Checkbox is already enabled');
  2880. return;
  2881. }
  2882. module.debug('Enabling checkbox');
  2883. module.set.enabled();
  2884. settings.onEnable.call(input);
  2885. // preserve legacy callbacks
  2886. settings.onEnabled.call(input);
  2887. },
  2888. disable: function() {
  2889. if( module.is.disabled() ) {
  2890. module.debug('Checkbox is already disabled');
  2891. return;
  2892. }
  2893. module.debug('Disabling checkbox');
  2894. module.set.disabled();
  2895. settings.onDisable.call(input);
  2896. // preserve legacy callbacks
  2897. settings.onDisabled.call(input);
  2898. },
  2899. get: {
  2900. radios: function() {
  2901. var
  2902. name = module.get.name()
  2903. ;
  2904. return $('input[name="' + name + '"]').closest(selector.checkbox);
  2905. },
  2906. otherRadios: function() {
  2907. return module.get.radios().not($module);
  2908. },
  2909. name: function() {
  2910. return $input.attr('name');
  2911. }
  2912. },
  2913. is: {
  2914. initialLoad: function() {
  2915. return initialLoad;
  2916. },
  2917. radio: function() {
  2918. return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
  2919. },
  2920. indeterminate: function() {
  2921. return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
  2922. },
  2923. checked: function() {
  2924. return $input.prop('checked') !== undefined && $input.prop('checked');
  2925. },
  2926. disabled: function() {
  2927. return $input.prop('disabled') !== undefined && $input.prop('disabled');
  2928. },
  2929. enabled: function() {
  2930. return !module.is.disabled();
  2931. },
  2932. determinate: function() {
  2933. return !module.is.indeterminate();
  2934. },
  2935. unchecked: function() {
  2936. return !module.is.checked();
  2937. }
  2938. },
  2939. should: {
  2940. allowCheck: function() {
  2941. if(module.is.determinate() && module.is.checked() && !module.should.forceCallbacks() ) {
  2942. module.debug('Should not allow check, checkbox is already checked');
  2943. return false;
  2944. }
  2945. if(settings.beforeChecked.apply(input) === false) {
  2946. module.debug('Should not allow check, beforeChecked cancelled');
  2947. return false;
  2948. }
  2949. return true;
  2950. },
  2951. allowUncheck: function() {
  2952. if(module.is.determinate() && module.is.unchecked() && !module.should.forceCallbacks() ) {
  2953. module.debug('Should not allow uncheck, checkbox is already unchecked');
  2954. return false;
  2955. }
  2956. if(settings.beforeUnchecked.apply(input) === false) {
  2957. module.debug('Should not allow uncheck, beforeUnchecked cancelled');
  2958. return false;
  2959. }
  2960. return true;
  2961. },
  2962. allowIndeterminate: function() {
  2963. if(module.is.indeterminate() && !module.should.forceCallbacks() ) {
  2964. module.debug('Should not allow indeterminate, checkbox is already indeterminate');
  2965. return false;
  2966. }
  2967. if(settings.beforeIndeterminate.apply(input) === false) {
  2968. module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
  2969. return false;
  2970. }
  2971. return true;
  2972. },
  2973. allowDeterminate: function() {
  2974. if(module.is.determinate() && !module.should.forceCallbacks() ) {
  2975. module.debug('Should not allow determinate, checkbox is already determinate');
  2976. return false;
  2977. }
  2978. if(settings.beforeDeterminate.apply(input) === false) {
  2979. module.debug('Should not allow determinate, beforeDeterminate cancelled');
  2980. return false;
  2981. }
  2982. return true;
  2983. },
  2984. forceCallbacks: function() {
  2985. return (module.is.initialLoad() && settings.fireOnInit);
  2986. },
  2987. ignoreCallbacks: function() {
  2988. return (initialLoad && !settings.fireOnInit);
  2989. }
  2990. },
  2991. can: {
  2992. change: function() {
  2993. return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
  2994. },
  2995. uncheck: function() {
  2996. return (typeof settings.uncheckable === 'boolean')
  2997. ? settings.uncheckable
  2998. : !module.is.radio()
  2999. ;
  3000. }
  3001. },
  3002. set: {
  3003. initialLoad: function() {
  3004. initialLoad = true;
  3005. },
  3006. checked: function() {
  3007. module.verbose('Setting class to checked');
  3008. $module
  3009. .removeClass(className.indeterminate)
  3010. .addClass(className.checked)
  3011. ;
  3012. if( module.is.radio() ) {
  3013. module.uncheckOthers();
  3014. }
  3015. if(!module.is.indeterminate() && module.is.checked()) {
  3016. module.debug('Input is already checked, skipping input property change');
  3017. return;
  3018. }
  3019. module.verbose('Setting state to checked', input);
  3020. $input
  3021. .prop('indeterminate', false)
  3022. .prop('checked', true)
  3023. ;
  3024. module.trigger.change();
  3025. },
  3026. unchecked: function() {
  3027. module.verbose('Removing checked class');
  3028. $module
  3029. .removeClass(className.indeterminate)
  3030. .removeClass(className.checked)
  3031. ;
  3032. if(!module.is.indeterminate() && module.is.unchecked() ) {
  3033. module.debug('Input is already unchecked');
  3034. return;
  3035. }
  3036. module.debug('Setting state to unchecked');
  3037. $input
  3038. .prop('indeterminate', false)
  3039. .prop('checked', false)
  3040. ;
  3041. module.trigger.change();
  3042. },
  3043. indeterminate: function() {
  3044. module.verbose('Setting class to indeterminate');
  3045. $module
  3046. .addClass(className.indeterminate)
  3047. ;
  3048. if( module.is.indeterminate() ) {
  3049. module.debug('Input is already indeterminate, skipping input property change');
  3050. return;
  3051. }
  3052. module.debug('Setting state to indeterminate');
  3053. $input
  3054. .prop('indeterminate', true)
  3055. ;
  3056. module.trigger.change();
  3057. },
  3058. determinate: function() {
  3059. module.verbose('Removing indeterminate class');
  3060. $module
  3061. .removeClass(className.indeterminate)
  3062. ;
  3063. if( module.is.determinate() ) {
  3064. module.debug('Input is already determinate, skipping input property change');
  3065. return;
  3066. }
  3067. module.debug('Setting state to determinate');
  3068. $input
  3069. .prop('indeterminate', false)
  3070. ;
  3071. },
  3072. disabled: function() {
  3073. module.verbose('Setting class to disabled');
  3074. $module
  3075. .addClass(className.disabled)
  3076. ;
  3077. if( module.is.disabled() ) {
  3078. module.debug('Input is already disabled, skipping input property change');
  3079. return;
  3080. }
  3081. module.debug('Setting state to disabled');
  3082. $input
  3083. .prop('disabled', 'disabled')
  3084. ;
  3085. module.trigger.change();
  3086. },
  3087. enabled: function() {
  3088. module.verbose('Removing disabled class');
  3089. $module.removeClass(className.disabled);
  3090. if( module.is.enabled() ) {
  3091. module.debug('Input is already enabled, skipping input property change');
  3092. return;
  3093. }
  3094. module.debug('Setting state to enabled');
  3095. $input
  3096. .prop('disabled', false)
  3097. ;
  3098. module.trigger.change();
  3099. },
  3100. tabbable: function() {
  3101. module.verbose('Adding tabindex to checkbox');
  3102. if( $input.attr('tabindex') === undefined) {
  3103. $input.attr('tabindex', 0);
  3104. }
  3105. }
  3106. },
  3107. remove: {
  3108. initialLoad: function() {
  3109. initialLoad = false;
  3110. }
  3111. },
  3112. trigger: {
  3113. change: function() {
  3114. var
  3115. events = document.createEvent('HTMLEvents'),
  3116. inputElement = $input[0]
  3117. ;
  3118. if(inputElement) {
  3119. module.verbose('Triggering native change event');
  3120. events.initEvent('change', true, false);
  3121. inputElement.dispatchEvent(events);
  3122. }
  3123. }
  3124. },
  3125. create: {
  3126. label: function() {
  3127. if($input.prevAll(selector.label).length > 0) {
  3128. $input.prev(selector.label).detach().insertAfter($input);
  3129. module.debug('Moving existing label', $label);
  3130. }
  3131. else if( !module.has.label() ) {
  3132. $label = $('<label>').insertAfter($input);
  3133. module.debug('Creating label', $label);
  3134. }
  3135. }
  3136. },
  3137. has: {
  3138. label: function() {
  3139. return ($label.length > 0);
  3140. }
  3141. },
  3142. bind: {
  3143. events: function() {
  3144. module.verbose('Attaching checkbox events');
  3145. $module
  3146. .on('click' + eventNamespace, module.event.click)
  3147. .on('keydown' + eventNamespace, selector.input, module.event.keydown)
  3148. .on('keyup' + eventNamespace, selector.input, module.event.keyup)
  3149. ;
  3150. }
  3151. },
  3152. unbind: {
  3153. events: function() {
  3154. module.debug('Removing events');
  3155. $module
  3156. .off(eventNamespace)
  3157. ;
  3158. }
  3159. },
  3160. uncheckOthers: function() {
  3161. var
  3162. $radios = module.get.otherRadios()
  3163. ;
  3164. module.debug('Unchecking other radios', $radios);
  3165. $radios.removeClass(className.checked);
  3166. },
  3167. toggle: function() {
  3168. if( !module.can.change() ) {
  3169. if(!module.is.radio()) {
  3170. module.debug('Checkbox is read-only or disabled, ignoring toggle');
  3171. }
  3172. return;
  3173. }
  3174. if( module.is.indeterminate() || module.is.unchecked() ) {
  3175. module.debug('Currently unchecked');
  3176. module.check();
  3177. }
  3178. else if( module.is.checked() && module.can.uncheck() ) {
  3179. module.debug('Currently checked');
  3180. module.uncheck();
  3181. }
  3182. },
  3183. setting: function(name, value) {
  3184. module.debug('Changing setting', name, value);
  3185. if( $.isPlainObject(name) ) {
  3186. $.extend(true, settings, name);
  3187. }
  3188. else if(value !== undefined) {
  3189. if($.isPlainObject(settings[name])) {
  3190. $.extend(true, settings[name], value);
  3191. }
  3192. else {
  3193. settings[name] = value;
  3194. }
  3195. }
  3196. else {
  3197. return settings[name];
  3198. }
  3199. },
  3200. internal: function(name, value) {
  3201. if( $.isPlainObject(name) ) {
  3202. $.extend(true, module, name);
  3203. }
  3204. else if(value !== undefined) {
  3205. module[name] = value;
  3206. }
  3207. else {
  3208. return module[name];
  3209. }
  3210. },
  3211. debug: function() {
  3212. if(!settings.silent && settings.debug) {
  3213. if(settings.performance) {
  3214. module.performance.log(arguments);
  3215. }
  3216. else {
  3217. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3218. module.debug.apply(console, arguments);
  3219. }
  3220. }
  3221. },
  3222. verbose: function() {
  3223. if(!settings.silent && settings.verbose && settings.debug) {
  3224. if(settings.performance) {
  3225. module.performance.log(arguments);
  3226. }
  3227. else {
  3228. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3229. module.verbose.apply(console, arguments);
  3230. }
  3231. }
  3232. },
  3233. error: function() {
  3234. if(!settings.silent) {
  3235. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3236. module.error.apply(console, arguments);
  3237. }
  3238. },
  3239. performance: {
  3240. log: function(message) {
  3241. var
  3242. currentTime,
  3243. executionTime,
  3244. previousTime
  3245. ;
  3246. if(settings.performance) {
  3247. currentTime = new Date().getTime();
  3248. previousTime = time || currentTime;
  3249. executionTime = currentTime - previousTime;
  3250. time = currentTime;
  3251. performance.push({
  3252. 'Name' : message[0],
  3253. 'Arguments' : [].slice.call(message, 1) || '',
  3254. 'Element' : element,
  3255. 'Execution Time' : executionTime
  3256. });
  3257. }
  3258. clearTimeout(module.performance.timer);
  3259. module.performance.timer = setTimeout(module.performance.display, 500);
  3260. },
  3261. display: function() {
  3262. var
  3263. title = settings.name + ':',
  3264. totalTime = 0
  3265. ;
  3266. time = false;
  3267. clearTimeout(module.performance.timer);
  3268. $.each(performance, function(index, data) {
  3269. totalTime += data['Execution Time'];
  3270. });
  3271. title += ' ' + totalTime + 'ms';
  3272. if(moduleSelector) {
  3273. title += ' \'' + moduleSelector + '\'';
  3274. }
  3275. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3276. console.groupCollapsed(title);
  3277. if(console.table) {
  3278. console.table(performance);
  3279. }
  3280. else {
  3281. $.each(performance, function(index, data) {
  3282. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  3283. });
  3284. }
  3285. console.groupEnd();
  3286. }
  3287. performance = [];
  3288. }
  3289. },
  3290. invoke: function(query, passedArguments, context) {
  3291. var
  3292. object = instance,
  3293. maxDepth,
  3294. found,
  3295. response
  3296. ;
  3297. passedArguments = passedArguments || queryArguments;
  3298. context = element || context;
  3299. if(typeof query == 'string' && object !== undefined) {
  3300. query = query.split(/[\. ]/);
  3301. maxDepth = query.length - 1;
  3302. $.each(query, function(depth, value) {
  3303. var camelCaseValue = (depth != maxDepth)
  3304. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3305. : query
  3306. ;
  3307. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  3308. object = object[camelCaseValue];
  3309. }
  3310. else if( object[camelCaseValue] !== undefined ) {
  3311. found = object[camelCaseValue];
  3312. return false;
  3313. }
  3314. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  3315. object = object[value];
  3316. }
  3317. else if( object[value] !== undefined ) {
  3318. found = object[value];
  3319. return false;
  3320. }
  3321. else {
  3322. module.error(error.method, query);
  3323. return false;
  3324. }
  3325. });
  3326. }
  3327. if ( $.isFunction( found ) ) {
  3328. response = found.apply(context, passedArguments);
  3329. }
  3330. else if(found !== undefined) {
  3331. response = found;
  3332. }
  3333. if($.isArray(returnedValue)) {
  3334. returnedValue.push(response);
  3335. }
  3336. else if(returnedValue !== undefined) {
  3337. returnedValue = [returnedValue, response];
  3338. }
  3339. else if(response !== undefined) {
  3340. returnedValue = response;
  3341. }
  3342. return found;
  3343. }
  3344. };
  3345. if(methodInvoked) {
  3346. if(instance === undefined) {
  3347. module.initialize();
  3348. }
  3349. module.invoke(query);
  3350. }
  3351. else {
  3352. if(instance !== undefined) {
  3353. instance.invoke('destroy');
  3354. }
  3355. module.initialize();
  3356. }
  3357. })
  3358. ;
  3359. return (returnedValue !== undefined)
  3360. ? returnedValue
  3361. : this
  3362. ;
  3363. };
  3364. $.fn.checkbox.settings = {
  3365. name : 'Checkbox',
  3366. namespace : 'checkbox',
  3367. silent : false,
  3368. debug : false,
  3369. verbose : true,
  3370. performance : true,
  3371. // delegated event context
  3372. uncheckable : 'auto',
  3373. fireOnInit : false,
  3374. onChange : function(){},
  3375. beforeChecked : function(){},
  3376. beforeUnchecked : function(){},
  3377. beforeDeterminate : function(){},
  3378. beforeIndeterminate : function(){},
  3379. onChecked : function(){},
  3380. onUnchecked : function(){},
  3381. onDeterminate : function() {},
  3382. onIndeterminate : function() {},
  3383. onEnable : function(){},
  3384. onDisable : function(){},
  3385. // preserve misspelled callbacks (will be removed in 3.0)
  3386. onEnabled : function(){},
  3387. onDisabled : function(){},
  3388. className : {
  3389. checked : 'checked',
  3390. indeterminate : 'indeterminate',
  3391. disabled : 'disabled',
  3392. hidden : 'hidden',
  3393. radio : 'radio',
  3394. readOnly : 'read-only'
  3395. },
  3396. error : {
  3397. method : 'The method you called is not defined'
  3398. },
  3399. selector : {
  3400. checkbox : '.ui.checkbox',
  3401. label : 'label, .box',
  3402. input : 'input[type="checkbox"], input[type="radio"]',
  3403. link : 'a[href]'
  3404. }
  3405. };
  3406. })( jQuery, window, document );
  3407. /*!
  3408. * # Semantic UI 2.3.3 - Dimmer
  3409. * http://github.com/semantic-org/semantic-ui/
  3410. *
  3411. *
  3412. * Released under the MIT license
  3413. * http://opensource.org/licenses/MIT
  3414. *
  3415. */
  3416. ;(function ($, window, document, undefined) {
  3417. 'use strict';
  3418. window = (typeof window != 'undefined' && window.Math == Math)
  3419. ? window
  3420. : (typeof self != 'undefined' && self.Math == Math)
  3421. ? self
  3422. : Function('return this')()
  3423. ;
  3424. $.fn.dimmer = function(parameters) {
  3425. var
  3426. $allModules = $(this),
  3427. time = new Date().getTime(),
  3428. performance = [],
  3429. query = arguments[0],
  3430. methodInvoked = (typeof query == 'string'),
  3431. queryArguments = [].slice.call(arguments, 1),
  3432. returnedValue
  3433. ;
  3434. $allModules
  3435. .each(function() {
  3436. var
  3437. settings = ( $.isPlainObject(parameters) )
  3438. ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
  3439. : $.extend({}, $.fn.dimmer.settings),
  3440. selector = settings.selector,
  3441. namespace = settings.namespace,
  3442. className = settings.className,
  3443. error = settings.error,
  3444. eventNamespace = '.' + namespace,
  3445. moduleNamespace = 'module-' + namespace,
  3446. moduleSelector = $allModules.selector || '',
  3447. clickEvent = ('ontouchstart' in document.documentElement)
  3448. ? 'touchstart'
  3449. : 'click',
  3450. $module = $(this),
  3451. $dimmer,
  3452. $dimmable,
  3453. element = this,
  3454. instance = $module.data(moduleNamespace),
  3455. module
  3456. ;
  3457. module = {
  3458. preinitialize: function() {
  3459. if( module.is.dimmer() ) {
  3460. $dimmable = $module.parent();
  3461. $dimmer = $module;
  3462. }
  3463. else {
  3464. $dimmable = $module;
  3465. if( module.has.dimmer() ) {
  3466. if(settings.dimmerName) {
  3467. $dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
  3468. }
  3469. else {
  3470. $dimmer = $dimmable.find(selector.dimmer);
  3471. }
  3472. }
  3473. else {
  3474. $dimmer = module.create();
  3475. }
  3476. module.set.variation();
  3477. }
  3478. },
  3479. initialize: function() {
  3480. module.debug('Initializing dimmer', settings);
  3481. module.bind.events();
  3482. module.set.dimmable();
  3483. module.instantiate();
  3484. },
  3485. instantiate: function() {
  3486. module.verbose('Storing instance of module', module);
  3487. instance = module;
  3488. $module
  3489. .data(moduleNamespace, instance)
  3490. ;
  3491. },
  3492. destroy: function() {
  3493. module.verbose('Destroying previous module', $dimmer);
  3494. module.unbind.events();
  3495. module.remove.variation();
  3496. $dimmable
  3497. .off(eventNamespace)
  3498. ;
  3499. },
  3500. bind: {
  3501. events: function() {
  3502. if(module.is.page()) {
  3503. // touch events default to passive, due to changes in chrome to optimize mobile perf
  3504. $dimmable.get(0).addEventListener('touchmove', module.event.preventScroll, { passive: false });
  3505. }
  3506. if(settings.on == 'hover') {
  3507. $dimmable
  3508. .on('mouseenter' + eventNamespace, module.show)
  3509. .on('mouseleave' + eventNamespace, module.hide)
  3510. ;
  3511. }
  3512. else if(settings.on == 'click') {
  3513. $dimmable
  3514. .on(clickEvent + eventNamespace, module.toggle)
  3515. ;
  3516. }
  3517. if( module.is.page() ) {
  3518. module.debug('Setting as a page dimmer', $dimmable);
  3519. module.set.pageDimmer();
  3520. }
  3521. if( module.is.closable() ) {
  3522. module.verbose('Adding dimmer close event', $dimmer);
  3523. $dimmable
  3524. .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
  3525. ;
  3526. }
  3527. }
  3528. },
  3529. unbind: {
  3530. events: function() {
  3531. if(module.is.page()) {
  3532. $dimmable.get(0).removeEventListener('touchmove', module.event.preventScroll, { passive: false });
  3533. }
  3534. $module
  3535. .removeData(moduleNamespace)
  3536. ;
  3537. $dimmable
  3538. .off(eventNamespace)
  3539. ;
  3540. }
  3541. },
  3542. event: {
  3543. click: function(event) {
  3544. module.verbose('Determining if event occured on dimmer', event);
  3545. if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
  3546. module.hide();
  3547. event.stopImmediatePropagation();
  3548. }
  3549. },
  3550. preventScroll: function(event) {
  3551. event.preventDefault();
  3552. }
  3553. },
  3554. addContent: function(element) {
  3555. var
  3556. $content = $(element)
  3557. ;
  3558. module.debug('Add content to dimmer', $content);
  3559. if($content.parent()[0] !== $dimmer[0]) {
  3560. $content.detach().appendTo($dimmer);
  3561. }
  3562. },
  3563. create: function() {
  3564. var
  3565. $element = $( settings.template.dimmer() )
  3566. ;
  3567. if(settings.dimmerName) {
  3568. module.debug('Creating named dimmer', settings.dimmerName);
  3569. $element.addClass(settings.dimmerName);
  3570. }
  3571. $element
  3572. .appendTo($dimmable)
  3573. ;
  3574. return $element;
  3575. },
  3576. show: function(callback) {
  3577. callback = $.isFunction(callback)
  3578. ? callback
  3579. : function(){}
  3580. ;
  3581. module.debug('Showing dimmer', $dimmer, settings);
  3582. if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
  3583. module.animate.show(callback);
  3584. settings.onShow.call(element);
  3585. settings.onChange.call(element);
  3586. }
  3587. else {
  3588. module.debug('Dimmer is already shown or disabled');
  3589. }
  3590. },
  3591. hide: function(callback) {
  3592. callback = $.isFunction(callback)
  3593. ? callback
  3594. : function(){}
  3595. ;
  3596. if( module.is.dimmed() || module.is.animating() ) {
  3597. module.debug('Hiding dimmer', $dimmer);
  3598. module.animate.hide(callback);
  3599. settings.onHide.call(element);
  3600. settings.onChange.call(element);
  3601. }
  3602. else {
  3603. module.debug('Dimmer is not visible');
  3604. }
  3605. },
  3606. toggle: function() {
  3607. module.verbose('Toggling dimmer visibility', $dimmer);
  3608. if( !module.is.dimmed() ) {
  3609. module.show();
  3610. }
  3611. else {
  3612. module.hide();
  3613. }
  3614. },
  3615. animate: {
  3616. show: function(callback) {
  3617. callback = $.isFunction(callback)
  3618. ? callback
  3619. : function(){}
  3620. ;
  3621. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3622. if(settings.opacity !== 'auto') {
  3623. module.set.opacity();
  3624. }
  3625. $dimmer
  3626. .transition({
  3627. displayType : 'flex',
  3628. animation : settings.transition + ' in',
  3629. queue : false,
  3630. duration : module.get.duration(),
  3631. useFailSafe : true,
  3632. onStart : function() {
  3633. module.set.dimmed();
  3634. },
  3635. onComplete : function() {
  3636. module.set.active();
  3637. callback();
  3638. }
  3639. })
  3640. ;
  3641. }
  3642. else {
  3643. module.verbose('Showing dimmer animation with javascript');
  3644. module.set.dimmed();
  3645. if(settings.opacity == 'auto') {
  3646. settings.opacity = 0.8;
  3647. }
  3648. $dimmer
  3649. .stop()
  3650. .css({
  3651. opacity : 0,
  3652. width : '100%',
  3653. height : '100%'
  3654. })
  3655. .fadeTo(module.get.duration(), settings.opacity, function() {
  3656. $dimmer.removeAttr('style');
  3657. module.set.active();
  3658. callback();
  3659. })
  3660. ;
  3661. }
  3662. },
  3663. hide: function(callback) {
  3664. callback = $.isFunction(callback)
  3665. ? callback
  3666. : function(){}
  3667. ;
  3668. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3669. module.verbose('Hiding dimmer with css');
  3670. $dimmer
  3671. .transition({
  3672. displayType : 'flex',
  3673. animation : settings.transition + ' out',
  3674. queue : false,
  3675. duration : module.get.duration(),
  3676. useFailSafe : true,
  3677. onStart : function() {
  3678. module.remove.dimmed();
  3679. },
  3680. onComplete : function() {
  3681. module.remove.active();
  3682. callback();
  3683. }
  3684. })
  3685. ;
  3686. }
  3687. else {
  3688. module.verbose('Hiding dimmer with javascript');
  3689. module.remove.dimmed();
  3690. $dimmer
  3691. .stop()
  3692. .fadeOut(module.get.duration(), function() {
  3693. module.remove.active();
  3694. $dimmer.removeAttr('style');
  3695. callback();
  3696. })
  3697. ;
  3698. }
  3699. }
  3700. },
  3701. get: {
  3702. dimmer: function() {
  3703. return $dimmer;
  3704. },
  3705. duration: function() {
  3706. if(typeof settings.duration == 'object') {
  3707. if( module.is.active() ) {
  3708. return settings.duration.hide;
  3709. }
  3710. else {
  3711. return settings.duration.show;
  3712. }
  3713. }
  3714. return settings.duration;
  3715. }
  3716. },
  3717. has: {
  3718. dimmer: function() {
  3719. if(settings.dimmerName) {
  3720. return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
  3721. }
  3722. else {
  3723. return ( $module.find(selector.dimmer).length > 0 );
  3724. }
  3725. }
  3726. },
  3727. is: {
  3728. active: function() {
  3729. return $dimmer.hasClass(className.active);
  3730. },
  3731. animating: function() {
  3732. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
  3733. },
  3734. closable: function() {
  3735. if(settings.closable == 'auto') {
  3736. if(settings.on == 'hover') {
  3737. return false;
  3738. }
  3739. return true;
  3740. }
  3741. return settings.closable;
  3742. },
  3743. dimmer: function() {
  3744. return $module.hasClass(className.dimmer);
  3745. },
  3746. dimmable: function() {
  3747. return $module.hasClass(className.dimmable);
  3748. },
  3749. dimmed: function() {
  3750. return $dimmable.hasClass(className.dimmed);
  3751. },
  3752. disabled: function() {
  3753. return $dimmable.hasClass(className.disabled);
  3754. },
  3755. enabled: function() {
  3756. return !module.is.disabled();
  3757. },
  3758. page: function () {
  3759. return $dimmable.is('body');
  3760. },
  3761. pageDimmer: function() {
  3762. return $dimmer.hasClass(className.pageDimmer);
  3763. }
  3764. },
  3765. can: {
  3766. show: function() {
  3767. return !$dimmer.hasClass(className.disabled);
  3768. }
  3769. },
  3770. set: {
  3771. opacity: function(opacity) {
  3772. var
  3773. color = $dimmer.css('background-color'),
  3774. colorArray = color.split(','),
  3775. isRGB = (colorArray && colorArray.length == 3),
  3776. isRGBA = (colorArray && colorArray.length == 4)
  3777. ;
  3778. opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
  3779. if(isRGB || isRGBA) {
  3780. colorArray[3] = opacity + ')';
  3781. color = colorArray.join(',');
  3782. }
  3783. else {
  3784. color = 'rgba(0, 0, 0, ' + opacity + ')';
  3785. }
  3786. module.debug('Setting opacity to', opacity);
  3787. $dimmer.css('background-color', color);
  3788. },
  3789. active: function() {
  3790. $dimmer.addClass(className.active);
  3791. },
  3792. dimmable: function() {
  3793. $dimmable.addClass(className.dimmable);
  3794. },
  3795. dimmed: function() {
  3796. $dimmable.addClass(className.dimmed);
  3797. },
  3798. pageDimmer: function() {
  3799. $dimmer.addClass(className.pageDimmer);
  3800. },
  3801. disabled: function() {
  3802. $dimmer.addClass(className.disabled);
  3803. },
  3804. variation: function(variation) {
  3805. variation = variation || settings.variation;
  3806. if(variation) {
  3807. $dimmer.addClass(variation);
  3808. }
  3809. }
  3810. },
  3811. remove: {
  3812. active: function() {
  3813. $dimmer
  3814. .removeClass(className.active)
  3815. ;
  3816. },
  3817. dimmed: function() {
  3818. $dimmable.removeClass(className.dimmed);
  3819. },
  3820. disabled: function() {
  3821. $dimmer.removeClass(className.disabled);
  3822. },
  3823. variation: function(variation) {
  3824. variation = variation || settings.variation;
  3825. if(variation) {
  3826. $dimmer.removeClass(variation);
  3827. }
  3828. }
  3829. },
  3830. setting: function(name, value) {
  3831. module.debug('Changing setting', name, value);
  3832. if( $.isPlainObject(name) ) {
  3833. $.extend(true, settings, name);
  3834. }
  3835. else if(value !== undefined) {
  3836. if($.isPlainObject(settings[name])) {
  3837. $.extend(true, settings[name], value);
  3838. }
  3839. else {
  3840. settings[name] = value;
  3841. }
  3842. }
  3843. else {
  3844. return settings[name];
  3845. }
  3846. },
  3847. internal: function(name, value) {
  3848. if( $.isPlainObject(name) ) {
  3849. $.extend(true, module, name);
  3850. }
  3851. else if(value !== undefined) {
  3852. module[name] = value;
  3853. }
  3854. else {
  3855. return module[name];
  3856. }
  3857. },
  3858. debug: function() {
  3859. if(!settings.silent && settings.debug) {
  3860. if(settings.performance) {
  3861. module.performance.log(arguments);
  3862. }
  3863. else {
  3864. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3865. module.debug.apply(console, arguments);
  3866. }
  3867. }
  3868. },
  3869. verbose: function() {
  3870. if(!settings.silent && settings.verbose && settings.debug) {
  3871. if(settings.performance) {
  3872. module.performance.log(arguments);
  3873. }
  3874. else {
  3875. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3876. module.verbose.apply(console, arguments);
  3877. }
  3878. }
  3879. },
  3880. error: function() {
  3881. if(!settings.silent) {
  3882. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3883. module.error.apply(console, arguments);
  3884. }
  3885. },
  3886. performance: {
  3887. log: function(message) {
  3888. var
  3889. currentTime,
  3890. executionTime,
  3891. previousTime
  3892. ;
  3893. if(settings.performance) {
  3894. currentTime = new Date().getTime();
  3895. previousTime = time || currentTime;
  3896. executionTime = currentTime - previousTime;
  3897. time = currentTime;
  3898. performance.push({
  3899. 'Name' : message[0],
  3900. 'Arguments' : [].slice.call(message, 1) || '',
  3901. 'Element' : element,
  3902. 'Execution Time' : executionTime
  3903. });
  3904. }
  3905. clearTimeout(module.performance.timer);
  3906. module.performance.timer = setTimeout(module.performance.display, 500);
  3907. },
  3908. display: function() {
  3909. var
  3910. title = settings.name + ':',
  3911. totalTime = 0
  3912. ;
  3913. time = false;
  3914. clearTimeout(module.performance.timer);
  3915. $.each(performance, function(index, data) {
  3916. totalTime += data['Execution Time'];
  3917. });
  3918. title += ' ' + totalTime + 'ms';
  3919. if(moduleSelector) {
  3920. title += ' \'' + moduleSelector + '\'';
  3921. }
  3922. if($allModules.length > 1) {
  3923. title += ' ' + '(' + $allModules.length + ')';
  3924. }
  3925. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3926. console.groupCollapsed(title);
  3927. if(console.table) {
  3928. console.table(performance);
  3929. }
  3930. else {
  3931. $.each(performance, function(index, data) {
  3932. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  3933. });
  3934. }
  3935. console.groupEnd();
  3936. }
  3937. performance = [];
  3938. }
  3939. },
  3940. invoke: function(query, passedArguments, context) {
  3941. var
  3942. object = instance,
  3943. maxDepth,
  3944. found,
  3945. response
  3946. ;
  3947. passedArguments = passedArguments || queryArguments;
  3948. context = element || context;
  3949. if(typeof query == 'string' && object !== undefined) {
  3950. query = query.split(/[\. ]/);
  3951. maxDepth = query.length - 1;
  3952. $.each(query, function(depth, value) {
  3953. var camelCaseValue = (depth != maxDepth)
  3954. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3955. : query
  3956. ;
  3957. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  3958. object = object[camelCaseValue];
  3959. }
  3960. else if( object[camelCaseValue] !== undefined ) {
  3961. found = object[camelCaseValue];
  3962. return false;
  3963. }
  3964. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  3965. object = object[value];
  3966. }
  3967. else if( object[value] !== undefined ) {
  3968. found = object[value];
  3969. return false;
  3970. }
  3971. else {
  3972. module.error(error.method, query);
  3973. return false;
  3974. }
  3975. });
  3976. }
  3977. if ( $.isFunction( found ) ) {
  3978. response = found.apply(context, passedArguments);
  3979. }
  3980. else if(found !== undefined) {
  3981. response = found;
  3982. }
  3983. if($.isArray(returnedValue)) {
  3984. returnedValue.push(response);
  3985. }
  3986. else if(returnedValue !== undefined) {
  3987. returnedValue = [returnedValue, response];
  3988. }
  3989. else if(response !== undefined) {
  3990. returnedValue = response;
  3991. }
  3992. return found;
  3993. }
  3994. };
  3995. module.preinitialize();
  3996. if(methodInvoked) {
  3997. if(instance === undefined) {
  3998. module.initialize();
  3999. }
  4000. module.invoke(query);
  4001. }
  4002. else {
  4003. if(instance !== undefined) {
  4004. instance.invoke('destroy');
  4005. }
  4006. module.initialize();
  4007. }
  4008. })
  4009. ;
  4010. return (returnedValue !== undefined)
  4011. ? returnedValue
  4012. : this
  4013. ;
  4014. };
  4015. $.fn.dimmer.settings = {
  4016. name : 'Dimmer',
  4017. namespace : 'dimmer',
  4018. silent : false,
  4019. debug : false,
  4020. verbose : false,
  4021. performance : true,
  4022. // name to distinguish between multiple dimmers in context
  4023. dimmerName : false,
  4024. // whether to add a variation type
  4025. variation : false,
  4026. // whether to bind close events
  4027. closable : 'auto',
  4028. // whether to use css animations
  4029. useCSS : true,
  4030. // css animation to use
  4031. transition : 'fade',
  4032. // event to bind to
  4033. on : false,
  4034. // overriding opacity value
  4035. opacity : 'auto',
  4036. // transition durations
  4037. duration : {
  4038. show : 500,
  4039. hide : 500
  4040. },
  4041. onChange : function(){},
  4042. onShow : function(){},
  4043. onHide : function(){},
  4044. error : {
  4045. method : 'The method you called is not defined.'
  4046. },
  4047. className : {
  4048. active : 'active',
  4049. animating : 'animating',
  4050. dimmable : 'dimmable',
  4051. dimmed : 'dimmed',
  4052. dimmer : 'dimmer',
  4053. disabled : 'disabled',
  4054. hide : 'hide',
  4055. pageDimmer : 'page',
  4056. show : 'show'
  4057. },
  4058. selector: {
  4059. dimmer : '> .ui.dimmer',
  4060. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  4061. },
  4062. template: {
  4063. dimmer: function() {
  4064. return $('<div />').attr('class', 'ui dimmer');
  4065. }
  4066. }
  4067. };
  4068. })( jQuery, window, document );
  4069. /*!
  4070. * # Semantic UI 2.3.3 - Dropdown
  4071. * http://github.com/semantic-org/semantic-ui/
  4072. *
  4073. *
  4074. * Released under the MIT license
  4075. * http://opensource.org/licenses/MIT
  4076. *
  4077. */
  4078. ;(function ($, window, document, undefined) {
  4079. 'use strict';
  4080. window = (typeof window != 'undefined' && window.Math == Math)
  4081. ? window
  4082. : (typeof self != 'undefined' && self.Math == Math)
  4083. ? self
  4084. : Function('return this')()
  4085. ;
  4086. $.fn.dropdown = function(parameters) {
  4087. var
  4088. $allModules = $(this),
  4089. $document = $(document),
  4090. moduleSelector = $allModules.selector || '',
  4091. hasTouch = ('ontouchstart' in document.documentElement),
  4092. time = new Date().getTime(),
  4093. performance = [],
  4094. query = arguments[0],
  4095. methodInvoked = (typeof query == 'string'),
  4096. queryArguments = [].slice.call(arguments, 1),
  4097. returnedValue
  4098. ;
  4099. $allModules
  4100. .each(function(elementIndex) {
  4101. var
  4102. settings = ( $.isPlainObject(parameters) )
  4103. ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
  4104. : $.extend({}, $.fn.dropdown.settings),
  4105. className = settings.className,
  4106. message = settings.message,
  4107. fields = settings.fields,
  4108. keys = settings.keys,
  4109. metadata = settings.metadata,
  4110. namespace = settings.namespace,
  4111. regExp = settings.regExp,
  4112. selector = settings.selector,
  4113. error = settings.error,
  4114. templates = settings.templates,
  4115. eventNamespace = '.' + namespace,
  4116. moduleNamespace = 'module-' + namespace,
  4117. $module = $(this),
  4118. $context = $(settings.context),
  4119. $text = $module.find(selector.text),
  4120. $search = $module.find(selector.search),
  4121. $sizer = $module.find(selector.sizer),
  4122. $input = $module.find(selector.input),
  4123. $icon = $module.find(selector.icon),
  4124. $combo = ($module.prev().find(selector.text).length > 0)
  4125. ? $module.prev().find(selector.text)
  4126. : $module.prev(),
  4127. $menu = $module.children(selector.menu),
  4128. $item = $menu.find(selector.item),
  4129. activated = false,
  4130. itemActivated = false,
  4131. internalChange = false,
  4132. element = this,
  4133. instance = $module.data(moduleNamespace),
  4134. initialLoad,
  4135. pageLostFocus,
  4136. willRefocus,
  4137. elementNamespace,
  4138. id,
  4139. selectObserver,
  4140. menuObserver,
  4141. module
  4142. ;
  4143. module = {
  4144. initialize: function() {
  4145. module.debug('Initializing dropdown', settings);
  4146. if( module.is.alreadySetup() ) {
  4147. module.setup.reference();
  4148. }
  4149. else {
  4150. module.setup.layout();
  4151. if(settings.values) {
  4152. module.change.values(settings.values);
  4153. }
  4154. module.refreshData();
  4155. module.save.defaults();
  4156. module.restore.selected();
  4157. module.create.id();
  4158. module.bind.events();
  4159. module.observeChanges();
  4160. module.instantiate();
  4161. }
  4162. },
  4163. instantiate: function() {
  4164. module.verbose('Storing instance of dropdown', module);
  4165. instance = module;
  4166. $module
  4167. .data(moduleNamespace, module)
  4168. ;
  4169. },
  4170. destroy: function() {
  4171. module.verbose('Destroying previous dropdown', $module);
  4172. module.remove.tabbable();
  4173. $module
  4174. .off(eventNamespace)
  4175. .removeData(moduleNamespace)
  4176. ;
  4177. $menu
  4178. .off(eventNamespace)
  4179. ;
  4180. $document
  4181. .off(elementNamespace)
  4182. ;
  4183. module.disconnect.menuObserver();
  4184. module.disconnect.selectObserver();
  4185. },
  4186. observeChanges: function() {
  4187. if('MutationObserver' in window) {
  4188. selectObserver = new MutationObserver(module.event.select.mutation);
  4189. menuObserver = new MutationObserver(module.event.menu.mutation);
  4190. module.debug('Setting up mutation observer', selectObserver, menuObserver);
  4191. module.observe.select();
  4192. module.observe.menu();
  4193. }
  4194. },
  4195. disconnect: {
  4196. menuObserver: function() {
  4197. if(menuObserver) {
  4198. menuObserver.disconnect();
  4199. }
  4200. },
  4201. selectObserver: function() {
  4202. if(selectObserver) {
  4203. selectObserver.disconnect();
  4204. }
  4205. }
  4206. },
  4207. observe: {
  4208. select: function() {
  4209. if(module.has.input()) {
  4210. selectObserver.observe($module[0], {
  4211. childList : true,
  4212. subtree : true
  4213. });
  4214. }
  4215. },
  4216. menu: function() {
  4217. if(module.has.menu()) {
  4218. menuObserver.observe($menu[0], {
  4219. childList : true,
  4220. subtree : true
  4221. });
  4222. }
  4223. }
  4224. },
  4225. create: {
  4226. id: function() {
  4227. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  4228. elementNamespace = '.' + id;
  4229. module.verbose('Creating unique id for element', id);
  4230. },
  4231. userChoice: function(values) {
  4232. var
  4233. $userChoices,
  4234. $userChoice,
  4235. isUserValue,
  4236. html
  4237. ;
  4238. values = values || module.get.userValues();
  4239. if(!values) {
  4240. return false;
  4241. }
  4242. values = $.isArray(values)
  4243. ? values
  4244. : [values]
  4245. ;
  4246. $.each(values, function(index, value) {
  4247. if(module.get.item(value) === false) {
  4248. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  4249. $userChoice = $('<div />')
  4250. .html(html)
  4251. .attr('data-' + metadata.value, value)
  4252. .attr('data-' + metadata.text, value)
  4253. .addClass(className.addition)
  4254. .addClass(className.item)
  4255. ;
  4256. if(settings.hideAdditions) {
  4257. $userChoice.addClass(className.hidden);
  4258. }
  4259. $userChoices = ($userChoices === undefined)
  4260. ? $userChoice
  4261. : $userChoices.add($userChoice)
  4262. ;
  4263. module.verbose('Creating user choices for value', value, $userChoice);
  4264. }
  4265. });
  4266. return $userChoices;
  4267. },
  4268. userLabels: function(value) {
  4269. var
  4270. userValues = module.get.userValues()
  4271. ;
  4272. if(userValues) {
  4273. module.debug('Adding user labels', userValues);
  4274. $.each(userValues, function(index, value) {
  4275. module.verbose('Adding custom user value');
  4276. module.add.label(value, value);
  4277. });
  4278. }
  4279. },
  4280. menu: function() {
  4281. $menu = $('<div />')
  4282. .addClass(className.menu)
  4283. .appendTo($module)
  4284. ;
  4285. },
  4286. sizer: function() {
  4287. $sizer = $('<span />')
  4288. .addClass(className.sizer)
  4289. .insertAfter($search)
  4290. ;
  4291. }
  4292. },
  4293. search: function(query) {
  4294. query = (query !== undefined)
  4295. ? query
  4296. : module.get.query()
  4297. ;
  4298. module.verbose('Searching for query', query);
  4299. if(module.has.minCharacters(query)) {
  4300. module.filter(query);
  4301. }
  4302. else {
  4303. module.hide();
  4304. }
  4305. },
  4306. select: {
  4307. firstUnfiltered: function() {
  4308. module.verbose('Selecting first non-filtered element');
  4309. module.remove.selectedItem();
  4310. $item
  4311. .not(selector.unselectable)
  4312. .not(selector.addition + selector.hidden)
  4313. .eq(0)
  4314. .addClass(className.selected)
  4315. ;
  4316. },
  4317. nextAvailable: function($selected) {
  4318. $selected = $selected.eq(0);
  4319. var
  4320. $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
  4321. $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
  4322. hasNext = ($nextAvailable.length > 0)
  4323. ;
  4324. if(hasNext) {
  4325. module.verbose('Moving selection to', $nextAvailable);
  4326. $nextAvailable.addClass(className.selected);
  4327. }
  4328. else {
  4329. module.verbose('Moving selection to', $prevAvailable);
  4330. $prevAvailable.addClass(className.selected);
  4331. }
  4332. }
  4333. },
  4334. setup: {
  4335. api: function() {
  4336. var
  4337. apiSettings = {
  4338. debug : settings.debug,
  4339. urlData : {
  4340. value : module.get.value(),
  4341. query : module.get.query()
  4342. },
  4343. on : false
  4344. }
  4345. ;
  4346. module.verbose('First request, initializing API');
  4347. $module
  4348. .api(apiSettings)
  4349. ;
  4350. },
  4351. layout: function() {
  4352. if( $module.is('select') ) {
  4353. module.setup.select();
  4354. module.setup.returnedObject();
  4355. }
  4356. if( !module.has.menu() ) {
  4357. module.create.menu();
  4358. }
  4359. if( module.is.search() && !module.has.search() ) {
  4360. module.verbose('Adding search input');
  4361. $search = $('<input />')
  4362. .addClass(className.search)
  4363. .prop('autocomplete', 'off')
  4364. .insertBefore($text)
  4365. ;
  4366. }
  4367. if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
  4368. module.create.sizer();
  4369. }
  4370. if(settings.allowTab) {
  4371. module.set.tabbable();
  4372. }
  4373. },
  4374. select: function() {
  4375. var
  4376. selectValues = module.get.selectValues()
  4377. ;
  4378. module.debug('Dropdown initialized on a select', selectValues);
  4379. if( $module.is('select') ) {
  4380. $input = $module;
  4381. }
  4382. // see if select is placed correctly already
  4383. if($input.parent(selector.dropdown).length > 0) {
  4384. module.debug('UI dropdown already exists. Creating dropdown menu only');
  4385. $module = $input.closest(selector.dropdown);
  4386. if( !module.has.menu() ) {
  4387. module.create.menu();
  4388. }
  4389. $menu = $module.children(selector.menu);
  4390. module.setup.menu(selectValues);
  4391. }
  4392. else {
  4393. module.debug('Creating entire dropdown from select');
  4394. $module = $('<div />')
  4395. .attr('class', $input.attr('class') )
  4396. .addClass(className.selection)
  4397. .addClass(className.dropdown)
  4398. .html( templates.dropdown(selectValues) )
  4399. .insertBefore($input)
  4400. ;
  4401. if($input.hasClass(className.multiple) && $input.prop('multiple') === false) {
  4402. module.error(error.missingMultiple);
  4403. $input.prop('multiple', true);
  4404. }
  4405. if($input.is('[multiple]')) {
  4406. module.set.multiple();
  4407. }
  4408. if ($input.prop('disabled')) {
  4409. module.debug('Disabling dropdown');
  4410. $module.addClass(className.disabled);
  4411. }
  4412. $input
  4413. .removeAttr('class')
  4414. .detach()
  4415. .prependTo($module)
  4416. ;
  4417. }
  4418. module.refresh();
  4419. },
  4420. menu: function(values) {
  4421. $menu.html( templates.menu(values, fields));
  4422. $item = $menu.find(selector.item);
  4423. },
  4424. reference: function() {
  4425. module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
  4426. // replace module reference
  4427. $module = $module.parent(selector.dropdown);
  4428. instance = $module.data(moduleNamespace);
  4429. element = $module.get(0);
  4430. module.refresh();
  4431. module.setup.returnedObject();
  4432. },
  4433. returnedObject: function() {
  4434. var
  4435. $firstModules = $allModules.slice(0, elementIndex),
  4436. $lastModules = $allModules.slice(elementIndex + 1)
  4437. ;
  4438. // adjust all modules to use correct reference
  4439. $allModules = $firstModules.add($module).add($lastModules);
  4440. }
  4441. },
  4442. refresh: function() {
  4443. module.refreshSelectors();
  4444. module.refreshData();
  4445. },
  4446. refreshItems: function() {
  4447. $item = $menu.find(selector.item);
  4448. },
  4449. refreshSelectors: function() {
  4450. module.verbose('Refreshing selector cache');
  4451. $text = $module.find(selector.text);
  4452. $search = $module.find(selector.search);
  4453. $input = $module.find(selector.input);
  4454. $icon = $module.find(selector.icon);
  4455. $combo = ($module.prev().find(selector.text).length > 0)
  4456. ? $module.prev().find(selector.text)
  4457. : $module.prev()
  4458. ;
  4459. $menu = $module.children(selector.menu);
  4460. $item = $menu.find(selector.item);
  4461. },
  4462. refreshData: function() {
  4463. module.verbose('Refreshing cached metadata');
  4464. $item
  4465. .removeData(metadata.text)
  4466. .removeData(metadata.value)
  4467. ;
  4468. },
  4469. clearData: function() {
  4470. module.verbose('Clearing metadata');
  4471. $item
  4472. .removeData(metadata.text)
  4473. .removeData(metadata.value)
  4474. ;
  4475. $module
  4476. .removeData(metadata.defaultText)
  4477. .removeData(metadata.defaultValue)
  4478. .removeData(metadata.placeholderText)
  4479. ;
  4480. },
  4481. toggle: function() {
  4482. module.verbose('Toggling menu visibility');
  4483. if( !module.is.active() ) {
  4484. module.show();
  4485. }
  4486. else {
  4487. module.hide();
  4488. }
  4489. },
  4490. show: function(callback) {
  4491. callback = $.isFunction(callback)
  4492. ? callback
  4493. : function(){}
  4494. ;
  4495. if(!module.can.show() && module.is.remote()) {
  4496. module.debug('No API results retrieved, searching before show');
  4497. module.queryRemote(module.get.query(), module.show);
  4498. }
  4499. if( module.can.show() && !module.is.active() ) {
  4500. module.debug('Showing dropdown');
  4501. if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
  4502. module.remove.message();
  4503. }
  4504. if(module.is.allFiltered()) {
  4505. return true;
  4506. }
  4507. if(settings.onShow.call(element) !== false) {
  4508. module.animate.show(function() {
  4509. if( module.can.click() ) {
  4510. module.bind.intent();
  4511. }
  4512. if(module.has.menuSearch()) {
  4513. module.focusSearch();
  4514. }
  4515. module.set.visible();
  4516. callback.call(element);
  4517. });
  4518. }
  4519. }
  4520. },
  4521. hide: function(callback) {
  4522. callback = $.isFunction(callback)
  4523. ? callback
  4524. : function(){}
  4525. ;
  4526. if( module.is.active() && !module.is.animatingOutward() ) {
  4527. module.debug('Hiding dropdown');
  4528. if(settings.onHide.call(element) !== false) {
  4529. module.animate.hide(function() {
  4530. module.remove.visible();
  4531. callback.call(element);
  4532. });
  4533. }
  4534. }
  4535. },
  4536. hideOthers: function() {
  4537. module.verbose('Finding other dropdowns to hide');
  4538. $allModules
  4539. .not($module)
  4540. .has(selector.menu + '.' + className.visible)
  4541. .dropdown('hide')
  4542. ;
  4543. },
  4544. hideMenu: function() {
  4545. module.verbose('Hiding menu instantaneously');
  4546. module.remove.active();
  4547. module.remove.visible();
  4548. $menu.transition('hide');
  4549. },
  4550. hideSubMenus: function() {
  4551. var
  4552. $subMenus = $menu.children(selector.item).find(selector.menu)
  4553. ;
  4554. module.verbose('Hiding sub menus', $subMenus);
  4555. $subMenus.transition('hide');
  4556. },
  4557. bind: {
  4558. events: function() {
  4559. if(hasTouch) {
  4560. module.bind.touchEvents();
  4561. }
  4562. module.bind.keyboardEvents();
  4563. module.bind.inputEvents();
  4564. module.bind.mouseEvents();
  4565. },
  4566. touchEvents: function() {
  4567. module.debug('Touch device detected binding additional touch events');
  4568. if( module.is.searchSelection() ) {
  4569. // do nothing special yet
  4570. }
  4571. else if( module.is.single() ) {
  4572. $module
  4573. .on('touchstart' + eventNamespace, module.event.test.toggle)
  4574. ;
  4575. }
  4576. $menu
  4577. .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
  4578. ;
  4579. },
  4580. keyboardEvents: function() {
  4581. module.verbose('Binding keyboard events');
  4582. $module
  4583. .on('keydown' + eventNamespace, module.event.keydown)
  4584. ;
  4585. if( module.has.search() ) {
  4586. $module
  4587. .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
  4588. ;
  4589. }
  4590. if( module.is.multiple() ) {
  4591. $document
  4592. .on('keydown' + elementNamespace, module.event.document.keydown)
  4593. ;
  4594. }
  4595. },
  4596. inputEvents: function() {
  4597. module.verbose('Binding input change events');
  4598. $module
  4599. .on('change' + eventNamespace, selector.input, module.event.change)
  4600. ;
  4601. },
  4602. mouseEvents: function() {
  4603. module.verbose('Binding mouse events');
  4604. if(module.is.multiple()) {
  4605. $module
  4606. .on('click' + eventNamespace, selector.label, module.event.label.click)
  4607. .on('click' + eventNamespace, selector.remove, module.event.remove.click)
  4608. ;
  4609. }
  4610. if( module.is.searchSelection() ) {
  4611. $module
  4612. .on('mousedown' + eventNamespace, module.event.mousedown)
  4613. .on('mouseup' + eventNamespace, module.event.mouseup)
  4614. .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
  4615. .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
  4616. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  4617. .on('focus' + eventNamespace, selector.search, module.event.search.focus)
  4618. .on('click' + eventNamespace, selector.search, module.event.search.focus)
  4619. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  4620. .on('click' + eventNamespace, selector.text, module.event.text.focus)
  4621. ;
  4622. if(module.is.multiple()) {
  4623. $module
  4624. .on('click' + eventNamespace, module.event.click)
  4625. ;
  4626. }
  4627. }
  4628. else {
  4629. if(settings.on == 'click') {
  4630. $module
  4631. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  4632. .on('click' + eventNamespace, module.event.test.toggle)
  4633. ;
  4634. }
  4635. else if(settings.on == 'hover') {
  4636. $module
  4637. .on('mouseenter' + eventNamespace, module.delay.show)
  4638. .on('mouseleave' + eventNamespace, module.delay.hide)
  4639. ;
  4640. }
  4641. else {
  4642. $module
  4643. .on(settings.on + eventNamespace, module.toggle)
  4644. ;
  4645. }
  4646. $module
  4647. .on('mousedown' + eventNamespace, module.event.mousedown)
  4648. .on('mouseup' + eventNamespace, module.event.mouseup)
  4649. .on('focus' + eventNamespace, module.event.focus)
  4650. ;
  4651. if(module.has.menuSearch() ) {
  4652. $module
  4653. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  4654. ;
  4655. }
  4656. else {
  4657. $module
  4658. .on('blur' + eventNamespace, module.event.blur)
  4659. ;
  4660. }
  4661. }
  4662. $menu
  4663. .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
  4664. .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
  4665. .on('click' + eventNamespace, selector.item, module.event.item.click)
  4666. ;
  4667. },
  4668. intent: function() {
  4669. module.verbose('Binding hide intent event to document');
  4670. if(hasTouch) {
  4671. $document
  4672. .on('touchstart' + elementNamespace, module.event.test.touch)
  4673. .on('touchmove' + elementNamespace, module.event.test.touch)
  4674. ;
  4675. }
  4676. $document
  4677. .on('click' + elementNamespace, module.event.test.hide)
  4678. ;
  4679. }
  4680. },
  4681. unbind: {
  4682. intent: function() {
  4683. module.verbose('Removing hide intent event from document');
  4684. if(hasTouch) {
  4685. $document
  4686. .off('touchstart' + elementNamespace)
  4687. .off('touchmove' + elementNamespace)
  4688. ;
  4689. }
  4690. $document
  4691. .off('click' + elementNamespace)
  4692. ;
  4693. }
  4694. },
  4695. filter: function(query) {
  4696. var
  4697. searchTerm = (query !== undefined)
  4698. ? query
  4699. : module.get.query(),
  4700. afterFiltered = function() {
  4701. if(module.is.multiple()) {
  4702. module.filterActive();
  4703. }
  4704. if(query || (!query && module.get.activeItem().length == 0)) {
  4705. module.select.firstUnfiltered();
  4706. }
  4707. if( module.has.allResultsFiltered() ) {
  4708. if( settings.onNoResults.call(element, searchTerm) ) {
  4709. if(settings.allowAdditions) {
  4710. if(settings.hideAdditions) {
  4711. module.verbose('User addition with no menu, setting empty style');
  4712. module.set.empty();
  4713. module.hideMenu();
  4714. }
  4715. }
  4716. else {
  4717. module.verbose('All items filtered, showing message', searchTerm);
  4718. module.add.message(message.noResults);
  4719. }
  4720. }
  4721. else {
  4722. module.verbose('All items filtered, hiding dropdown', searchTerm);
  4723. module.hideMenu();
  4724. }
  4725. }
  4726. else {
  4727. module.remove.empty();
  4728. module.remove.message();
  4729. }
  4730. if(settings.allowAdditions) {
  4731. module.add.userSuggestion(query);
  4732. }
  4733. if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
  4734. module.show();
  4735. }
  4736. }
  4737. ;
  4738. if(settings.useLabels && module.has.maxSelections()) {
  4739. return;
  4740. }
  4741. if(settings.apiSettings) {
  4742. if( module.can.useAPI() ) {
  4743. module.queryRemote(searchTerm, function() {
  4744. if(settings.filterRemoteData) {
  4745. module.filterItems(searchTerm);
  4746. }
  4747. afterFiltered();
  4748. });
  4749. }
  4750. else {
  4751. module.error(error.noAPI);
  4752. }
  4753. }
  4754. else {
  4755. module.filterItems(searchTerm);
  4756. afterFiltered();
  4757. }
  4758. },
  4759. queryRemote: function(query, callback) {
  4760. var
  4761. apiSettings = {
  4762. errorDuration : false,
  4763. cache : 'local',
  4764. throttle : settings.throttle,
  4765. urlData : {
  4766. query: query
  4767. },
  4768. onError: function() {
  4769. module.add.message(message.serverError);
  4770. callback();
  4771. },
  4772. onFailure: function() {
  4773. module.add.message(message.serverError);
  4774. callback();
  4775. },
  4776. onSuccess : function(response) {
  4777. var
  4778. values = response[fields.remoteValues],
  4779. hasRemoteValues = ($.isArray(values) && values.length > 0)
  4780. ;
  4781. if(hasRemoteValues) {
  4782. module.remove.message();
  4783. module.setup.menu({
  4784. values: response[fields.remoteValues]
  4785. });
  4786. }
  4787. else {
  4788. module.add.message(message.noResults);
  4789. }
  4790. callback();
  4791. }
  4792. }
  4793. ;
  4794. if( !$module.api('get request') ) {
  4795. module.setup.api();
  4796. }
  4797. apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
  4798. $module
  4799. .api('setting', apiSettings)
  4800. .api('query')
  4801. ;
  4802. },
  4803. filterItems: function(query) {
  4804. var
  4805. searchTerm = (query !== undefined)
  4806. ? query
  4807. : module.get.query(),
  4808. results = null,
  4809. escapedTerm = module.escape.string(searchTerm),
  4810. beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm')
  4811. ;
  4812. // avoid loop if we're matching nothing
  4813. if( module.has.query() ) {
  4814. results = [];
  4815. module.verbose('Searching for matching values', searchTerm);
  4816. $item
  4817. .each(function(){
  4818. var
  4819. $choice = $(this),
  4820. text,
  4821. value
  4822. ;
  4823. if(settings.match == 'both' || settings.match == 'text') {
  4824. text = String(module.get.choiceText($choice, false));
  4825. if(text.search(beginsWithRegExp) !== -1) {
  4826. results.push(this);
  4827. return true;
  4828. }
  4829. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) {
  4830. results.push(this);
  4831. return true;
  4832. }
  4833. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) {
  4834. results.push(this);
  4835. return true;
  4836. }
  4837. }
  4838. if(settings.match == 'both' || settings.match == 'value') {
  4839. value = String(module.get.choiceValue($choice, text));
  4840. if(value.search(beginsWithRegExp) !== -1) {
  4841. results.push(this);
  4842. return true;
  4843. }
  4844. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, value)) {
  4845. results.push(this);
  4846. return true;
  4847. }
  4848. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, value)) {
  4849. results.push(this);
  4850. return true;
  4851. }
  4852. }
  4853. })
  4854. ;
  4855. }
  4856. module.debug('Showing only matched items', searchTerm);
  4857. module.remove.filteredItem();
  4858. if(results) {
  4859. $item
  4860. .not(results)
  4861. .addClass(className.filtered)
  4862. ;
  4863. }
  4864. },
  4865. fuzzySearch: function(query, term) {
  4866. var
  4867. termLength = term.length,
  4868. queryLength = query.length
  4869. ;
  4870. query = query.toLowerCase();
  4871. term = term.toLowerCase();
  4872. if(queryLength > termLength) {
  4873. return false;
  4874. }
  4875. if(queryLength === termLength) {
  4876. return (query === term);
  4877. }
  4878. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  4879. var
  4880. queryCharacter = query.charCodeAt(characterIndex)
  4881. ;
  4882. while(nextCharacterIndex < termLength) {
  4883. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  4884. continue search;
  4885. }
  4886. }
  4887. return false;
  4888. }
  4889. return true;
  4890. },
  4891. exactSearch: function (query, term) {
  4892. query = query.toLowerCase();
  4893. term = term.toLowerCase();
  4894. if(term.indexOf(query) > -1) {
  4895. return true;
  4896. }
  4897. return false;
  4898. },
  4899. filterActive: function() {
  4900. if(settings.useLabels) {
  4901. $item.filter('.' + className.active)
  4902. .addClass(className.filtered)
  4903. ;
  4904. }
  4905. },
  4906. focusSearch: function(skipHandler) {
  4907. if( module.has.search() && !module.is.focusedOnSearch() ) {
  4908. if(skipHandler) {
  4909. $module.off('focus' + eventNamespace, selector.search);
  4910. $search.focus();
  4911. $module.on('focus' + eventNamespace, selector.search, module.event.search.focus);
  4912. }
  4913. else {
  4914. $search.focus();
  4915. }
  4916. }
  4917. },
  4918. forceSelection: function() {
  4919. var
  4920. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  4921. $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
  4922. $selectedItem = ($currentlySelected.length > 0)
  4923. ? $currentlySelected
  4924. : $activeItem,
  4925. hasSelected = ($selectedItem.length > 0)
  4926. ;
  4927. if(hasSelected && !module.is.multiple()) {
  4928. module.debug('Forcing partial selection to selected item', $selectedItem);
  4929. module.event.item.click.call($selectedItem, {}, true);
  4930. return;
  4931. }
  4932. else {
  4933. if(settings.allowAdditions) {
  4934. module.set.selected(module.get.query());
  4935. module.remove.searchTerm();
  4936. }
  4937. else {
  4938. module.remove.searchTerm();
  4939. }
  4940. }
  4941. },
  4942. change: {
  4943. values: function(values) {
  4944. if(!settings.allowAdditions) {
  4945. module.clear();
  4946. }
  4947. module.debug('Creating dropdown with specified values', values);
  4948. module.setup.menu({values: values});
  4949. $.each(values, function(index, item) {
  4950. if(item.selected == true) {
  4951. module.debug('Setting initial selection to', item.value);
  4952. module.set.selected(item.value);
  4953. return true;
  4954. }
  4955. });
  4956. }
  4957. },
  4958. event: {
  4959. change: function() {
  4960. if(!internalChange) {
  4961. module.debug('Input changed, updating selection');
  4962. module.set.selected();
  4963. }
  4964. },
  4965. focus: function() {
  4966. if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
  4967. module.show();
  4968. }
  4969. },
  4970. blur: function(event) {
  4971. pageLostFocus = (document.activeElement === this);
  4972. if(!activated && !pageLostFocus) {
  4973. module.remove.activeLabel();
  4974. module.hide();
  4975. }
  4976. },
  4977. mousedown: function() {
  4978. if(module.is.searchSelection()) {
  4979. // prevent menu hiding on immediate re-focus
  4980. willRefocus = true;
  4981. }
  4982. else {
  4983. // prevents focus callback from occurring on mousedown
  4984. activated = true;
  4985. }
  4986. },
  4987. mouseup: function() {
  4988. if(module.is.searchSelection()) {
  4989. // prevent menu hiding on immediate re-focus
  4990. willRefocus = false;
  4991. }
  4992. else {
  4993. activated = false;
  4994. }
  4995. },
  4996. click: function(event) {
  4997. var
  4998. $target = $(event.target)
  4999. ;
  5000. // focus search
  5001. if($target.is($module)) {
  5002. if(!module.is.focusedOnSearch()) {
  5003. module.focusSearch();
  5004. }
  5005. else {
  5006. module.show();
  5007. }
  5008. }
  5009. },
  5010. search: {
  5011. focus: function() {
  5012. activated = true;
  5013. if(module.is.multiple()) {
  5014. module.remove.activeLabel();
  5015. }
  5016. if(settings.showOnFocus) {
  5017. module.search();
  5018. }
  5019. },
  5020. blur: function(event) {
  5021. pageLostFocus = (document.activeElement === this);
  5022. if(module.is.searchSelection() && !willRefocus) {
  5023. if(!itemActivated && !pageLostFocus) {
  5024. if(settings.forceSelection) {
  5025. module.forceSelection();
  5026. }
  5027. module.hide();
  5028. }
  5029. }
  5030. willRefocus = false;
  5031. }
  5032. },
  5033. icon: {
  5034. click: function(event) {
  5035. module.toggle();
  5036. }
  5037. },
  5038. text: {
  5039. focus: function(event) {
  5040. activated = true;
  5041. module.focusSearch();
  5042. }
  5043. },
  5044. input: function(event) {
  5045. if(module.is.multiple() || module.is.searchSelection()) {
  5046. module.set.filtered();
  5047. }
  5048. clearTimeout(module.timer);
  5049. module.timer = setTimeout(module.search, settings.delay.search);
  5050. },
  5051. label: {
  5052. click: function(event) {
  5053. var
  5054. $label = $(this),
  5055. $labels = $module.find(selector.label),
  5056. $activeLabels = $labels.filter('.' + className.active),
  5057. $nextActive = $label.nextAll('.' + className.active),
  5058. $prevActive = $label.prevAll('.' + className.active),
  5059. $range = ($nextActive.length > 0)
  5060. ? $label.nextUntil($nextActive).add($activeLabels).add($label)
  5061. : $label.prevUntil($prevActive).add($activeLabels).add($label)
  5062. ;
  5063. if(event.shiftKey) {
  5064. $activeLabels.removeClass(className.active);
  5065. $range.addClass(className.active);
  5066. }
  5067. else if(event.ctrlKey) {
  5068. $label.toggleClass(className.active);
  5069. }
  5070. else {
  5071. $activeLabels.removeClass(className.active);
  5072. $label.addClass(className.active);
  5073. }
  5074. settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
  5075. }
  5076. },
  5077. remove: {
  5078. click: function() {
  5079. var
  5080. $label = $(this).parent()
  5081. ;
  5082. if( $label.hasClass(className.active) ) {
  5083. // remove all selected labels
  5084. module.remove.activeLabels();
  5085. }
  5086. else {
  5087. // remove this label only
  5088. module.remove.activeLabels( $label );
  5089. }
  5090. }
  5091. },
  5092. test: {
  5093. toggle: function(event) {
  5094. var
  5095. toggleBehavior = (module.is.multiple())
  5096. ? module.show
  5097. : module.toggle
  5098. ;
  5099. if(module.is.bubbledLabelClick(event) || module.is.bubbledIconClick(event)) {
  5100. return;
  5101. }
  5102. if( module.determine.eventOnElement(event, toggleBehavior) ) {
  5103. event.preventDefault();
  5104. }
  5105. },
  5106. touch: function(event) {
  5107. module.determine.eventOnElement(event, function() {
  5108. if(event.type == 'touchstart') {
  5109. module.timer = setTimeout(function() {
  5110. module.hide();
  5111. }, settings.delay.touch);
  5112. }
  5113. else if(event.type == 'touchmove') {
  5114. clearTimeout(module.timer);
  5115. }
  5116. });
  5117. event.stopPropagation();
  5118. },
  5119. hide: function(event) {
  5120. module.determine.eventInModule(event, module.hide);
  5121. }
  5122. },
  5123. select: {
  5124. mutation: function(mutations) {
  5125. module.debug('<select> modified, recreating menu');
  5126. var
  5127. isSelectMutation = false
  5128. ;
  5129. $.each(mutations, function(index, mutation) {
  5130. if($(mutation.target).is('select') || $(mutation.addedNodes).is('select')) {
  5131. isSelectMutation = true;
  5132. return true;
  5133. }
  5134. });
  5135. if(isSelectMutation) {
  5136. module.disconnect.selectObserver();
  5137. module.refresh();
  5138. module.setup.select();
  5139. module.set.selected();
  5140. module.observe.select();
  5141. }
  5142. }
  5143. },
  5144. menu: {
  5145. mutation: function(mutations) {
  5146. var
  5147. mutation = mutations[0],
  5148. $addedNode = mutation.addedNodes
  5149. ? $(mutation.addedNodes[0])
  5150. : $(false),
  5151. $removedNode = mutation.removedNodes
  5152. ? $(mutation.removedNodes[0])
  5153. : $(false),
  5154. $changedNodes = $addedNode.add($removedNode),
  5155. isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
  5156. isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
  5157. ;
  5158. if(isUserAddition || isMessage) {
  5159. module.debug('Updating item selector cache');
  5160. module.refreshItems();
  5161. }
  5162. else {
  5163. module.debug('Menu modified, updating selector cache');
  5164. module.refresh();
  5165. }
  5166. },
  5167. mousedown: function() {
  5168. itemActivated = true;
  5169. },
  5170. mouseup: function() {
  5171. itemActivated = false;
  5172. }
  5173. },
  5174. item: {
  5175. mouseenter: function(event) {
  5176. var
  5177. $target = $(event.target),
  5178. $item = $(this),
  5179. $subMenu = $item.children(selector.menu),
  5180. $otherMenus = $item.siblings(selector.item).children(selector.menu),
  5181. hasSubMenu = ($subMenu.length > 0),
  5182. isBubbledEvent = ($subMenu.find($target).length > 0)
  5183. ;
  5184. if( !isBubbledEvent && hasSubMenu ) {
  5185. clearTimeout(module.itemTimer);
  5186. module.itemTimer = setTimeout(function() {
  5187. module.verbose('Showing sub-menu', $subMenu);
  5188. $.each($otherMenus, function() {
  5189. module.animate.hide(false, $(this));
  5190. });
  5191. module.animate.show(false, $subMenu);
  5192. }, settings.delay.show);
  5193. event.preventDefault();
  5194. }
  5195. },
  5196. mouseleave: function(event) {
  5197. var
  5198. $subMenu = $(this).children(selector.menu)
  5199. ;
  5200. if($subMenu.length > 0) {
  5201. clearTimeout(module.itemTimer);
  5202. module.itemTimer = setTimeout(function() {
  5203. module.verbose('Hiding sub-menu', $subMenu);
  5204. module.animate.hide(false, $subMenu);
  5205. }, settings.delay.hide);
  5206. }
  5207. },
  5208. click: function (event, skipRefocus) {
  5209. var
  5210. $choice = $(this),
  5211. $target = (event)
  5212. ? $(event.target)
  5213. : $(''),
  5214. $subMenu = $choice.find(selector.menu),
  5215. text = module.get.choiceText($choice),
  5216. value = module.get.choiceValue($choice, text),
  5217. hasSubMenu = ($subMenu.length > 0),
  5218. isBubbledEvent = ($subMenu.find($target).length > 0)
  5219. ;
  5220. // prevents IE11 bug where menu receives focus even though `tabindex=-1`
  5221. if(module.has.menuSearch()) {
  5222. $(document.activeElement).blur();
  5223. }
  5224. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  5225. if(module.is.searchSelection()) {
  5226. if(settings.allowAdditions) {
  5227. module.remove.userAddition();
  5228. }
  5229. module.remove.searchTerm();
  5230. if(!module.is.focusedOnSearch() && !(skipRefocus == true)) {
  5231. module.focusSearch(true);
  5232. }
  5233. }
  5234. if(!settings.useLabels) {
  5235. module.remove.filteredItem();
  5236. module.set.scrollPosition($choice);
  5237. }
  5238. module.determine.selectAction.call(this, text, value);
  5239. }
  5240. }
  5241. },
  5242. document: {
  5243. // label selection should occur even when element has no focus
  5244. keydown: function(event) {
  5245. var
  5246. pressedKey = event.which,
  5247. isShortcutKey = module.is.inObject(pressedKey, keys)
  5248. ;
  5249. if(isShortcutKey) {
  5250. var
  5251. $label = $module.find(selector.label),
  5252. $activeLabel = $label.filter('.' + className.active),
  5253. activeValue = $activeLabel.data(metadata.value),
  5254. labelIndex = $label.index($activeLabel),
  5255. labelCount = $label.length,
  5256. hasActiveLabel = ($activeLabel.length > 0),
  5257. hasMultipleActive = ($activeLabel.length > 1),
  5258. isFirstLabel = (labelIndex === 0),
  5259. isLastLabel = (labelIndex + 1 == labelCount),
  5260. isSearch = module.is.searchSelection(),
  5261. isFocusedOnSearch = module.is.focusedOnSearch(),
  5262. isFocused = module.is.focused(),
  5263. caretAtStart = (isFocusedOnSearch && module.get.caretPosition() === 0),
  5264. $nextLabel
  5265. ;
  5266. if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
  5267. return;
  5268. }
  5269. if(pressedKey == keys.leftArrow) {
  5270. // activate previous label
  5271. if((isFocused || caretAtStart) && !hasActiveLabel) {
  5272. module.verbose('Selecting previous label');
  5273. $label.last().addClass(className.active);
  5274. }
  5275. else if(hasActiveLabel) {
  5276. if(!event.shiftKey) {
  5277. module.verbose('Selecting previous label');
  5278. $label.removeClass(className.active);
  5279. }
  5280. else {
  5281. module.verbose('Adding previous label to selection');
  5282. }
  5283. if(isFirstLabel && !hasMultipleActive) {
  5284. $activeLabel.addClass(className.active);
  5285. }
  5286. else {
  5287. $activeLabel.prev(selector.siblingLabel)
  5288. .addClass(className.active)
  5289. .end()
  5290. ;
  5291. }
  5292. event.preventDefault();
  5293. }
  5294. }
  5295. else if(pressedKey == keys.rightArrow) {
  5296. // activate first label
  5297. if(isFocused && !hasActiveLabel) {
  5298. $label.first().addClass(className.active);
  5299. }
  5300. // activate next label
  5301. if(hasActiveLabel) {
  5302. if(!event.shiftKey) {
  5303. module.verbose('Selecting next label');
  5304. $label.removeClass(className.active);
  5305. }
  5306. else {
  5307. module.verbose('Adding next label to selection');
  5308. }
  5309. if(isLastLabel) {
  5310. if(isSearch) {
  5311. if(!isFocusedOnSearch) {
  5312. module.focusSearch();
  5313. }
  5314. else {
  5315. $label.removeClass(className.active);
  5316. }
  5317. }
  5318. else if(hasMultipleActive) {
  5319. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  5320. }
  5321. else {
  5322. $activeLabel.addClass(className.active);
  5323. }
  5324. }
  5325. else {
  5326. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  5327. }
  5328. event.preventDefault();
  5329. }
  5330. }
  5331. else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
  5332. if(hasActiveLabel) {
  5333. module.verbose('Removing active labels');
  5334. if(isLastLabel) {
  5335. if(isSearch && !isFocusedOnSearch) {
  5336. module.focusSearch();
  5337. }
  5338. }
  5339. $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
  5340. module.remove.activeLabels($activeLabel);
  5341. event.preventDefault();
  5342. }
  5343. else if(caretAtStart && !hasActiveLabel && pressedKey == keys.backspace) {
  5344. module.verbose('Removing last label on input backspace');
  5345. $activeLabel = $label.last().addClass(className.active);
  5346. module.remove.activeLabels($activeLabel);
  5347. }
  5348. }
  5349. else {
  5350. $activeLabel.removeClass(className.active);
  5351. }
  5352. }
  5353. }
  5354. },
  5355. keydown: function(event) {
  5356. var
  5357. pressedKey = event.which,
  5358. isShortcutKey = module.is.inObject(pressedKey, keys)
  5359. ;
  5360. if(isShortcutKey) {
  5361. var
  5362. $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
  5363. $activeItem = $menu.children('.' + className.active).eq(0),
  5364. $selectedItem = ($currentlySelected.length > 0)
  5365. ? $currentlySelected
  5366. : $activeItem,
  5367. $visibleItems = ($selectedItem.length > 0)
  5368. ? $selectedItem.siblings(':not(.' + className.filtered +')').addBack()
  5369. : $menu.children(':not(.' + className.filtered +')'),
  5370. $subMenu = $selectedItem.children(selector.menu),
  5371. $parentMenu = $selectedItem.closest(selector.menu),
  5372. inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
  5373. hasSubMenu = ($subMenu.length> 0),
  5374. hasSelectedItem = ($selectedItem.length > 0),
  5375. selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
  5376. delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
  5377. isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable),
  5378. $nextItem,
  5379. isSubMenuItem,
  5380. newIndex
  5381. ;
  5382. // allow selection with menu closed
  5383. if(isAdditionWithoutMenu) {
  5384. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  5385. module.event.item.click.call($selectedItem, event);
  5386. if(module.is.searchSelection()) {
  5387. module.remove.searchTerm();
  5388. }
  5389. }
  5390. // visible menu keyboard shortcuts
  5391. if( module.is.visible() ) {
  5392. // enter (select or open sub-menu)
  5393. if(pressedKey == keys.enter || delimiterPressed) {
  5394. if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
  5395. module.verbose('Pressed enter on unselectable category, opening sub menu');
  5396. pressedKey = keys.rightArrow;
  5397. }
  5398. else if(selectedIsSelectable) {
  5399. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  5400. module.event.item.click.call($selectedItem, event);
  5401. if(module.is.searchSelection()) {
  5402. module.remove.searchTerm();
  5403. }
  5404. }
  5405. event.preventDefault();
  5406. }
  5407. // sub-menu actions
  5408. if(hasSelectedItem) {
  5409. if(pressedKey == keys.leftArrow) {
  5410. isSubMenuItem = ($parentMenu[0] !== $menu[0]);
  5411. if(isSubMenuItem) {
  5412. module.verbose('Left key pressed, closing sub-menu');
  5413. module.animate.hide(false, $parentMenu);
  5414. $selectedItem
  5415. .removeClass(className.selected)
  5416. ;
  5417. $parentMenu
  5418. .closest(selector.item)
  5419. .addClass(className.selected)
  5420. ;
  5421. event.preventDefault();
  5422. }
  5423. }
  5424. // right arrow (show sub-menu)
  5425. if(pressedKey == keys.rightArrow) {
  5426. if(hasSubMenu) {
  5427. module.verbose('Right key pressed, opening sub-menu');
  5428. module.animate.show(false, $subMenu);
  5429. $selectedItem
  5430. .removeClass(className.selected)
  5431. ;
  5432. $subMenu
  5433. .find(selector.item).eq(0)
  5434. .addClass(className.selected)
  5435. ;
  5436. event.preventDefault();
  5437. }
  5438. }
  5439. }
  5440. // up arrow (traverse menu up)
  5441. if(pressedKey == keys.upArrow) {
  5442. $nextItem = (hasSelectedItem && inVisibleMenu)
  5443. ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  5444. : $item.eq(0)
  5445. ;
  5446. if($visibleItems.index( $nextItem ) < 0) {
  5447. module.verbose('Up key pressed but reached top of current menu');
  5448. event.preventDefault();
  5449. return;
  5450. }
  5451. else {
  5452. module.verbose('Up key pressed, changing active item');
  5453. $selectedItem
  5454. .removeClass(className.selected)
  5455. ;
  5456. $nextItem
  5457. .addClass(className.selected)
  5458. ;
  5459. module.set.scrollPosition($nextItem);
  5460. if(settings.selectOnKeydown && module.is.single()) {
  5461. module.set.selectedItem($nextItem);
  5462. }
  5463. }
  5464. event.preventDefault();
  5465. }
  5466. // down arrow (traverse menu down)
  5467. if(pressedKey == keys.downArrow) {
  5468. $nextItem = (hasSelectedItem && inVisibleMenu)
  5469. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  5470. : $item.eq(0)
  5471. ;
  5472. if($nextItem.length === 0) {
  5473. module.verbose('Down key pressed but reached bottom of current menu');
  5474. event.preventDefault();
  5475. return;
  5476. }
  5477. else {
  5478. module.verbose('Down key pressed, changing active item');
  5479. $item
  5480. .removeClass(className.selected)
  5481. ;
  5482. $nextItem
  5483. .addClass(className.selected)
  5484. ;
  5485. module.set.scrollPosition($nextItem);
  5486. if(settings.selectOnKeydown && module.is.single()) {
  5487. module.set.selectedItem($nextItem);
  5488. }
  5489. }
  5490. event.preventDefault();
  5491. }
  5492. // page down (show next page)
  5493. if(pressedKey == keys.pageUp) {
  5494. module.scrollPage('up');
  5495. event.preventDefault();
  5496. }
  5497. if(pressedKey == keys.pageDown) {
  5498. module.scrollPage('down');
  5499. event.preventDefault();
  5500. }
  5501. // escape (close menu)
  5502. if(pressedKey == keys.escape) {
  5503. module.verbose('Escape key pressed, closing dropdown');
  5504. module.hide();
  5505. }
  5506. }
  5507. else {
  5508. // delimiter key
  5509. if(delimiterPressed) {
  5510. event.preventDefault();
  5511. }
  5512. // down arrow (open menu)
  5513. if(pressedKey == keys.downArrow && !module.is.visible()) {
  5514. module.verbose('Down key pressed, showing dropdown');
  5515. module.show();
  5516. event.preventDefault();
  5517. }
  5518. }
  5519. }
  5520. else {
  5521. if( !module.has.search() ) {
  5522. module.set.selectedLetter( String.fromCharCode(pressedKey) );
  5523. }
  5524. }
  5525. }
  5526. },
  5527. trigger: {
  5528. change: function() {
  5529. var
  5530. events = document.createEvent('HTMLEvents'),
  5531. inputElement = $input[0]
  5532. ;
  5533. if(inputElement) {
  5534. module.verbose('Triggering native change event');
  5535. events.initEvent('change', true, false);
  5536. inputElement.dispatchEvent(events);
  5537. }
  5538. }
  5539. },
  5540. determine: {
  5541. selectAction: function(text, value) {
  5542. module.verbose('Determining action', settings.action);
  5543. if( $.isFunction( module.action[settings.action] ) ) {
  5544. module.verbose('Triggering preset action', settings.action, text, value);
  5545. module.action[ settings.action ].call(element, text, value, this);
  5546. }
  5547. else if( $.isFunction(settings.action) ) {
  5548. module.verbose('Triggering user action', settings.action, text, value);
  5549. settings.action.call(element, text, value, this);
  5550. }
  5551. else {
  5552. module.error(error.action, settings.action);
  5553. }
  5554. },
  5555. eventInModule: function(event, callback) {
  5556. var
  5557. $target = $(event.target),
  5558. inDocument = ($target.closest(document.documentElement).length > 0),
  5559. inModule = ($target.closest($module).length > 0)
  5560. ;
  5561. callback = $.isFunction(callback)
  5562. ? callback
  5563. : function(){}
  5564. ;
  5565. if(inDocument && !inModule) {
  5566. module.verbose('Triggering event', callback);
  5567. callback();
  5568. return true;
  5569. }
  5570. else {
  5571. module.verbose('Event occurred in dropdown, canceling callback');
  5572. return false;
  5573. }
  5574. },
  5575. eventOnElement: function(event, callback) {
  5576. var
  5577. $target = $(event.target),
  5578. $label = $target.closest(selector.siblingLabel),
  5579. inVisibleDOM = document.body.contains(event.target),
  5580. notOnLabel = ($module.find($label).length === 0),
  5581. notInMenu = ($target.closest($menu).length === 0)
  5582. ;
  5583. callback = $.isFunction(callback)
  5584. ? callback
  5585. : function(){}
  5586. ;
  5587. if(inVisibleDOM && notOnLabel && notInMenu) {
  5588. module.verbose('Triggering event', callback);
  5589. callback();
  5590. return true;
  5591. }
  5592. else {
  5593. module.verbose('Event occurred in dropdown menu, canceling callback');
  5594. return false;
  5595. }
  5596. }
  5597. },
  5598. action: {
  5599. nothing: function() {},
  5600. activate: function(text, value, element) {
  5601. value = (value !== undefined)
  5602. ? value
  5603. : text
  5604. ;
  5605. if( module.can.activate( $(element) ) ) {
  5606. module.set.selected(value, $(element));
  5607. if(module.is.multiple() && !module.is.allFiltered()) {
  5608. return;
  5609. }
  5610. else {
  5611. module.hideAndClear();
  5612. }
  5613. }
  5614. },
  5615. select: function(text, value, element) {
  5616. value = (value !== undefined)
  5617. ? value
  5618. : text
  5619. ;
  5620. if( module.can.activate( $(element) ) ) {
  5621. module.set.value(value, text, $(element));
  5622. if(module.is.multiple() && !module.is.allFiltered()) {
  5623. return;
  5624. }
  5625. else {
  5626. module.hideAndClear();
  5627. }
  5628. }
  5629. },
  5630. combo: function(text, value, element) {
  5631. value = (value !== undefined)
  5632. ? value
  5633. : text
  5634. ;
  5635. module.set.selected(value, $(element));
  5636. module.hideAndClear();
  5637. },
  5638. hide: function(text, value, element) {
  5639. module.set.value(value, text);
  5640. module.hideAndClear();
  5641. }
  5642. },
  5643. get: {
  5644. id: function() {
  5645. return id;
  5646. },
  5647. defaultText: function() {
  5648. return $module.data(metadata.defaultText);
  5649. },
  5650. defaultValue: function() {
  5651. return $module.data(metadata.defaultValue);
  5652. },
  5653. placeholderText: function() {
  5654. if(settings.placeholder != 'auto' && typeof settings.placeholder == 'string') {
  5655. return settings.placeholder;
  5656. }
  5657. return $module.data(metadata.placeholderText) || '';
  5658. },
  5659. text: function() {
  5660. return $text.text();
  5661. },
  5662. query: function() {
  5663. return $.trim($search.val());
  5664. },
  5665. searchWidth: function(value) {
  5666. value = (value !== undefined)
  5667. ? value
  5668. : $search.val()
  5669. ;
  5670. $sizer.text(value);
  5671. // prevent rounding issues
  5672. return Math.ceil( $sizer.width() + 1);
  5673. },
  5674. selectionCount: function() {
  5675. var
  5676. values = module.get.values(),
  5677. count
  5678. ;
  5679. count = ( module.is.multiple() )
  5680. ? $.isArray(values)
  5681. ? values.length
  5682. : 0
  5683. : (module.get.value() !== '')
  5684. ? 1
  5685. : 0
  5686. ;
  5687. return count;
  5688. },
  5689. transition: function($subMenu) {
  5690. return (settings.transition == 'auto')
  5691. ? module.is.upward($subMenu)
  5692. ? 'slide up'
  5693. : 'slide down'
  5694. : settings.transition
  5695. ;
  5696. },
  5697. userValues: function() {
  5698. var
  5699. values = module.get.values()
  5700. ;
  5701. if(!values) {
  5702. return false;
  5703. }
  5704. values = $.isArray(values)
  5705. ? values
  5706. : [values]
  5707. ;
  5708. return $.grep(values, function(value) {
  5709. return (module.get.item(value) === false);
  5710. });
  5711. },
  5712. uniqueArray: function(array) {
  5713. return $.grep(array, function (value, index) {
  5714. return $.inArray(value, array) === index;
  5715. });
  5716. },
  5717. caretPosition: function() {
  5718. var
  5719. input = $search.get(0),
  5720. range,
  5721. rangeLength
  5722. ;
  5723. if('selectionStart' in input) {
  5724. return input.selectionStart;
  5725. }
  5726. else if (document.selection) {
  5727. input.focus();
  5728. range = document.selection.createRange();
  5729. rangeLength = range.text.length;
  5730. range.moveStart('character', -input.value.length);
  5731. return range.text.length - rangeLength;
  5732. }
  5733. },
  5734. value: function() {
  5735. var
  5736. value = ($input.length > 0)
  5737. ? $input.val()
  5738. : $module.data(metadata.value),
  5739. isEmptyMultiselect = ($.isArray(value) && value.length === 1 && value[0] === '')
  5740. ;
  5741. // prevents placeholder element from being selected when multiple
  5742. return (value === undefined || isEmptyMultiselect)
  5743. ? ''
  5744. : value
  5745. ;
  5746. },
  5747. values: function() {
  5748. var
  5749. value = module.get.value()
  5750. ;
  5751. if(value === '') {
  5752. return '';
  5753. }
  5754. return ( !module.has.selectInput() && module.is.multiple() )
  5755. ? (typeof value == 'string') // delimited string
  5756. ? value.split(settings.delimiter)
  5757. : ''
  5758. : value
  5759. ;
  5760. },
  5761. remoteValues: function() {
  5762. var
  5763. values = module.get.values(),
  5764. remoteValues = false
  5765. ;
  5766. if(values) {
  5767. if(typeof values == 'string') {
  5768. values = [values];
  5769. }
  5770. $.each(values, function(index, value) {
  5771. var
  5772. name = module.read.remoteData(value)
  5773. ;
  5774. module.verbose('Restoring value from session data', name, value);
  5775. if(name) {
  5776. if(!remoteValues) {
  5777. remoteValues = {};
  5778. }
  5779. remoteValues[value] = name;
  5780. }
  5781. });
  5782. }
  5783. return remoteValues;
  5784. },
  5785. choiceText: function($choice, preserveHTML) {
  5786. preserveHTML = (preserveHTML !== undefined)
  5787. ? preserveHTML
  5788. : settings.preserveHTML
  5789. ;
  5790. if($choice) {
  5791. if($choice.find(selector.menu).length > 0) {
  5792. module.verbose('Retrieving text of element with sub-menu');
  5793. $choice = $choice.clone();
  5794. $choice.find(selector.menu).remove();
  5795. $choice.find(selector.menuIcon).remove();
  5796. }
  5797. return ($choice.data(metadata.text) !== undefined)
  5798. ? $choice.data(metadata.text)
  5799. : (preserveHTML)
  5800. ? $.trim($choice.html())
  5801. : $.trim($choice.text())
  5802. ;
  5803. }
  5804. },
  5805. choiceValue: function($choice, choiceText) {
  5806. choiceText = choiceText || module.get.choiceText($choice);
  5807. if(!$choice) {
  5808. return false;
  5809. }
  5810. return ($choice.data(metadata.value) !== undefined)
  5811. ? String( $choice.data(metadata.value) )
  5812. : (typeof choiceText === 'string')
  5813. ? $.trim(choiceText.toLowerCase())
  5814. : String(choiceText)
  5815. ;
  5816. },
  5817. inputEvent: function() {
  5818. var
  5819. input = $search[0]
  5820. ;
  5821. if(input) {
  5822. return (input.oninput !== undefined)
  5823. ? 'input'
  5824. : (input.onpropertychange !== undefined)
  5825. ? 'propertychange'
  5826. : 'keyup'
  5827. ;
  5828. }
  5829. return false;
  5830. },
  5831. selectValues: function() {
  5832. var
  5833. select = {}
  5834. ;
  5835. select.values = [];
  5836. $module
  5837. .find('option')
  5838. .each(function() {
  5839. var
  5840. $option = $(this),
  5841. name = $option.html(),
  5842. disabled = $option.attr('disabled'),
  5843. value = ( $option.attr('value') !== undefined )
  5844. ? $option.attr('value')
  5845. : name
  5846. ;
  5847. if(settings.placeholder === 'auto' && value === '') {
  5848. select.placeholder = name;
  5849. }
  5850. else {
  5851. select.values.push({
  5852. name : name,
  5853. value : value,
  5854. disabled : disabled
  5855. });
  5856. }
  5857. })
  5858. ;
  5859. if(settings.placeholder && settings.placeholder !== 'auto') {
  5860. module.debug('Setting placeholder value to', settings.placeholder);
  5861. select.placeholder = settings.placeholder;
  5862. }
  5863. if(settings.sortSelect) {
  5864. select.values.sort(function(a, b) {
  5865. return (a.name > b.name)
  5866. ? 1
  5867. : -1
  5868. ;
  5869. });
  5870. module.debug('Retrieved and sorted values from select', select);
  5871. }
  5872. else {
  5873. module.debug('Retrieved values from select', select);
  5874. }
  5875. return select;
  5876. },
  5877. activeItem: function() {
  5878. return $item.filter('.' + className.active);
  5879. },
  5880. selectedItem: function() {
  5881. var
  5882. $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
  5883. ;
  5884. return ($selectedItem.length > 0)
  5885. ? $selectedItem
  5886. : $item.eq(0)
  5887. ;
  5888. },
  5889. itemWithAdditions: function(value) {
  5890. var
  5891. $items = module.get.item(value),
  5892. $userItems = module.create.userChoice(value),
  5893. hasUserItems = ($userItems && $userItems.length > 0)
  5894. ;
  5895. if(hasUserItems) {
  5896. $items = ($items.length > 0)
  5897. ? $items.add($userItems)
  5898. : $userItems
  5899. ;
  5900. }
  5901. return $items;
  5902. },
  5903. item: function(value, strict) {
  5904. var
  5905. $selectedItem = false,
  5906. shouldSearch,
  5907. isMultiple
  5908. ;
  5909. value = (value !== undefined)
  5910. ? value
  5911. : ( module.get.values() !== undefined)
  5912. ? module.get.values()
  5913. : module.get.text()
  5914. ;
  5915. shouldSearch = (isMultiple)
  5916. ? (value.length > 0)
  5917. : (value !== undefined && value !== null)
  5918. ;
  5919. isMultiple = (module.is.multiple() && $.isArray(value));
  5920. strict = (value === '' || value === 0)
  5921. ? true
  5922. : strict || false
  5923. ;
  5924. if(shouldSearch) {
  5925. $item
  5926. .each(function() {
  5927. var
  5928. $choice = $(this),
  5929. optionText = module.get.choiceText($choice),
  5930. optionValue = module.get.choiceValue($choice, optionText)
  5931. ;
  5932. // safe early exit
  5933. if(optionValue === null || optionValue === undefined) {
  5934. return;
  5935. }
  5936. if(isMultiple) {
  5937. if($.inArray( String(optionValue), value) !== -1 || $.inArray(optionText, value) !== -1) {
  5938. $selectedItem = ($selectedItem)
  5939. ? $selectedItem.add($choice)
  5940. : $choice
  5941. ;
  5942. }
  5943. }
  5944. else if(strict) {
  5945. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  5946. if( optionValue === value || optionText === value) {
  5947. $selectedItem = $choice;
  5948. return true;
  5949. }
  5950. }
  5951. else {
  5952. if( String(optionValue) == String(value) || optionText == value) {
  5953. module.verbose('Found select item by value', optionValue, value);
  5954. $selectedItem = $choice;
  5955. return true;
  5956. }
  5957. }
  5958. })
  5959. ;
  5960. }
  5961. return $selectedItem;
  5962. }
  5963. },
  5964. check: {
  5965. maxSelections: function(selectionCount) {
  5966. if(settings.maxSelections) {
  5967. selectionCount = (selectionCount !== undefined)
  5968. ? selectionCount
  5969. : module.get.selectionCount()
  5970. ;
  5971. if(selectionCount >= settings.maxSelections) {
  5972. module.debug('Maximum selection count reached');
  5973. if(settings.useLabels) {
  5974. $item.addClass(className.filtered);
  5975. module.add.message(message.maxSelections);
  5976. }
  5977. return true;
  5978. }
  5979. else {
  5980. module.verbose('No longer at maximum selection count');
  5981. module.remove.message();
  5982. module.remove.filteredItem();
  5983. if(module.is.searchSelection()) {
  5984. module.filterItems();
  5985. }
  5986. return false;
  5987. }
  5988. }
  5989. return true;
  5990. }
  5991. },
  5992. restore: {
  5993. defaults: function() {
  5994. module.clear();
  5995. module.restore.defaultText();
  5996. module.restore.defaultValue();
  5997. },
  5998. defaultText: function() {
  5999. var
  6000. defaultText = module.get.defaultText(),
  6001. placeholderText = module.get.placeholderText
  6002. ;
  6003. if(defaultText === placeholderText) {
  6004. module.debug('Restoring default placeholder text', defaultText);
  6005. module.set.placeholderText(defaultText);
  6006. }
  6007. else {
  6008. module.debug('Restoring default text', defaultText);
  6009. module.set.text(defaultText);
  6010. }
  6011. },
  6012. placeholderText: function() {
  6013. module.set.placeholderText();
  6014. },
  6015. defaultValue: function() {
  6016. var
  6017. defaultValue = module.get.defaultValue()
  6018. ;
  6019. if(defaultValue !== undefined) {
  6020. module.debug('Restoring default value', defaultValue);
  6021. if(defaultValue !== '') {
  6022. module.set.value(defaultValue);
  6023. module.set.selected();
  6024. }
  6025. else {
  6026. module.remove.activeItem();
  6027. module.remove.selectedItem();
  6028. }
  6029. }
  6030. },
  6031. labels: function() {
  6032. if(settings.allowAdditions) {
  6033. if(!settings.useLabels) {
  6034. module.error(error.labels);
  6035. settings.useLabels = true;
  6036. }
  6037. module.debug('Restoring selected values');
  6038. module.create.userLabels();
  6039. }
  6040. module.check.maxSelections();
  6041. },
  6042. selected: function() {
  6043. module.restore.values();
  6044. if(module.is.multiple()) {
  6045. module.debug('Restoring previously selected values and labels');
  6046. module.restore.labels();
  6047. }
  6048. else {
  6049. module.debug('Restoring previously selected values');
  6050. }
  6051. },
  6052. values: function() {
  6053. // prevents callbacks from occurring on initial load
  6054. module.set.initialLoad();
  6055. if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) {
  6056. module.restore.remoteValues();
  6057. }
  6058. else {
  6059. module.set.selected();
  6060. }
  6061. module.remove.initialLoad();
  6062. },
  6063. remoteValues: function() {
  6064. var
  6065. values = module.get.remoteValues()
  6066. ;
  6067. module.debug('Recreating selected from session data', values);
  6068. if(values) {
  6069. if( module.is.single() ) {
  6070. $.each(values, function(value, name) {
  6071. module.set.text(name);
  6072. });
  6073. }
  6074. else {
  6075. $.each(values, function(value, name) {
  6076. module.add.label(value, name);
  6077. });
  6078. }
  6079. }
  6080. }
  6081. },
  6082. read: {
  6083. remoteData: function(value) {
  6084. var
  6085. name
  6086. ;
  6087. if(window.Storage === undefined) {
  6088. module.error(error.noStorage);
  6089. return;
  6090. }
  6091. name = sessionStorage.getItem(value);
  6092. return (name !== undefined)
  6093. ? name
  6094. : false
  6095. ;
  6096. }
  6097. },
  6098. save: {
  6099. defaults: function() {
  6100. module.save.defaultText();
  6101. module.save.placeholderText();
  6102. module.save.defaultValue();
  6103. },
  6104. defaultValue: function() {
  6105. var
  6106. value = module.get.value()
  6107. ;
  6108. module.verbose('Saving default value as', value);
  6109. $module.data(metadata.defaultValue, value);
  6110. },
  6111. defaultText: function() {
  6112. var
  6113. text = module.get.text()
  6114. ;
  6115. module.verbose('Saving default text as', text);
  6116. $module.data(metadata.defaultText, text);
  6117. },
  6118. placeholderText: function() {
  6119. var
  6120. text
  6121. ;
  6122. if(settings.placeholder !== false && $text.hasClass(className.placeholder)) {
  6123. text = module.get.text();
  6124. module.verbose('Saving placeholder text as', text);
  6125. $module.data(metadata.placeholderText, text);
  6126. }
  6127. },
  6128. remoteData: function(name, value) {
  6129. if(window.Storage === undefined) {
  6130. module.error(error.noStorage);
  6131. return;
  6132. }
  6133. module.verbose('Saving remote data to session storage', value, name);
  6134. sessionStorage.setItem(value, name);
  6135. }
  6136. },
  6137. clear: function() {
  6138. if(module.is.multiple() && settings.useLabels) {
  6139. module.remove.labels();
  6140. }
  6141. else {
  6142. module.remove.activeItem();
  6143. module.remove.selectedItem();
  6144. }
  6145. module.set.placeholderText();
  6146. module.clearValue();
  6147. },
  6148. clearValue: function() {
  6149. module.set.value('');
  6150. },
  6151. scrollPage: function(direction, $selectedItem) {
  6152. var
  6153. $currentItem = $selectedItem || module.get.selectedItem(),
  6154. $menu = $currentItem.closest(selector.menu),
  6155. menuHeight = $menu.outerHeight(),
  6156. currentScroll = $menu.scrollTop(),
  6157. itemHeight = $item.eq(0).outerHeight(),
  6158. itemsPerPage = Math.floor(menuHeight / itemHeight),
  6159. maxScroll = $menu.prop('scrollHeight'),
  6160. newScroll = (direction == 'up')
  6161. ? currentScroll - (itemHeight * itemsPerPage)
  6162. : currentScroll + (itemHeight * itemsPerPage),
  6163. $selectableItem = $item.not(selector.unselectable),
  6164. isWithinRange,
  6165. $nextSelectedItem,
  6166. elementIndex
  6167. ;
  6168. elementIndex = (direction == 'up')
  6169. ? $selectableItem.index($currentItem) - itemsPerPage
  6170. : $selectableItem.index($currentItem) + itemsPerPage
  6171. ;
  6172. isWithinRange = (direction == 'up')
  6173. ? (elementIndex >= 0)
  6174. : (elementIndex < $selectableItem.length)
  6175. ;
  6176. $nextSelectedItem = (isWithinRange)
  6177. ? $selectableItem.eq(elementIndex)
  6178. : (direction == 'up')
  6179. ? $selectableItem.first()
  6180. : $selectableItem.last()
  6181. ;
  6182. if($nextSelectedItem.length > 0) {
  6183. module.debug('Scrolling page', direction, $nextSelectedItem);
  6184. $currentItem
  6185. .removeClass(className.selected)
  6186. ;
  6187. $nextSelectedItem
  6188. .addClass(className.selected)
  6189. ;
  6190. if(settings.selectOnKeydown && module.is.single()) {
  6191. module.set.selectedItem($nextSelectedItem);
  6192. }
  6193. $menu
  6194. .scrollTop(newScroll)
  6195. ;
  6196. }
  6197. },
  6198. set: {
  6199. filtered: function() {
  6200. var
  6201. isMultiple = module.is.multiple(),
  6202. isSearch = module.is.searchSelection(),
  6203. isSearchMultiple = (isMultiple && isSearch),
  6204. searchValue = (isSearch)
  6205. ? module.get.query()
  6206. : '',
  6207. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
  6208. searchWidth = module.get.searchWidth(),
  6209. valueIsSet = searchValue !== ''
  6210. ;
  6211. if(isMultiple && hasSearchValue) {
  6212. module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
  6213. $search.css('width', searchWidth);
  6214. }
  6215. if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
  6216. module.verbose('Hiding placeholder text');
  6217. $text.addClass(className.filtered);
  6218. }
  6219. else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
  6220. module.verbose('Showing placeholder text');
  6221. $text.removeClass(className.filtered);
  6222. }
  6223. },
  6224. empty: function() {
  6225. $module.addClass(className.empty);
  6226. },
  6227. loading: function() {
  6228. $module.addClass(className.loading);
  6229. },
  6230. placeholderText: function(text) {
  6231. text = text || module.get.placeholderText();
  6232. module.debug('Setting placeholder text', text);
  6233. module.set.text(text);
  6234. $text.addClass(className.placeholder);
  6235. },
  6236. tabbable: function() {
  6237. if( module.is.searchSelection() ) {
  6238. module.debug('Added tabindex to searchable dropdown');
  6239. $search
  6240. .val('')
  6241. .attr('tabindex', 0)
  6242. ;
  6243. $menu
  6244. .attr('tabindex', -1)
  6245. ;
  6246. }
  6247. else {
  6248. module.debug('Added tabindex to dropdown');
  6249. if( $module.attr('tabindex') === undefined) {
  6250. $module
  6251. .attr('tabindex', 0)
  6252. ;
  6253. $menu
  6254. .attr('tabindex', -1)
  6255. ;
  6256. }
  6257. }
  6258. },
  6259. initialLoad: function() {
  6260. module.verbose('Setting initial load');
  6261. initialLoad = true;
  6262. },
  6263. activeItem: function($item) {
  6264. if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) {
  6265. $item.addClass(className.filtered);
  6266. }
  6267. else {
  6268. $item.addClass(className.active);
  6269. }
  6270. },
  6271. partialSearch: function(text) {
  6272. var
  6273. length = module.get.query().length
  6274. ;
  6275. $search.val( text.substr(0, length));
  6276. },
  6277. scrollPosition: function($item, forceScroll) {
  6278. var
  6279. edgeTolerance = 5,
  6280. $menu,
  6281. hasActive,
  6282. offset,
  6283. itemHeight,
  6284. itemOffset,
  6285. menuOffset,
  6286. menuScroll,
  6287. menuHeight,
  6288. abovePage,
  6289. belowPage
  6290. ;
  6291. $item = $item || module.get.selectedItem();
  6292. $menu = $item.closest(selector.menu);
  6293. hasActive = ($item && $item.length > 0);
  6294. forceScroll = (forceScroll !== undefined)
  6295. ? forceScroll
  6296. : false
  6297. ;
  6298. if($item && $menu.length > 0 && hasActive) {
  6299. itemOffset = $item.position().top;
  6300. $menu.addClass(className.loading);
  6301. menuScroll = $menu.scrollTop();
  6302. menuOffset = $menu.offset().top;
  6303. itemOffset = $item.offset().top;
  6304. offset = menuScroll - menuOffset + itemOffset;
  6305. if(!forceScroll) {
  6306. menuHeight = $menu.height();
  6307. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  6308. abovePage = ((offset - edgeTolerance) < menuScroll);
  6309. }
  6310. module.debug('Scrolling to active item', offset);
  6311. if(forceScroll || abovePage || belowPage) {
  6312. $menu.scrollTop(offset);
  6313. }
  6314. $menu.removeClass(className.loading);
  6315. }
  6316. },
  6317. text: function(text) {
  6318. if(settings.action !== 'select') {
  6319. if(settings.action == 'combo') {
  6320. module.debug('Changing combo button text', text, $combo);
  6321. if(settings.preserveHTML) {
  6322. $combo.html(text);
  6323. }
  6324. else {
  6325. $combo.text(text);
  6326. }
  6327. }
  6328. else {
  6329. if(text !== module.get.placeholderText()) {
  6330. $text.removeClass(className.placeholder);
  6331. }
  6332. module.debug('Changing text', text, $text);
  6333. $text
  6334. .removeClass(className.filtered)
  6335. ;
  6336. if(settings.preserveHTML) {
  6337. $text.html(text);
  6338. }
  6339. else {
  6340. $text.text(text);
  6341. }
  6342. }
  6343. }
  6344. },
  6345. selectedItem: function($item) {
  6346. var
  6347. value = module.get.choiceValue($item),
  6348. searchText = module.get.choiceText($item, false),
  6349. text = module.get.choiceText($item, true)
  6350. ;
  6351. module.debug('Setting user selection to item', $item);
  6352. module.remove.activeItem();
  6353. module.set.partialSearch(searchText);
  6354. module.set.activeItem($item);
  6355. module.set.selected(value, $item);
  6356. module.set.text(text);
  6357. },
  6358. selectedLetter: function(letter) {
  6359. var
  6360. $selectedItem = $item.filter('.' + className.selected),
  6361. alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter),
  6362. $nextValue = false,
  6363. $nextItem
  6364. ;
  6365. // check next of same letter
  6366. if(alreadySelectedLetter) {
  6367. $nextItem = $selectedItem.nextAll($item).eq(0);
  6368. if( module.has.firstLetter($nextItem, letter) ) {
  6369. $nextValue = $nextItem;
  6370. }
  6371. }
  6372. // check all values
  6373. if(!$nextValue) {
  6374. $item
  6375. .each(function(){
  6376. if(module.has.firstLetter($(this), letter)) {
  6377. $nextValue = $(this);
  6378. return false;
  6379. }
  6380. })
  6381. ;
  6382. }
  6383. // set next value
  6384. if($nextValue) {
  6385. module.verbose('Scrolling to next value with letter', letter);
  6386. module.set.scrollPosition($nextValue);
  6387. $selectedItem.removeClass(className.selected);
  6388. $nextValue.addClass(className.selected);
  6389. if(settings.selectOnKeydown && module.is.single()) {
  6390. module.set.selectedItem($nextValue);
  6391. }
  6392. }
  6393. },
  6394. direction: function($menu) {
  6395. if(settings.direction == 'auto') {
  6396. // reset position
  6397. module.remove.upward();
  6398. if(module.can.openDownward($menu)) {
  6399. module.remove.upward($menu);
  6400. }
  6401. else {
  6402. module.set.upward($menu);
  6403. }
  6404. if(!module.is.leftward($menu) && !module.can.openRightward($menu)) {
  6405. module.set.leftward($menu);
  6406. }
  6407. }
  6408. else if(settings.direction == 'upward') {
  6409. module.set.upward($menu);
  6410. }
  6411. },
  6412. upward: function($currentMenu) {
  6413. var $element = $currentMenu || $module;
  6414. $element.addClass(className.upward);
  6415. },
  6416. leftward: function($currentMenu) {
  6417. var $element = $currentMenu || $menu;
  6418. $element.addClass(className.leftward);
  6419. },
  6420. value: function(value, text, $selected) {
  6421. var
  6422. escapedValue = module.escape.value(value),
  6423. hasInput = ($input.length > 0),
  6424. currentValue = module.get.values(),
  6425. stringValue = (value !== undefined)
  6426. ? String(value)
  6427. : value,
  6428. newValue
  6429. ;
  6430. if(hasInput) {
  6431. if(!settings.allowReselection && stringValue == currentValue) {
  6432. module.verbose('Skipping value update already same value', value, currentValue);
  6433. if(!module.is.initialLoad()) {
  6434. return;
  6435. }
  6436. }
  6437. if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) {
  6438. module.debug('Adding user option', value);
  6439. module.add.optionValue(value);
  6440. }
  6441. module.debug('Updating input value', escapedValue, currentValue);
  6442. internalChange = true;
  6443. $input
  6444. .val(escapedValue)
  6445. ;
  6446. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6447. module.debug('Input native change event ignored on initial load');
  6448. }
  6449. else {
  6450. module.trigger.change();
  6451. }
  6452. internalChange = false;
  6453. }
  6454. else {
  6455. module.verbose('Storing value in metadata', escapedValue, $input);
  6456. if(escapedValue !== currentValue) {
  6457. $module.data(metadata.value, stringValue);
  6458. }
  6459. }
  6460. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6461. module.verbose('No callback on initial load', settings.onChange);
  6462. }
  6463. else {
  6464. settings.onChange.call(element, value, text, $selected);
  6465. }
  6466. },
  6467. active: function() {
  6468. $module
  6469. .addClass(className.active)
  6470. ;
  6471. },
  6472. multiple: function() {
  6473. $module.addClass(className.multiple);
  6474. },
  6475. visible: function() {
  6476. $module.addClass(className.visible);
  6477. },
  6478. exactly: function(value, $selectedItem) {
  6479. module.debug('Setting selected to exact values');
  6480. module.clear();
  6481. module.set.selected(value, $selectedItem);
  6482. },
  6483. selected: function(value, $selectedItem) {
  6484. var
  6485. isMultiple = module.is.multiple(),
  6486. $userSelectedItem
  6487. ;
  6488. $selectedItem = (settings.allowAdditions)
  6489. ? $selectedItem || module.get.itemWithAdditions(value)
  6490. : $selectedItem || module.get.item(value)
  6491. ;
  6492. if(!$selectedItem) {
  6493. return;
  6494. }
  6495. module.debug('Setting selected menu item to', $selectedItem);
  6496. if(module.is.multiple()) {
  6497. module.remove.searchWidth();
  6498. }
  6499. if(module.is.single()) {
  6500. module.remove.activeItem();
  6501. module.remove.selectedItem();
  6502. }
  6503. else if(settings.useLabels) {
  6504. module.remove.selectedItem();
  6505. }
  6506. // select each item
  6507. $selectedItem
  6508. .each(function() {
  6509. var
  6510. $selected = $(this),
  6511. selectedText = module.get.choiceText($selected),
  6512. selectedValue = module.get.choiceValue($selected, selectedText),
  6513. isFiltered = $selected.hasClass(className.filtered),
  6514. isActive = $selected.hasClass(className.active),
  6515. isUserValue = $selected.hasClass(className.addition),
  6516. shouldAnimate = (isMultiple && $selectedItem.length == 1)
  6517. ;
  6518. if(isMultiple) {
  6519. if(!isActive || isUserValue) {
  6520. if(settings.apiSettings && settings.saveRemoteData) {
  6521. module.save.remoteData(selectedText, selectedValue);
  6522. }
  6523. if(settings.useLabels) {
  6524. module.add.label(selectedValue, selectedText, shouldAnimate);
  6525. module.add.value(selectedValue, selectedText, $selected);
  6526. module.set.activeItem($selected);
  6527. module.filterActive();
  6528. module.select.nextAvailable($selectedItem);
  6529. }
  6530. else {
  6531. module.add.value(selectedValue, selectedText, $selected);
  6532. module.set.text(module.add.variables(message.count));
  6533. module.set.activeItem($selected);
  6534. }
  6535. }
  6536. else if(!isFiltered) {
  6537. module.debug('Selected active value, removing label');
  6538. module.remove.selected(selectedValue);
  6539. }
  6540. }
  6541. else {
  6542. if(settings.apiSettings && settings.saveRemoteData) {
  6543. module.save.remoteData(selectedText, selectedValue);
  6544. }
  6545. module.set.text(selectedText);
  6546. module.set.value(selectedValue, selectedText, $selected);
  6547. $selected
  6548. .addClass(className.active)
  6549. .addClass(className.selected)
  6550. ;
  6551. }
  6552. })
  6553. ;
  6554. }
  6555. },
  6556. add: {
  6557. label: function(value, text, shouldAnimate) {
  6558. var
  6559. $next = module.is.searchSelection()
  6560. ? $search
  6561. : $text,
  6562. escapedValue = module.escape.value(value),
  6563. $label
  6564. ;
  6565. if(settings.ignoreCase) {
  6566. escapedValue = escapedValue.toLowerCase();
  6567. }
  6568. $label = $('<a />')
  6569. .addClass(className.label)
  6570. .attr('data-' + metadata.value, escapedValue)
  6571. .html(templates.label(escapedValue, text))
  6572. ;
  6573. $label = settings.onLabelCreate.call($label, escapedValue, text);
  6574. if(module.has.label(value)) {
  6575. module.debug('User selection already exists, skipping', escapedValue);
  6576. return;
  6577. }
  6578. if(settings.label.variation) {
  6579. $label.addClass(settings.label.variation);
  6580. }
  6581. if(shouldAnimate === true) {
  6582. module.debug('Animating in label', $label);
  6583. $label
  6584. .addClass(className.hidden)
  6585. .insertBefore($next)
  6586. .transition(settings.label.transition, settings.label.duration)
  6587. ;
  6588. }
  6589. else {
  6590. module.debug('Adding selection label', $label);
  6591. $label
  6592. .insertBefore($next)
  6593. ;
  6594. }
  6595. },
  6596. message: function(message) {
  6597. var
  6598. $message = $menu.children(selector.message),
  6599. html = settings.templates.message(module.add.variables(message))
  6600. ;
  6601. if($message.length > 0) {
  6602. $message
  6603. .html(html)
  6604. ;
  6605. }
  6606. else {
  6607. $message = $('<div/>')
  6608. .html(html)
  6609. .addClass(className.message)
  6610. .appendTo($menu)
  6611. ;
  6612. }
  6613. },
  6614. optionValue: function(value) {
  6615. var
  6616. escapedValue = module.escape.value(value),
  6617. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  6618. hasOption = ($option.length > 0)
  6619. ;
  6620. if(hasOption) {
  6621. return;
  6622. }
  6623. // temporarily disconnect observer
  6624. module.disconnect.selectObserver();
  6625. if( module.is.single() ) {
  6626. module.verbose('Removing previous user addition');
  6627. $input.find('option.' + className.addition).remove();
  6628. }
  6629. $('<option/>')
  6630. .prop('value', escapedValue)
  6631. .addClass(className.addition)
  6632. .html(value)
  6633. .appendTo($input)
  6634. ;
  6635. module.verbose('Adding user addition as an <option>', value);
  6636. module.observe.select();
  6637. },
  6638. userSuggestion: function(value) {
  6639. var
  6640. $addition = $menu.children(selector.addition),
  6641. $existingItem = module.get.item(value),
  6642. alreadyHasValue = $existingItem && $existingItem.not(selector.addition).length,
  6643. hasUserSuggestion = $addition.length > 0,
  6644. html
  6645. ;
  6646. if(settings.useLabels && module.has.maxSelections()) {
  6647. return;
  6648. }
  6649. if(value === '' || alreadyHasValue) {
  6650. $addition.remove();
  6651. return;
  6652. }
  6653. if(hasUserSuggestion) {
  6654. $addition
  6655. .data(metadata.value, value)
  6656. .data(metadata.text, value)
  6657. .attr('data-' + metadata.value, value)
  6658. .attr('data-' + metadata.text, value)
  6659. .removeClass(className.filtered)
  6660. ;
  6661. if(!settings.hideAdditions) {
  6662. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  6663. $addition
  6664. .html(html)
  6665. ;
  6666. }
  6667. module.verbose('Replacing user suggestion with new value', $addition);
  6668. }
  6669. else {
  6670. $addition = module.create.userChoice(value);
  6671. $addition
  6672. .prependTo($menu)
  6673. ;
  6674. module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
  6675. }
  6676. if(!settings.hideAdditions || module.is.allFiltered()) {
  6677. $addition
  6678. .addClass(className.selected)
  6679. .siblings()
  6680. .removeClass(className.selected)
  6681. ;
  6682. }
  6683. module.refreshItems();
  6684. },
  6685. variables: function(message, term) {
  6686. var
  6687. hasCount = (message.search('{count}') !== -1),
  6688. hasMaxCount = (message.search('{maxCount}') !== -1),
  6689. hasTerm = (message.search('{term}') !== -1),
  6690. values,
  6691. count,
  6692. query
  6693. ;
  6694. module.verbose('Adding templated variables to message', message);
  6695. if(hasCount) {
  6696. count = module.get.selectionCount();
  6697. message = message.replace('{count}', count);
  6698. }
  6699. if(hasMaxCount) {
  6700. count = module.get.selectionCount();
  6701. message = message.replace('{maxCount}', settings.maxSelections);
  6702. }
  6703. if(hasTerm) {
  6704. query = term || module.get.query();
  6705. message = message.replace('{term}', query);
  6706. }
  6707. return message;
  6708. },
  6709. value: function(addedValue, addedText, $selectedItem) {
  6710. var
  6711. currentValue = module.get.values(),
  6712. newValue
  6713. ;
  6714. if(module.has.value(addedValue)) {
  6715. module.debug('Value already selected');
  6716. return;
  6717. }
  6718. if(addedValue === '') {
  6719. module.debug('Cannot select blank values from multiselect');
  6720. return;
  6721. }
  6722. // extend current array
  6723. if($.isArray(currentValue)) {
  6724. newValue = currentValue.concat([addedValue]);
  6725. newValue = module.get.uniqueArray(newValue);
  6726. }
  6727. else {
  6728. newValue = [addedValue];
  6729. }
  6730. // add values
  6731. if( module.has.selectInput() ) {
  6732. if(module.can.extendSelect()) {
  6733. module.debug('Adding value to select', addedValue, newValue, $input);
  6734. module.add.optionValue(addedValue);
  6735. }
  6736. }
  6737. else {
  6738. newValue = newValue.join(settings.delimiter);
  6739. module.debug('Setting hidden input to delimited value', newValue, $input);
  6740. }
  6741. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6742. module.verbose('Skipping onadd callback on initial load', settings.onAdd);
  6743. }
  6744. else {
  6745. settings.onAdd.call(element, addedValue, addedText, $selectedItem);
  6746. }
  6747. module.set.value(newValue, addedValue, addedText, $selectedItem);
  6748. module.check.maxSelections();
  6749. }
  6750. },
  6751. remove: {
  6752. active: function() {
  6753. $module.removeClass(className.active);
  6754. },
  6755. activeLabel: function() {
  6756. $module.find(selector.label).removeClass(className.active);
  6757. },
  6758. empty: function() {
  6759. $module.removeClass(className.empty);
  6760. },
  6761. loading: function() {
  6762. $module.removeClass(className.loading);
  6763. },
  6764. initialLoad: function() {
  6765. initialLoad = false;
  6766. },
  6767. upward: function($currentMenu) {
  6768. var $element = $currentMenu || $module;
  6769. $element.removeClass(className.upward);
  6770. },
  6771. leftward: function($currentMenu) {
  6772. var $element = $currentMenu || $menu;
  6773. $element.removeClass(className.leftward);
  6774. },
  6775. visible: function() {
  6776. $module.removeClass(className.visible);
  6777. },
  6778. activeItem: function() {
  6779. $item.removeClass(className.active);
  6780. },
  6781. filteredItem: function() {
  6782. if(settings.useLabels && module.has.maxSelections() ) {
  6783. return;
  6784. }
  6785. if(settings.useLabels && module.is.multiple()) {
  6786. $item.not('.' + className.active).removeClass(className.filtered);
  6787. }
  6788. else {
  6789. $item.removeClass(className.filtered);
  6790. }
  6791. module.remove.empty();
  6792. },
  6793. optionValue: function(value) {
  6794. var
  6795. escapedValue = module.escape.value(value),
  6796. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  6797. hasOption = ($option.length > 0)
  6798. ;
  6799. if(!hasOption || !$option.hasClass(className.addition)) {
  6800. return;
  6801. }
  6802. // temporarily disconnect observer
  6803. if(selectObserver) {
  6804. selectObserver.disconnect();
  6805. module.verbose('Temporarily disconnecting mutation observer');
  6806. }
  6807. $option.remove();
  6808. module.verbose('Removing user addition as an <option>', escapedValue);
  6809. if(selectObserver) {
  6810. selectObserver.observe($input[0], {
  6811. childList : true,
  6812. subtree : true
  6813. });
  6814. }
  6815. },
  6816. message: function() {
  6817. $menu.children(selector.message).remove();
  6818. },
  6819. searchWidth: function() {
  6820. $search.css('width', '');
  6821. },
  6822. searchTerm: function() {
  6823. module.verbose('Cleared search term');
  6824. $search.val('');
  6825. module.set.filtered();
  6826. },
  6827. userAddition: function() {
  6828. $item.filter(selector.addition).remove();
  6829. },
  6830. selected: function(value, $selectedItem) {
  6831. $selectedItem = (settings.allowAdditions)
  6832. ? $selectedItem || module.get.itemWithAdditions(value)
  6833. : $selectedItem || module.get.item(value)
  6834. ;
  6835. if(!$selectedItem) {
  6836. return false;
  6837. }
  6838. $selectedItem
  6839. .each(function() {
  6840. var
  6841. $selected = $(this),
  6842. selectedText = module.get.choiceText($selected),
  6843. selectedValue = module.get.choiceValue($selected, selectedText)
  6844. ;
  6845. if(module.is.multiple()) {
  6846. if(settings.useLabels) {
  6847. module.remove.value(selectedValue, selectedText, $selected);
  6848. module.remove.label(selectedValue);
  6849. }
  6850. else {
  6851. module.remove.value(selectedValue, selectedText, $selected);
  6852. if(module.get.selectionCount() === 0) {
  6853. module.set.placeholderText();
  6854. }
  6855. else {
  6856. module.set.text(module.add.variables(message.count));
  6857. }
  6858. }
  6859. }
  6860. else {
  6861. module.remove.value(selectedValue, selectedText, $selected);
  6862. }
  6863. $selected
  6864. .removeClass(className.filtered)
  6865. .removeClass(className.active)
  6866. ;
  6867. if(settings.useLabels) {
  6868. $selected.removeClass(className.selected);
  6869. }
  6870. })
  6871. ;
  6872. },
  6873. selectedItem: function() {
  6874. $item.removeClass(className.selected);
  6875. },
  6876. value: function(removedValue, removedText, $removedItem) {
  6877. var
  6878. values = module.get.values(),
  6879. newValue
  6880. ;
  6881. if( module.has.selectInput() ) {
  6882. module.verbose('Input is <select> removing selected option', removedValue);
  6883. newValue = module.remove.arrayValue(removedValue, values);
  6884. module.remove.optionValue(removedValue);
  6885. }
  6886. else {
  6887. module.verbose('Removing from delimited values', removedValue);
  6888. newValue = module.remove.arrayValue(removedValue, values);
  6889. newValue = newValue.join(settings.delimiter);
  6890. }
  6891. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6892. module.verbose('No callback on initial load', settings.onRemove);
  6893. }
  6894. else {
  6895. settings.onRemove.call(element, removedValue, removedText, $removedItem);
  6896. }
  6897. module.set.value(newValue, removedText, $removedItem);
  6898. module.check.maxSelections();
  6899. },
  6900. arrayValue: function(removedValue, values) {
  6901. if( !$.isArray(values) ) {
  6902. values = [values];
  6903. }
  6904. values = $.grep(values, function(value){
  6905. return (removedValue != value);
  6906. });
  6907. module.verbose('Removed value from delimited string', removedValue, values);
  6908. return values;
  6909. },
  6910. label: function(value, shouldAnimate) {
  6911. var
  6912. $labels = $module.find(selector.label),
  6913. $removedLabel = $labels.filter('[data-' + metadata.value + '="' + module.escape.string(value) +'"]')
  6914. ;
  6915. module.verbose('Removing label', $removedLabel);
  6916. $removedLabel.remove();
  6917. },
  6918. activeLabels: function($activeLabels) {
  6919. $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
  6920. module.verbose('Removing active label selections', $activeLabels);
  6921. module.remove.labels($activeLabels);
  6922. },
  6923. labels: function($labels) {
  6924. $labels = $labels || $module.find(selector.label);
  6925. module.verbose('Removing labels', $labels);
  6926. $labels
  6927. .each(function(){
  6928. var
  6929. $label = $(this),
  6930. value = $label.data(metadata.value),
  6931. stringValue = (value !== undefined)
  6932. ? String(value)
  6933. : value,
  6934. isUserValue = module.is.userValue(stringValue)
  6935. ;
  6936. if(settings.onLabelRemove.call($label, value) === false) {
  6937. module.debug('Label remove callback cancelled removal');
  6938. return;
  6939. }
  6940. module.remove.message();
  6941. if(isUserValue) {
  6942. module.remove.value(stringValue);
  6943. module.remove.label(stringValue);
  6944. }
  6945. else {
  6946. // selected will also remove label
  6947. module.remove.selected(stringValue);
  6948. }
  6949. })
  6950. ;
  6951. },
  6952. tabbable: function() {
  6953. if( module.is.searchSelection() ) {
  6954. module.debug('Searchable dropdown initialized');
  6955. $search
  6956. .removeAttr('tabindex')
  6957. ;
  6958. $menu
  6959. .removeAttr('tabindex')
  6960. ;
  6961. }
  6962. else {
  6963. module.debug('Simple selection dropdown initialized');
  6964. $module
  6965. .removeAttr('tabindex')
  6966. ;
  6967. $menu
  6968. .removeAttr('tabindex')
  6969. ;
  6970. }
  6971. }
  6972. },
  6973. has: {
  6974. menuSearch: function() {
  6975. return (module.has.search() && $search.closest($menu).length > 0);
  6976. },
  6977. search: function() {
  6978. return ($search.length > 0);
  6979. },
  6980. sizer: function() {
  6981. return ($sizer.length > 0);
  6982. },
  6983. selectInput: function() {
  6984. return ( $input.is('select') );
  6985. },
  6986. minCharacters: function(searchTerm) {
  6987. if(settings.minCharacters) {
  6988. searchTerm = (searchTerm !== undefined)
  6989. ? String(searchTerm)
  6990. : String(module.get.query())
  6991. ;
  6992. return (searchTerm.length >= settings.minCharacters);
  6993. }
  6994. return true;
  6995. },
  6996. firstLetter: function($item, letter) {
  6997. var
  6998. text,
  6999. firstLetter
  7000. ;
  7001. if(!$item || $item.length === 0 || typeof letter !== 'string') {
  7002. return false;
  7003. }
  7004. text = module.get.choiceText($item, false);
  7005. letter = letter.toLowerCase();
  7006. firstLetter = String(text).charAt(0).toLowerCase();
  7007. return (letter == firstLetter);
  7008. },
  7009. input: function() {
  7010. return ($input.length > 0);
  7011. },
  7012. items: function() {
  7013. return ($item.length > 0);
  7014. },
  7015. menu: function() {
  7016. return ($menu.length > 0);
  7017. },
  7018. message: function() {
  7019. return ($menu.children(selector.message).length !== 0);
  7020. },
  7021. label: function(value) {
  7022. var
  7023. escapedValue = module.escape.value(value),
  7024. $labels = $module.find(selector.label)
  7025. ;
  7026. if(settings.ignoreCase) {
  7027. escapedValue = escapedValue.toLowerCase();
  7028. }
  7029. return ($labels.filter('[data-' + metadata.value + '="' + module.escape.string(escapedValue) +'"]').length > 0);
  7030. },
  7031. maxSelections: function() {
  7032. return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
  7033. },
  7034. allResultsFiltered: function() {
  7035. var
  7036. $normalResults = $item.not(selector.addition)
  7037. ;
  7038. return ($normalResults.filter(selector.unselectable).length === $normalResults.length);
  7039. },
  7040. userSuggestion: function() {
  7041. return ($menu.children(selector.addition).length > 0);
  7042. },
  7043. query: function() {
  7044. return (module.get.query() !== '');
  7045. },
  7046. value: function(value) {
  7047. return (settings.ignoreCase)
  7048. ? module.has.valueIgnoringCase(value)
  7049. : module.has.valueMatchingCase(value)
  7050. ;
  7051. },
  7052. valueMatchingCase: function(value) {
  7053. var
  7054. values = module.get.values(),
  7055. hasValue = $.isArray(values)
  7056. ? values && ($.inArray(value, values) !== -1)
  7057. : (values == value)
  7058. ;
  7059. return (hasValue)
  7060. ? true
  7061. : false
  7062. ;
  7063. },
  7064. valueIgnoringCase: function(value) {
  7065. var
  7066. values = module.get.values(),
  7067. hasValue = false
  7068. ;
  7069. if(!$.isArray(values)) {
  7070. values = [values];
  7071. }
  7072. $.each(values, function(index, existingValue) {
  7073. if(String(value).toLowerCase() == String(existingValue).toLowerCase()) {
  7074. hasValue = true;
  7075. return false;
  7076. }
  7077. });
  7078. return hasValue;
  7079. }
  7080. },
  7081. is: {
  7082. active: function() {
  7083. return $module.hasClass(className.active);
  7084. },
  7085. animatingInward: function() {
  7086. return $menu.transition('is inward');
  7087. },
  7088. animatingOutward: function() {
  7089. return $menu.transition('is outward');
  7090. },
  7091. bubbledLabelClick: function(event) {
  7092. return $(event.target).is('select, input') && $module.closest('label').length > 0;
  7093. },
  7094. bubbledIconClick: function(event) {
  7095. return $(event.target).closest($icon).length > 0;
  7096. },
  7097. alreadySetup: function() {
  7098. return ($module.is('select') && $module.parent(selector.dropdown).data(moduleNamespace) !== undefined && $module.prev().length === 0);
  7099. },
  7100. animating: function($subMenu) {
  7101. return ($subMenu)
  7102. ? $subMenu.transition && $subMenu.transition('is animating')
  7103. : $menu.transition && $menu.transition('is animating')
  7104. ;
  7105. },
  7106. leftward: function($subMenu) {
  7107. var $selectedMenu = $subMenu || $menu;
  7108. return $selectedMenu.hasClass(className.leftward);
  7109. },
  7110. disabled: function() {
  7111. return $module.hasClass(className.disabled);
  7112. },
  7113. focused: function() {
  7114. return (document.activeElement === $module[0]);
  7115. },
  7116. focusedOnSearch: function() {
  7117. return (document.activeElement === $search[0]);
  7118. },
  7119. allFiltered: function() {
  7120. return( (module.is.multiple() || module.has.search()) && !(settings.hideAdditions == false && module.has.userSuggestion()) && !module.has.message() && module.has.allResultsFiltered() );
  7121. },
  7122. hidden: function($subMenu) {
  7123. return !module.is.visible($subMenu);
  7124. },
  7125. initialLoad: function() {
  7126. return initialLoad;
  7127. },
  7128. inObject: function(needle, object) {
  7129. var
  7130. found = false
  7131. ;
  7132. $.each(object, function(index, property) {
  7133. if(property == needle) {
  7134. found = true;
  7135. return true;
  7136. }
  7137. });
  7138. return found;
  7139. },
  7140. multiple: function() {
  7141. return $module.hasClass(className.multiple);
  7142. },
  7143. remote: function() {
  7144. return settings.apiSettings && module.can.useAPI();
  7145. },
  7146. single: function() {
  7147. return !module.is.multiple();
  7148. },
  7149. selectMutation: function(mutations) {
  7150. var
  7151. selectChanged = false
  7152. ;
  7153. $.each(mutations, function(index, mutation) {
  7154. if(mutation.target && $(mutation.target).is('select')) {
  7155. selectChanged = true;
  7156. return true;
  7157. }
  7158. });
  7159. return selectChanged;
  7160. },
  7161. search: function() {
  7162. return $module.hasClass(className.search);
  7163. },
  7164. searchSelection: function() {
  7165. return ( module.has.search() && $search.parent(selector.dropdown).length === 1 );
  7166. },
  7167. selection: function() {
  7168. return $module.hasClass(className.selection);
  7169. },
  7170. userValue: function(value) {
  7171. return ($.inArray(value, module.get.userValues()) !== -1);
  7172. },
  7173. upward: function($menu) {
  7174. var $element = $menu || $module;
  7175. return $element.hasClass(className.upward);
  7176. },
  7177. visible: function($subMenu) {
  7178. return ($subMenu)
  7179. ? $subMenu.hasClass(className.visible)
  7180. : $menu.hasClass(className.visible)
  7181. ;
  7182. },
  7183. verticallyScrollableContext: function() {
  7184. var
  7185. overflowY = ($context.get(0) !== window)
  7186. ? $context.css('overflow-y')
  7187. : false
  7188. ;
  7189. return (overflowY == 'auto' || overflowY == 'scroll');
  7190. },
  7191. horizontallyScrollableContext: function() {
  7192. var
  7193. overflowX = ($context.get(0) !== window)
  7194. ? $context.css('overflow-X')
  7195. : false
  7196. ;
  7197. return (overflowX == 'auto' || overflowX == 'scroll');
  7198. }
  7199. },
  7200. can: {
  7201. activate: function($item) {
  7202. if(settings.useLabels) {
  7203. return true;
  7204. }
  7205. if(!module.has.maxSelections()) {
  7206. return true;
  7207. }
  7208. if(module.has.maxSelections() && $item.hasClass(className.active)) {
  7209. return true;
  7210. }
  7211. return false;
  7212. },
  7213. openDownward: function($subMenu) {
  7214. var
  7215. $currentMenu = $subMenu || $menu,
  7216. canOpenDownward = true,
  7217. onScreen = {},
  7218. calculations
  7219. ;
  7220. $currentMenu
  7221. .addClass(className.loading)
  7222. ;
  7223. calculations = {
  7224. context: {
  7225. offset : ($context.get(0) === window)
  7226. ? { top: 0, left: 0}
  7227. : $context.offset(),
  7228. scrollTop : $context.scrollTop(),
  7229. height : $context.outerHeight()
  7230. },
  7231. menu : {
  7232. offset: $currentMenu.offset(),
  7233. height: $currentMenu.outerHeight()
  7234. }
  7235. };
  7236. if(module.is.verticallyScrollableContext()) {
  7237. calculations.menu.offset.top += calculations.context.scrollTop;
  7238. }
  7239. onScreen = {
  7240. above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.context.offset.top - calculations.menu.height,
  7241. below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top - calculations.context.offset.top + calculations.menu.height
  7242. };
  7243. if(onScreen.below) {
  7244. module.verbose('Dropdown can fit in context downward', onScreen);
  7245. canOpenDownward = true;
  7246. }
  7247. else if(!onScreen.below && !onScreen.above) {
  7248. module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
  7249. canOpenDownward = true;
  7250. }
  7251. else {
  7252. module.verbose('Dropdown cannot fit below, opening upward', onScreen);
  7253. canOpenDownward = false;
  7254. }
  7255. $currentMenu.removeClass(className.loading);
  7256. return canOpenDownward;
  7257. },
  7258. openRightward: function($subMenu) {
  7259. var
  7260. $currentMenu = $subMenu || $menu,
  7261. canOpenRightward = true,
  7262. isOffscreenRight = false,
  7263. calculations
  7264. ;
  7265. $currentMenu
  7266. .addClass(className.loading)
  7267. ;
  7268. calculations = {
  7269. context: {
  7270. offset : ($context.get(0) === window)
  7271. ? { top: 0, left: 0}
  7272. : $context.offset(),
  7273. scrollLeft : $context.scrollLeft(),
  7274. width : $context.outerWidth()
  7275. },
  7276. menu: {
  7277. offset : $currentMenu.offset(),
  7278. width : $currentMenu.outerWidth()
  7279. }
  7280. };
  7281. if(module.is.horizontallyScrollableContext()) {
  7282. calculations.menu.offset.left += calculations.context.scrollLeft;
  7283. }
  7284. isOffscreenRight = (calculations.menu.offset.left - calculations.context.offset.left + calculations.menu.width >= calculations.context.scrollLeft + calculations.context.width);
  7285. if(isOffscreenRight) {
  7286. module.verbose('Dropdown cannot fit in context rightward', isOffscreenRight);
  7287. canOpenRightward = false;
  7288. }
  7289. $currentMenu.removeClass(className.loading);
  7290. return canOpenRightward;
  7291. },
  7292. click: function() {
  7293. return (hasTouch || settings.on == 'click');
  7294. },
  7295. extendSelect: function() {
  7296. return settings.allowAdditions || settings.apiSettings;
  7297. },
  7298. show: function() {
  7299. return !module.is.disabled() && (module.has.items() || module.has.message());
  7300. },
  7301. useAPI: function() {
  7302. return $.fn.api !== undefined;
  7303. }
  7304. },
  7305. animate: {
  7306. show: function(callback, $subMenu) {
  7307. var
  7308. $currentMenu = $subMenu || $menu,
  7309. start = ($subMenu)
  7310. ? function() {}
  7311. : function() {
  7312. module.hideSubMenus();
  7313. module.hideOthers();
  7314. module.set.active();
  7315. },
  7316. transition
  7317. ;
  7318. callback = $.isFunction(callback)
  7319. ? callback
  7320. : function(){}
  7321. ;
  7322. module.verbose('Doing menu show animation', $currentMenu);
  7323. module.set.direction($subMenu);
  7324. transition = module.get.transition($subMenu);
  7325. if( module.is.selection() ) {
  7326. module.set.scrollPosition(module.get.selectedItem(), true);
  7327. }
  7328. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  7329. if(transition == 'none') {
  7330. start();
  7331. $currentMenu.transition('show');
  7332. callback.call(element);
  7333. }
  7334. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  7335. $currentMenu
  7336. .transition({
  7337. animation : transition + ' in',
  7338. debug : settings.debug,
  7339. verbose : settings.verbose,
  7340. duration : settings.duration,
  7341. queue : true,
  7342. onStart : start,
  7343. onComplete : function() {
  7344. callback.call(element);
  7345. }
  7346. })
  7347. ;
  7348. }
  7349. else {
  7350. module.error(error.noTransition, transition);
  7351. }
  7352. }
  7353. },
  7354. hide: function(callback, $subMenu) {
  7355. var
  7356. $currentMenu = $subMenu || $menu,
  7357. duration = ($subMenu)
  7358. ? (settings.duration * 0.9)
  7359. : settings.duration,
  7360. start = ($subMenu)
  7361. ? function() {}
  7362. : function() {
  7363. if( module.can.click() ) {
  7364. module.unbind.intent();
  7365. }
  7366. module.remove.active();
  7367. },
  7368. transition = module.get.transition($subMenu)
  7369. ;
  7370. callback = $.isFunction(callback)
  7371. ? callback
  7372. : function(){}
  7373. ;
  7374. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  7375. module.verbose('Doing menu hide animation', $currentMenu);
  7376. if(transition == 'none') {
  7377. start();
  7378. $currentMenu.transition('hide');
  7379. callback.call(element);
  7380. }
  7381. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  7382. $currentMenu
  7383. .transition({
  7384. animation : transition + ' out',
  7385. duration : settings.duration,
  7386. debug : settings.debug,
  7387. verbose : settings.verbose,
  7388. queue : false,
  7389. onStart : start,
  7390. onComplete : function() {
  7391. callback.call(element);
  7392. }
  7393. })
  7394. ;
  7395. }
  7396. else {
  7397. module.error(error.transition);
  7398. }
  7399. }
  7400. }
  7401. },
  7402. hideAndClear: function() {
  7403. module.remove.searchTerm();
  7404. if( module.has.maxSelections() ) {
  7405. return;
  7406. }
  7407. if(module.has.search()) {
  7408. module.hide(function() {
  7409. module.remove.filteredItem();
  7410. });
  7411. }
  7412. else {
  7413. module.hide();
  7414. }
  7415. },
  7416. delay: {
  7417. show: function() {
  7418. module.verbose('Delaying show event to ensure user intent');
  7419. clearTimeout(module.timer);
  7420. module.timer = setTimeout(module.show, settings.delay.show);
  7421. },
  7422. hide: function() {
  7423. module.verbose('Delaying hide event to ensure user intent');
  7424. clearTimeout(module.timer);
  7425. module.timer = setTimeout(module.hide, settings.delay.hide);
  7426. }
  7427. },
  7428. escape: {
  7429. value: function(value) {
  7430. var
  7431. multipleValues = $.isArray(value),
  7432. stringValue = (typeof value === 'string'),
  7433. isUnparsable = (!stringValue && !multipleValues),
  7434. hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
  7435. values = []
  7436. ;
  7437. if(isUnparsable || !hasQuotes) {
  7438. return value;
  7439. }
  7440. module.debug('Encoding quote values for use in select', value);
  7441. if(multipleValues) {
  7442. $.each(value, function(index, value){
  7443. values.push(value.replace(regExp.quote, '&quot;'));
  7444. });
  7445. return values;
  7446. }
  7447. return value.replace(regExp.quote, '&quot;');
  7448. },
  7449. string: function(text) {
  7450. text = String(text);
  7451. return text.replace(regExp.escape, '\\$&');
  7452. }
  7453. },
  7454. setting: function(name, value) {
  7455. module.debug('Changing setting', name, value);
  7456. if( $.isPlainObject(name) ) {
  7457. $.extend(true, settings, name);
  7458. }
  7459. else if(value !== undefined) {
  7460. if($.isPlainObject(settings[name])) {
  7461. $.extend(true, settings[name], value);
  7462. }
  7463. else {
  7464. settings[name] = value;
  7465. }
  7466. }
  7467. else {
  7468. return settings[name];
  7469. }
  7470. },
  7471. internal: function(name, value) {
  7472. if( $.isPlainObject(name) ) {
  7473. $.extend(true, module, name);
  7474. }
  7475. else if(value !== undefined) {
  7476. module[name] = value;
  7477. }
  7478. else {
  7479. return module[name];
  7480. }
  7481. },
  7482. debug: function() {
  7483. if(!settings.silent && settings.debug) {
  7484. if(settings.performance) {
  7485. module.performance.log(arguments);
  7486. }
  7487. else {
  7488. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7489. module.debug.apply(console, arguments);
  7490. }
  7491. }
  7492. },
  7493. verbose: function() {
  7494. if(!settings.silent && settings.verbose && settings.debug) {
  7495. if(settings.performance) {
  7496. module.performance.log(arguments);
  7497. }
  7498. else {
  7499. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7500. module.verbose.apply(console, arguments);
  7501. }
  7502. }
  7503. },
  7504. error: function() {
  7505. if(!settings.silent) {
  7506. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  7507. module.error.apply(console, arguments);
  7508. }
  7509. },
  7510. performance: {
  7511. log: function(message) {
  7512. var
  7513. currentTime,
  7514. executionTime,
  7515. previousTime
  7516. ;
  7517. if(settings.performance) {
  7518. currentTime = new Date().getTime();
  7519. previousTime = time || currentTime;
  7520. executionTime = currentTime - previousTime;
  7521. time = currentTime;
  7522. performance.push({
  7523. 'Name' : message[0],
  7524. 'Arguments' : [].slice.call(message, 1) || '',
  7525. 'Element' : element,
  7526. 'Execution Time' : executionTime
  7527. });
  7528. }
  7529. clearTimeout(module.performance.timer);
  7530. module.performance.timer = setTimeout(module.performance.display, 500);
  7531. },
  7532. display: function() {
  7533. var
  7534. title = settings.name + ':',
  7535. totalTime = 0
  7536. ;
  7537. time = false;
  7538. clearTimeout(module.performance.timer);
  7539. $.each(performance, function(index, data) {
  7540. totalTime += data['Execution Time'];
  7541. });
  7542. title += ' ' + totalTime + 'ms';
  7543. if(moduleSelector) {
  7544. title += ' \'' + moduleSelector + '\'';
  7545. }
  7546. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  7547. console.groupCollapsed(title);
  7548. if(console.table) {
  7549. console.table(performance);
  7550. }
  7551. else {
  7552. $.each(performance, function(index, data) {
  7553. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  7554. });
  7555. }
  7556. console.groupEnd();
  7557. }
  7558. performance = [];
  7559. }
  7560. },
  7561. invoke: function(query, passedArguments, context) {
  7562. var
  7563. object = instance,
  7564. maxDepth,
  7565. found,
  7566. response
  7567. ;
  7568. passedArguments = passedArguments || queryArguments;
  7569. context = element || context;
  7570. if(typeof query == 'string' && object !== undefined) {
  7571. query = query.split(/[\. ]/);
  7572. maxDepth = query.length - 1;
  7573. $.each(query, function(depth, value) {
  7574. var camelCaseValue = (depth != maxDepth)
  7575. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  7576. : query
  7577. ;
  7578. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  7579. object = object[camelCaseValue];
  7580. }
  7581. else if( object[camelCaseValue] !== undefined ) {
  7582. found = object[camelCaseValue];
  7583. return false;
  7584. }
  7585. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  7586. object = object[value];
  7587. }
  7588. else if( object[value] !== undefined ) {
  7589. found = object[value];
  7590. return false;
  7591. }
  7592. else {
  7593. module.error(error.method, query);
  7594. return false;
  7595. }
  7596. });
  7597. }
  7598. if ( $.isFunction( found ) ) {
  7599. response = found.apply(context, passedArguments);
  7600. }
  7601. else if(found !== undefined) {
  7602. response = found;
  7603. }
  7604. if($.isArray(returnedValue)) {
  7605. returnedValue.push(response);
  7606. }
  7607. else if(returnedValue !== undefined) {
  7608. returnedValue = [returnedValue, response];
  7609. }
  7610. else if(response !== undefined) {
  7611. returnedValue = response;
  7612. }
  7613. return found;
  7614. }
  7615. };
  7616. if(methodInvoked) {
  7617. if(instance === undefined) {
  7618. module.initialize();
  7619. }
  7620. module.invoke(query);
  7621. }
  7622. else {
  7623. if(instance !== undefined) {
  7624. instance.invoke('destroy');
  7625. }
  7626. module.initialize();
  7627. }
  7628. })
  7629. ;
  7630. return (returnedValue !== undefined)
  7631. ? returnedValue
  7632. : $allModules
  7633. ;
  7634. };
  7635. $.fn.dropdown.settings = {
  7636. silent : false,
  7637. debug : false,
  7638. verbose : false,
  7639. performance : true,
  7640. on : 'click', // what event should show menu action on item selection
  7641. action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
  7642. values : false, // specify values to use for dropdown
  7643. apiSettings : false,
  7644. selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
  7645. minCharacters : 0, // Minimum characters required to trigger API call
  7646. filterRemoteData : false, // Whether API results should be filtered after being returned for query term
  7647. saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
  7648. throttle : 200, // How long to wait after last user input to search remotely
  7649. context : window, // Context to use when determining if on screen
  7650. direction : 'auto', // Whether dropdown should always open in one direction
  7651. keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
  7652. match : 'both', // what to match against with search selection (both, text, or label)
  7653. fullTextSearch : false, // search anywhere in value (set to 'exact' to require exact matches)
  7654. placeholder : 'auto', // whether to convert blank <select> values to placeholder text
  7655. preserveHTML : true, // preserve html when selecting value
  7656. sortSelect : false, // sort selection on init
  7657. forceSelection : true, // force a choice on blur with search selection
  7658. allowAdditions : false, // whether multiple select should allow user added values
  7659. ignoreCase : false, // whether to consider values not matching in case to be the same
  7660. hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
  7661. maxSelections : false, // When set to a number limits the number of selections to this count
  7662. useLabels : true, // whether multiple select should filter currently active selections from choices
  7663. delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
  7664. showOnFocus : true, // show menu on focus
  7665. allowReselection : false, // whether current value should trigger callbacks when reselected
  7666. allowTab : true, // add tabindex to element
  7667. allowCategorySelection : false, // allow elements with sub-menus to be selected
  7668. fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
  7669. transition : 'auto', // auto transition will slide down or up based on direction
  7670. duration : 200, // duration of transition
  7671. glyphWidth : 1.037, // widest glyph width in em (W is 1.037 em) used to calculate multiselect input width
  7672. // label settings on multi-select
  7673. label: {
  7674. transition : 'scale',
  7675. duration : 200,
  7676. variation : false
  7677. },
  7678. // delay before event
  7679. delay : {
  7680. hide : 300,
  7681. show : 200,
  7682. search : 20,
  7683. touch : 50
  7684. },
  7685. /* Callbacks */
  7686. onChange : function(value, text, $selected){},
  7687. onAdd : function(value, text, $selected){},
  7688. onRemove : function(value, text, $selected){},
  7689. onLabelSelect : function($selectedLabels){},
  7690. onLabelCreate : function(value, text) { return $(this); },
  7691. onLabelRemove : function(value) { return true; },
  7692. onNoResults : function(searchTerm) { return true; },
  7693. onShow : function(){},
  7694. onHide : function(){},
  7695. /* Component */
  7696. name : 'Dropdown',
  7697. namespace : 'dropdown',
  7698. message: {
  7699. addResult : 'Add <b>{term}</b>',
  7700. count : '{count} selected',
  7701. maxSelections : 'Max {maxCount} selections',
  7702. noResults : 'No results found.',
  7703. serverError : 'There was an error contacting the server'
  7704. },
  7705. error : {
  7706. action : 'You called a dropdown action that was not defined',
  7707. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  7708. labels : 'Allowing user additions currently requires the use of labels.',
  7709. missingMultiple : '<select> requires multiple property to be set to correctly preserve multiple values',
  7710. method : 'The method you called is not defined.',
  7711. noAPI : 'The API module is required to load resources remotely',
  7712. noStorage : 'Saving remote data requires session storage',
  7713. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>'
  7714. },
  7715. regExp : {
  7716. escape : /[-[\]{}()*+?.,\\^$|#\s]/g,
  7717. quote : /"/g
  7718. },
  7719. metadata : {
  7720. defaultText : 'defaultText',
  7721. defaultValue : 'defaultValue',
  7722. placeholderText : 'placeholder',
  7723. text : 'text',
  7724. value : 'value'
  7725. },
  7726. // property names for remote query
  7727. fields: {
  7728. remoteValues : 'results', // grouping for api results
  7729. values : 'values', // grouping for all dropdown values
  7730. disabled : 'disabled', // whether value should be disabled
  7731. name : 'name', // displayed dropdown text
  7732. value : 'value', // actual dropdown value
  7733. text : 'text' // displayed text when selected
  7734. },
  7735. keys : {
  7736. backspace : 8,
  7737. delimiter : 188, // comma
  7738. deleteKey : 46,
  7739. enter : 13,
  7740. escape : 27,
  7741. pageUp : 33,
  7742. pageDown : 34,
  7743. leftArrow : 37,
  7744. upArrow : 38,
  7745. rightArrow : 39,
  7746. downArrow : 40
  7747. },
  7748. selector : {
  7749. addition : '.addition',
  7750. dropdown : '.ui.dropdown',
  7751. hidden : '.hidden',
  7752. icon : '> .dropdown.icon',
  7753. input : '> input[type="hidden"], > select',
  7754. item : '.item',
  7755. label : '> .label',
  7756. remove : '> .label > .delete.icon',
  7757. siblingLabel : '.label',
  7758. menu : '.menu',
  7759. message : '.message',
  7760. menuIcon : '.dropdown.icon',
  7761. search : 'input.search, .menu > .search > input, .menu input.search',
  7762. sizer : '> input.sizer',
  7763. text : '> .text:not(.icon)',
  7764. unselectable : '.disabled, .filtered'
  7765. },
  7766. className : {
  7767. active : 'active',
  7768. addition : 'addition',
  7769. animating : 'animating',
  7770. disabled : 'disabled',
  7771. empty : 'empty',
  7772. dropdown : 'ui dropdown',
  7773. filtered : 'filtered',
  7774. hidden : 'hidden transition',
  7775. item : 'item',
  7776. label : 'ui label',
  7777. loading : 'loading',
  7778. menu : 'menu',
  7779. message : 'message',
  7780. multiple : 'multiple',
  7781. placeholder : 'default',
  7782. sizer : 'sizer',
  7783. search : 'search',
  7784. selected : 'selected',
  7785. selection : 'selection',
  7786. upward : 'upward',
  7787. leftward : 'left',
  7788. visible : 'visible'
  7789. }
  7790. };
  7791. /* Templates */
  7792. $.fn.dropdown.settings.templates = {
  7793. // generates dropdown from select values
  7794. dropdown: function(select) {
  7795. var
  7796. placeholder = select.placeholder || false,
  7797. values = select.values || {},
  7798. html = ''
  7799. ;
  7800. html += '<i class="dropdown icon"></i>';
  7801. if(select.placeholder) {
  7802. html += '<div class="default text">' + placeholder + '</div>';
  7803. }
  7804. else {
  7805. html += '<div class="text"></div>';
  7806. }
  7807. html += '<div class="menu">';
  7808. $.each(select.values, function(index, option) {
  7809. html += (option.disabled)
  7810. ? '<div class="disabled item" data-value="' + option.value + '">' + option.name + '</div>'
  7811. : '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'
  7812. ;
  7813. });
  7814. html += '</div>';
  7815. return html;
  7816. },
  7817. // generates just menu from select
  7818. menu: function(response, fields) {
  7819. var
  7820. values = response[fields.values] || {},
  7821. html = ''
  7822. ;
  7823. $.each(values, function(index, option) {
  7824. var
  7825. maybeText = (option[fields.text])
  7826. ? 'data-text="' + option[fields.text] + '"'
  7827. : '',
  7828. maybeDisabled = (option[fields.disabled])
  7829. ? 'disabled '
  7830. : ''
  7831. ;
  7832. html += '<div class="'+ maybeDisabled +'item" data-value="' + option[fields.value] + '"' + maybeText + '>';
  7833. html += option[fields.name];
  7834. html += '</div>';
  7835. });
  7836. return html;
  7837. },
  7838. // generates label for multiselect
  7839. label: function(value, text) {
  7840. return text + '<i class="delete icon"></i>';
  7841. },
  7842. // generates messages like "No results"
  7843. message: function(message) {
  7844. return message;
  7845. },
  7846. // generates user addition to selection menu
  7847. addition: function(choice) {
  7848. return choice;
  7849. }
  7850. };
  7851. })( jQuery, window, document );
  7852. /*!
  7853. * # Semantic UI 2.3.3 - Embed
  7854. * http://github.com/semantic-org/semantic-ui/
  7855. *
  7856. *
  7857. * Released under the MIT license
  7858. * http://opensource.org/licenses/MIT
  7859. *
  7860. */
  7861. ;(function ($, window, document, undefined) {
  7862. 'use strict';
  7863. window = (typeof window != 'undefined' && window.Math == Math)
  7864. ? window
  7865. : (typeof self != 'undefined' && self.Math == Math)
  7866. ? self
  7867. : Function('return this')()
  7868. ;
  7869. $.fn.embed = function(parameters) {
  7870. var
  7871. $allModules = $(this),
  7872. moduleSelector = $allModules.selector || '',
  7873. time = new Date().getTime(),
  7874. performance = [],
  7875. query = arguments[0],
  7876. methodInvoked = (typeof query == 'string'),
  7877. queryArguments = [].slice.call(arguments, 1),
  7878. returnedValue
  7879. ;
  7880. $allModules
  7881. .each(function() {
  7882. var
  7883. settings = ( $.isPlainObject(parameters) )
  7884. ? $.extend(true, {}, $.fn.embed.settings, parameters)
  7885. : $.extend({}, $.fn.embed.settings),
  7886. selector = settings.selector,
  7887. className = settings.className,
  7888. sources = settings.sources,
  7889. error = settings.error,
  7890. metadata = settings.metadata,
  7891. namespace = settings.namespace,
  7892. templates = settings.templates,
  7893. eventNamespace = '.' + namespace,
  7894. moduleNamespace = 'module-' + namespace,
  7895. $window = $(window),
  7896. $module = $(this),
  7897. $placeholder = $module.find(selector.placeholder),
  7898. $icon = $module.find(selector.icon),
  7899. $embed = $module.find(selector.embed),
  7900. element = this,
  7901. instance = $module.data(moduleNamespace),
  7902. module
  7903. ;
  7904. module = {
  7905. initialize: function() {
  7906. module.debug('Initializing embed');
  7907. module.determine.autoplay();
  7908. module.create();
  7909. module.bind.events();
  7910. module.instantiate();
  7911. },
  7912. instantiate: function() {
  7913. module.verbose('Storing instance of module', module);
  7914. instance = module;
  7915. $module
  7916. .data(moduleNamespace, module)
  7917. ;
  7918. },
  7919. destroy: function() {
  7920. module.verbose('Destroying previous instance of embed');
  7921. module.reset();
  7922. $module
  7923. .removeData(moduleNamespace)
  7924. .off(eventNamespace)
  7925. ;
  7926. },
  7927. refresh: function() {
  7928. module.verbose('Refreshing selector cache');
  7929. $placeholder = $module.find(selector.placeholder);
  7930. $icon = $module.find(selector.icon);
  7931. $embed = $module.find(selector.embed);
  7932. },
  7933. bind: {
  7934. events: function() {
  7935. if( module.has.placeholder() ) {
  7936. module.debug('Adding placeholder events');
  7937. $module
  7938. .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
  7939. .on('click' + eventNamespace, selector.icon, module.createAndShow)
  7940. ;
  7941. }
  7942. }
  7943. },
  7944. create: function() {
  7945. var
  7946. placeholder = module.get.placeholder()
  7947. ;
  7948. if(placeholder) {
  7949. module.createPlaceholder();
  7950. }
  7951. else {
  7952. module.createAndShow();
  7953. }
  7954. },
  7955. createPlaceholder: function(placeholder) {
  7956. var
  7957. icon = module.get.icon(),
  7958. url = module.get.url(),
  7959. embed = module.generate.embed(url)
  7960. ;
  7961. placeholder = placeholder || module.get.placeholder();
  7962. $module.html( templates.placeholder(placeholder, icon) );
  7963. module.debug('Creating placeholder for embed', placeholder, icon);
  7964. },
  7965. createEmbed: function(url) {
  7966. module.refresh();
  7967. url = url || module.get.url();
  7968. $embed = $('<div/>')
  7969. .addClass(className.embed)
  7970. .html( module.generate.embed(url) )
  7971. .appendTo($module)
  7972. ;
  7973. settings.onCreate.call(element, url);
  7974. module.debug('Creating embed object', $embed);
  7975. },
  7976. changeEmbed: function(url) {
  7977. $embed
  7978. .html( module.generate.embed(url) )
  7979. ;
  7980. },
  7981. createAndShow: function() {
  7982. module.createEmbed();
  7983. module.show();
  7984. },
  7985. // sets new embed
  7986. change: function(source, id, url) {
  7987. module.debug('Changing video to ', source, id, url);
  7988. $module
  7989. .data(metadata.source, source)
  7990. .data(metadata.id, id)
  7991. ;
  7992. if(url) {
  7993. $module.data(metadata.url, url);
  7994. }
  7995. else {
  7996. $module.removeData(metadata.url);
  7997. }
  7998. if(module.has.embed()) {
  7999. module.changeEmbed();
  8000. }
  8001. else {
  8002. module.create();
  8003. }
  8004. },
  8005. // clears embed
  8006. reset: function() {
  8007. module.debug('Clearing embed and showing placeholder');
  8008. module.remove.active();
  8009. module.remove.embed();
  8010. module.showPlaceholder();
  8011. settings.onReset.call(element);
  8012. },
  8013. // shows current embed
  8014. show: function() {
  8015. module.debug('Showing embed');
  8016. module.set.active();
  8017. settings.onDisplay.call(element);
  8018. },
  8019. hide: function() {
  8020. module.debug('Hiding embed');
  8021. module.showPlaceholder();
  8022. },
  8023. showPlaceholder: function() {
  8024. module.debug('Showing placeholder image');
  8025. module.remove.active();
  8026. settings.onPlaceholderDisplay.call(element);
  8027. },
  8028. get: {
  8029. id: function() {
  8030. return settings.id || $module.data(metadata.id);
  8031. },
  8032. placeholder: function() {
  8033. return settings.placeholder || $module.data(metadata.placeholder);
  8034. },
  8035. icon: function() {
  8036. return (settings.icon)
  8037. ? settings.icon
  8038. : ($module.data(metadata.icon) !== undefined)
  8039. ? $module.data(metadata.icon)
  8040. : module.determine.icon()
  8041. ;
  8042. },
  8043. source: function(url) {
  8044. return (settings.source)
  8045. ? settings.source
  8046. : ($module.data(metadata.source) !== undefined)
  8047. ? $module.data(metadata.source)
  8048. : module.determine.source()
  8049. ;
  8050. },
  8051. type: function() {
  8052. var source = module.get.source();
  8053. return (sources[source] !== undefined)
  8054. ? sources[source].type
  8055. : false
  8056. ;
  8057. },
  8058. url: function() {
  8059. return (settings.url)
  8060. ? settings.url
  8061. : ($module.data(metadata.url) !== undefined)
  8062. ? $module.data(metadata.url)
  8063. : module.determine.url()
  8064. ;
  8065. }
  8066. },
  8067. determine: {
  8068. autoplay: function() {
  8069. if(module.should.autoplay()) {
  8070. settings.autoplay = true;
  8071. }
  8072. },
  8073. source: function(url) {
  8074. var
  8075. matchedSource = false
  8076. ;
  8077. url = url || module.get.url();
  8078. if(url) {
  8079. $.each(sources, function(name, source) {
  8080. if(url.search(source.domain) !== -1) {
  8081. matchedSource = name;
  8082. return false;
  8083. }
  8084. });
  8085. }
  8086. return matchedSource;
  8087. },
  8088. icon: function() {
  8089. var
  8090. source = module.get.source()
  8091. ;
  8092. return (sources[source] !== undefined)
  8093. ? sources[source].icon
  8094. : false
  8095. ;
  8096. },
  8097. url: function() {
  8098. var
  8099. id = settings.id || $module.data(metadata.id),
  8100. source = settings.source || $module.data(metadata.source),
  8101. url
  8102. ;
  8103. url = (sources[source] !== undefined)
  8104. ? sources[source].url.replace('{id}', id)
  8105. : false
  8106. ;
  8107. if(url) {
  8108. $module.data(metadata.url, url);
  8109. }
  8110. return url;
  8111. }
  8112. },
  8113. set: {
  8114. active: function() {
  8115. $module.addClass(className.active);
  8116. }
  8117. },
  8118. remove: {
  8119. active: function() {
  8120. $module.removeClass(className.active);
  8121. },
  8122. embed: function() {
  8123. $embed.empty();
  8124. }
  8125. },
  8126. encode: {
  8127. parameters: function(parameters) {
  8128. var
  8129. urlString = [],
  8130. index
  8131. ;
  8132. for (index in parameters) {
  8133. urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
  8134. }
  8135. return urlString.join('&amp;');
  8136. }
  8137. },
  8138. generate: {
  8139. embed: function(url) {
  8140. module.debug('Generating embed html');
  8141. var
  8142. source = module.get.source(),
  8143. html,
  8144. parameters
  8145. ;
  8146. url = module.get.url(url);
  8147. if(url) {
  8148. parameters = module.generate.parameters(source);
  8149. html = templates.iframe(url, parameters);
  8150. }
  8151. else {
  8152. module.error(error.noURL, $module);
  8153. }
  8154. return html;
  8155. },
  8156. parameters: function(source, extraParameters) {
  8157. var
  8158. parameters = (sources[source] && sources[source].parameters !== undefined)
  8159. ? sources[source].parameters(settings)
  8160. : {}
  8161. ;
  8162. extraParameters = extraParameters || settings.parameters;
  8163. if(extraParameters) {
  8164. parameters = $.extend({}, parameters, extraParameters);
  8165. }
  8166. parameters = settings.onEmbed(parameters);
  8167. return module.encode.parameters(parameters);
  8168. }
  8169. },
  8170. has: {
  8171. embed: function() {
  8172. return ($embed.length > 0);
  8173. },
  8174. placeholder: function() {
  8175. return settings.placeholder || $module.data(metadata.placeholder);
  8176. }
  8177. },
  8178. should: {
  8179. autoplay: function() {
  8180. return (settings.autoplay === 'auto')
  8181. ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
  8182. : settings.autoplay
  8183. ;
  8184. }
  8185. },
  8186. is: {
  8187. video: function() {
  8188. return module.get.type() == 'video';
  8189. }
  8190. },
  8191. setting: function(name, value) {
  8192. module.debug('Changing setting', name, value);
  8193. if( $.isPlainObject(name) ) {
  8194. $.extend(true, settings, name);
  8195. }
  8196. else if(value !== undefined) {
  8197. if($.isPlainObject(settings[name])) {
  8198. $.extend(true, settings[name], value);
  8199. }
  8200. else {
  8201. settings[name] = value;
  8202. }
  8203. }
  8204. else {
  8205. return settings[name];
  8206. }
  8207. },
  8208. internal: function(name, value) {
  8209. if( $.isPlainObject(name) ) {
  8210. $.extend(true, module, name);
  8211. }
  8212. else if(value !== undefined) {
  8213. module[name] = value;
  8214. }
  8215. else {
  8216. return module[name];
  8217. }
  8218. },
  8219. debug: function() {
  8220. if(!settings.silent && settings.debug) {
  8221. if(settings.performance) {
  8222. module.performance.log(arguments);
  8223. }
  8224. else {
  8225. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8226. module.debug.apply(console, arguments);
  8227. }
  8228. }
  8229. },
  8230. verbose: function() {
  8231. if(!settings.silent && settings.verbose && settings.debug) {
  8232. if(settings.performance) {
  8233. module.performance.log(arguments);
  8234. }
  8235. else {
  8236. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8237. module.verbose.apply(console, arguments);
  8238. }
  8239. }
  8240. },
  8241. error: function() {
  8242. if(!settings.silent) {
  8243. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  8244. module.error.apply(console, arguments);
  8245. }
  8246. },
  8247. performance: {
  8248. log: function(message) {
  8249. var
  8250. currentTime,
  8251. executionTime,
  8252. previousTime
  8253. ;
  8254. if(settings.performance) {
  8255. currentTime = new Date().getTime();
  8256. previousTime = time || currentTime;
  8257. executionTime = currentTime - previousTime;
  8258. time = currentTime;
  8259. performance.push({
  8260. 'Name' : message[0],
  8261. 'Arguments' : [].slice.call(message, 1) || '',
  8262. 'Element' : element,
  8263. 'Execution Time' : executionTime
  8264. });
  8265. }
  8266. clearTimeout(module.performance.timer);
  8267. module.performance.timer = setTimeout(module.performance.display, 500);
  8268. },
  8269. display: function() {
  8270. var
  8271. title = settings.name + ':',
  8272. totalTime = 0
  8273. ;
  8274. time = false;
  8275. clearTimeout(module.performance.timer);
  8276. $.each(performance, function(index, data) {
  8277. totalTime += data['Execution Time'];
  8278. });
  8279. title += ' ' + totalTime + 'ms';
  8280. if(moduleSelector) {
  8281. title += ' \'' + moduleSelector + '\'';
  8282. }
  8283. if($allModules.length > 1) {
  8284. title += ' ' + '(' + $allModules.length + ')';
  8285. }
  8286. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  8287. console.groupCollapsed(title);
  8288. if(console.table) {
  8289. console.table(performance);
  8290. }
  8291. else {
  8292. $.each(performance, function(index, data) {
  8293. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  8294. });
  8295. }
  8296. console.groupEnd();
  8297. }
  8298. performance = [];
  8299. }
  8300. },
  8301. invoke: function(query, passedArguments, context) {
  8302. var
  8303. object = instance,
  8304. maxDepth,
  8305. found,
  8306. response
  8307. ;
  8308. passedArguments = passedArguments || queryArguments;
  8309. context = element || context;
  8310. if(typeof query == 'string' && object !== undefined) {
  8311. query = query.split(/[\. ]/);
  8312. maxDepth = query.length - 1;
  8313. $.each(query, function(depth, value) {
  8314. var camelCaseValue = (depth != maxDepth)
  8315. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  8316. : query
  8317. ;
  8318. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  8319. object = object[camelCaseValue];
  8320. }
  8321. else if( object[camelCaseValue] !== undefined ) {
  8322. found = object[camelCaseValue];
  8323. return false;
  8324. }
  8325. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  8326. object = object[value];
  8327. }
  8328. else if( object[value] !== undefined ) {
  8329. found = object[value];
  8330. return false;
  8331. }
  8332. else {
  8333. module.error(error.method, query);
  8334. return false;
  8335. }
  8336. });
  8337. }
  8338. if ( $.isFunction( found ) ) {
  8339. response = found.apply(context, passedArguments);
  8340. }
  8341. else if(found !== undefined) {
  8342. response = found;
  8343. }
  8344. if($.isArray(returnedValue)) {
  8345. returnedValue.push(response);
  8346. }
  8347. else if(returnedValue !== undefined) {
  8348. returnedValue = [returnedValue, response];
  8349. }
  8350. else if(response !== undefined) {
  8351. returnedValue = response;
  8352. }
  8353. return found;
  8354. }
  8355. };
  8356. if(methodInvoked) {
  8357. if(instance === undefined) {
  8358. module.initialize();
  8359. }
  8360. module.invoke(query);
  8361. }
  8362. else {
  8363. if(instance !== undefined) {
  8364. instance.invoke('destroy');
  8365. }
  8366. module.initialize();
  8367. }
  8368. })
  8369. ;
  8370. return (returnedValue !== undefined)
  8371. ? returnedValue
  8372. : this
  8373. ;
  8374. };
  8375. $.fn.embed.settings = {
  8376. name : 'Embed',
  8377. namespace : 'embed',
  8378. silent : false,
  8379. debug : false,
  8380. verbose : false,
  8381. performance : true,
  8382. icon : false,
  8383. source : false,
  8384. url : false,
  8385. id : false,
  8386. // standard video settings
  8387. autoplay : 'auto',
  8388. color : '#444444',
  8389. hd : true,
  8390. brandedUI : false,
  8391. // additional parameters to include with the embed
  8392. parameters: false,
  8393. onDisplay : function() {},
  8394. onPlaceholderDisplay : function() {},
  8395. onReset : function() {},
  8396. onCreate : function(url) {},
  8397. onEmbed : function(parameters) {
  8398. return parameters;
  8399. },
  8400. metadata : {
  8401. id : 'id',
  8402. icon : 'icon',
  8403. placeholder : 'placeholder',
  8404. source : 'source',
  8405. url : 'url'
  8406. },
  8407. error : {
  8408. noURL : 'No URL specified',
  8409. method : 'The method you called is not defined'
  8410. },
  8411. className : {
  8412. active : 'active',
  8413. embed : 'embed'
  8414. },
  8415. selector : {
  8416. embed : '.embed',
  8417. placeholder : '.placeholder',
  8418. icon : '.icon'
  8419. },
  8420. sources: {
  8421. youtube: {
  8422. name : 'youtube',
  8423. type : 'video',
  8424. icon : 'video play',
  8425. domain : 'youtube.com',
  8426. url : '//www.youtube.com/embed/{id}',
  8427. parameters: function(settings) {
  8428. return {
  8429. autohide : !settings.brandedUI,
  8430. autoplay : settings.autoplay,
  8431. color : settings.color || undefined,
  8432. hq : settings.hd,
  8433. jsapi : settings.api,
  8434. modestbranding : !settings.brandedUI
  8435. };
  8436. }
  8437. },
  8438. vimeo: {
  8439. name : 'vimeo',
  8440. type : 'video',
  8441. icon : 'video play',
  8442. domain : 'vimeo.com',
  8443. url : '//player.vimeo.com/video/{id}',
  8444. parameters: function(settings) {
  8445. return {
  8446. api : settings.api,
  8447. autoplay : settings.autoplay,
  8448. byline : settings.brandedUI,
  8449. color : settings.color || undefined,
  8450. portrait : settings.brandedUI,
  8451. title : settings.brandedUI
  8452. };
  8453. }
  8454. }
  8455. },
  8456. templates: {
  8457. iframe : function(url, parameters) {
  8458. var src = url;
  8459. if (parameters) {
  8460. src += '?' + parameters;
  8461. }
  8462. return ''
  8463. + '<iframe src="' + src + '"'
  8464. + ' width="100%" height="100%"'
  8465. + ' frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  8466. ;
  8467. },
  8468. placeholder : function(image, icon) {
  8469. var
  8470. html = ''
  8471. ;
  8472. if(icon) {
  8473. html += '<i class="' + icon + ' icon"></i>';
  8474. }
  8475. if(image) {
  8476. html += '<img class="placeholder" src="' + image + '">';
  8477. }
  8478. return html;
  8479. }
  8480. },
  8481. // NOT YET IMPLEMENTED
  8482. api : false,
  8483. onPause : function() {},
  8484. onPlay : function() {},
  8485. onStop : function() {}
  8486. };
  8487. })( jQuery, window, document );
  8488. /*!
  8489. * # Semantic UI 2.3.3 - Modal
  8490. * http://github.com/semantic-org/semantic-ui/
  8491. *
  8492. *
  8493. * Released under the MIT license
  8494. * http://opensource.org/licenses/MIT
  8495. *
  8496. */
  8497. ;(function ($, window, document, undefined) {
  8498. 'use strict';
  8499. window = (typeof window != 'undefined' && window.Math == Math)
  8500. ? window
  8501. : (typeof self != 'undefined' && self.Math == Math)
  8502. ? self
  8503. : Function('return this')()
  8504. ;
  8505. $.fn.modal = function(parameters) {
  8506. var
  8507. $allModules = $(this),
  8508. $window = $(window),
  8509. $document = $(document),
  8510. $body = $('body'),
  8511. moduleSelector = $allModules.selector || '',
  8512. time = new Date().getTime(),
  8513. performance = [],
  8514. query = arguments[0],
  8515. methodInvoked = (typeof query == 'string'),
  8516. queryArguments = [].slice.call(arguments, 1),
  8517. requestAnimationFrame = window.requestAnimationFrame
  8518. || window.mozRequestAnimationFrame
  8519. || window.webkitRequestAnimationFrame
  8520. || window.msRequestAnimationFrame
  8521. || function(callback) { setTimeout(callback, 0); },
  8522. returnedValue
  8523. ;
  8524. $allModules
  8525. .each(function() {
  8526. var
  8527. settings = ( $.isPlainObject(parameters) )
  8528. ? $.extend(true, {}, $.fn.modal.settings, parameters)
  8529. : $.extend({}, $.fn.modal.settings),
  8530. selector = settings.selector,
  8531. className = settings.className,
  8532. namespace = settings.namespace,
  8533. error = settings.error,
  8534. eventNamespace = '.' + namespace,
  8535. moduleNamespace = 'module-' + namespace,
  8536. $module = $(this),
  8537. $context = $(settings.context),
  8538. $close = $module.find(selector.close),
  8539. $allModals,
  8540. $otherModals,
  8541. $focusedElement,
  8542. $dimmable,
  8543. $dimmer,
  8544. element = this,
  8545. instance = $module.data(moduleNamespace),
  8546. ignoreRepeatedEvents = false,
  8547. elementEventNamespace,
  8548. id,
  8549. observer,
  8550. module
  8551. ;
  8552. module = {
  8553. initialize: function() {
  8554. module.verbose('Initializing dimmer', $context);
  8555. module.create.id();
  8556. module.create.dimmer();
  8557. module.refreshModals();
  8558. module.bind.events();
  8559. if(settings.observeChanges) {
  8560. module.observeChanges();
  8561. }
  8562. module.instantiate();
  8563. },
  8564. instantiate: function() {
  8565. module.verbose('Storing instance of modal');
  8566. instance = module;
  8567. $module
  8568. .data(moduleNamespace, instance)
  8569. ;
  8570. },
  8571. create: {
  8572. dimmer: function() {
  8573. var
  8574. defaultSettings = {
  8575. debug : settings.debug,
  8576. variation : settings.centered
  8577. ? false
  8578. : 'top aligned'
  8579. ,
  8580. dimmerName : 'modals'
  8581. },
  8582. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  8583. ;
  8584. if($.fn.dimmer === undefined) {
  8585. module.error(error.dimmer);
  8586. return;
  8587. }
  8588. module.debug('Creating dimmer');
  8589. $dimmable = $context.dimmer(dimmerSettings);
  8590. if(settings.detachable) {
  8591. module.verbose('Modal is detachable, moving content into dimmer');
  8592. $dimmable.dimmer('add content', $module);
  8593. }
  8594. else {
  8595. module.set.undetached();
  8596. }
  8597. $dimmer = $dimmable.dimmer('get dimmer');
  8598. },
  8599. id: function() {
  8600. id = (Math.random().toString(16) + '000000000').substr(2,8);
  8601. elementEventNamespace = '.' + id;
  8602. module.verbose('Creating unique id for element', id);
  8603. }
  8604. },
  8605. destroy: function() {
  8606. module.verbose('Destroying previous modal');
  8607. $module
  8608. .removeData(moduleNamespace)
  8609. .off(eventNamespace)
  8610. ;
  8611. $window.off(elementEventNamespace);
  8612. $dimmer.off(elementEventNamespace);
  8613. $close.off(eventNamespace);
  8614. $context.dimmer('destroy');
  8615. },
  8616. observeChanges: function() {
  8617. if('MutationObserver' in window) {
  8618. observer = new MutationObserver(function(mutations) {
  8619. module.debug('DOM tree modified, refreshing');
  8620. module.refresh();
  8621. });
  8622. observer.observe(element, {
  8623. childList : true,
  8624. subtree : true
  8625. });
  8626. module.debug('Setting up mutation observer', observer);
  8627. }
  8628. },
  8629. refresh: function() {
  8630. module.remove.scrolling();
  8631. module.cacheSizes();
  8632. module.set.screenHeight();
  8633. module.set.type();
  8634. },
  8635. refreshModals: function() {
  8636. $otherModals = $module.siblings(selector.modal);
  8637. $allModals = $otherModals.add($module);
  8638. },
  8639. attachEvents: function(selector, event) {
  8640. var
  8641. $toggle = $(selector)
  8642. ;
  8643. event = $.isFunction(module[event])
  8644. ? module[event]
  8645. : module.toggle
  8646. ;
  8647. if($toggle.length > 0) {
  8648. module.debug('Attaching modal events to element', selector, event);
  8649. $toggle
  8650. .off(eventNamespace)
  8651. .on('click' + eventNamespace, event)
  8652. ;
  8653. }
  8654. else {
  8655. module.error(error.notFound, selector);
  8656. }
  8657. },
  8658. bind: {
  8659. events: function() {
  8660. module.verbose('Attaching events');
  8661. $module
  8662. .on('click' + eventNamespace, selector.close, module.event.close)
  8663. .on('click' + eventNamespace, selector.approve, module.event.approve)
  8664. .on('click' + eventNamespace, selector.deny, module.event.deny)
  8665. ;
  8666. $window
  8667. .on('resize' + elementEventNamespace, module.event.resize)
  8668. ;
  8669. }
  8670. },
  8671. get: {
  8672. id: function() {
  8673. return (Math.random().toString(16) + '000000000').substr(2,8);
  8674. }
  8675. },
  8676. event: {
  8677. approve: function() {
  8678. if(ignoreRepeatedEvents || settings.onApprove.call(element, $(this)) === false) {
  8679. module.verbose('Approve callback returned false cancelling hide');
  8680. return;
  8681. }
  8682. ignoreRepeatedEvents = true;
  8683. module.hide(function() {
  8684. ignoreRepeatedEvents = false;
  8685. });
  8686. },
  8687. deny: function() {
  8688. if(ignoreRepeatedEvents || settings.onDeny.call(element, $(this)) === false) {
  8689. module.verbose('Deny callback returned false cancelling hide');
  8690. return;
  8691. }
  8692. ignoreRepeatedEvents = true;
  8693. module.hide(function() {
  8694. ignoreRepeatedEvents = false;
  8695. });
  8696. },
  8697. close: function() {
  8698. module.hide();
  8699. },
  8700. click: function(event) {
  8701. if(!settings.closable) {
  8702. module.verbose('Dimmer clicked but closable setting is disabled');
  8703. return;
  8704. }
  8705. var
  8706. $target = $(event.target),
  8707. isInModal = ($target.closest(selector.modal).length > 0),
  8708. isInDOM = $.contains(document.documentElement, event.target)
  8709. ;
  8710. if(!isInModal && isInDOM && module.is.active()) {
  8711. module.debug('Dimmer clicked, hiding all modals');
  8712. module.remove.clickaway();
  8713. if(settings.allowMultiple) {
  8714. module.hide();
  8715. }
  8716. else {
  8717. module.hideAll();
  8718. }
  8719. }
  8720. },
  8721. debounce: function(method, delay) {
  8722. clearTimeout(module.timer);
  8723. module.timer = setTimeout(method, delay);
  8724. },
  8725. keyboard: function(event) {
  8726. var
  8727. keyCode = event.which,
  8728. escapeKey = 27
  8729. ;
  8730. if(keyCode == escapeKey) {
  8731. if(settings.closable) {
  8732. module.debug('Escape key pressed hiding modal');
  8733. module.hide();
  8734. }
  8735. else {
  8736. module.debug('Escape key pressed, but closable is set to false');
  8737. }
  8738. event.preventDefault();
  8739. }
  8740. },
  8741. resize: function() {
  8742. if( $dimmable.dimmer('is active') && ( module.is.animating() || module.is.active() ) ) {
  8743. requestAnimationFrame(module.refresh);
  8744. }
  8745. }
  8746. },
  8747. toggle: function() {
  8748. if( module.is.active() || module.is.animating() ) {
  8749. module.hide();
  8750. }
  8751. else {
  8752. module.show();
  8753. }
  8754. },
  8755. show: function(callback) {
  8756. callback = $.isFunction(callback)
  8757. ? callback
  8758. : function(){}
  8759. ;
  8760. module.refreshModals();
  8761. module.set.dimmerSettings();
  8762. module.showModal(callback);
  8763. },
  8764. hide: function(callback) {
  8765. callback = $.isFunction(callback)
  8766. ? callback
  8767. : function(){}
  8768. ;
  8769. module.refreshModals();
  8770. module.hideModal(callback);
  8771. },
  8772. showModal: function(callback) {
  8773. callback = $.isFunction(callback)
  8774. ? callback
  8775. : function(){}
  8776. ;
  8777. if( module.is.animating() || !module.is.active() ) {
  8778. module.showDimmer();
  8779. module.cacheSizes();
  8780. module.set.screenHeight();
  8781. module.set.type();
  8782. module.set.clickaway();
  8783. if( !settings.allowMultiple && module.others.active() ) {
  8784. module.hideOthers(module.showModal);
  8785. }
  8786. else {
  8787. if(settings.allowMultiple && settings.detachable) {
  8788. $module.detach().appendTo($dimmer);
  8789. }
  8790. settings.onShow.call(element);
  8791. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8792. module.debug('Showing modal with css animations');
  8793. $module
  8794. .transition({
  8795. debug : settings.debug,
  8796. animation : settings.transition + ' in',
  8797. queue : settings.queue,
  8798. duration : settings.duration,
  8799. useFailSafe : true,
  8800. onComplete : function() {
  8801. settings.onVisible.apply(element);
  8802. if(settings.keyboardShortcuts) {
  8803. module.add.keyboardShortcuts();
  8804. }
  8805. module.save.focus();
  8806. module.set.active();
  8807. if(settings.autofocus) {
  8808. module.set.autofocus();
  8809. }
  8810. callback();
  8811. }
  8812. })
  8813. ;
  8814. }
  8815. else {
  8816. module.error(error.noTransition);
  8817. }
  8818. }
  8819. }
  8820. else {
  8821. module.debug('Modal is already visible');
  8822. }
  8823. },
  8824. hideModal: function(callback, keepDimmed) {
  8825. callback = $.isFunction(callback)
  8826. ? callback
  8827. : function(){}
  8828. ;
  8829. module.debug('Hiding modal');
  8830. if(settings.onHide.call(element, $(this)) === false) {
  8831. module.verbose('Hide callback returned false cancelling hide');
  8832. return;
  8833. }
  8834. if( module.is.animating() || module.is.active() ) {
  8835. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8836. module.remove.active();
  8837. $module
  8838. .transition({
  8839. debug : settings.debug,
  8840. animation : settings.transition + ' out',
  8841. queue : settings.queue,
  8842. duration : settings.duration,
  8843. useFailSafe : true,
  8844. onStart : function() {
  8845. if(!module.others.active() && !keepDimmed) {
  8846. module.hideDimmer();
  8847. }
  8848. if(settings.keyboardShortcuts) {
  8849. module.remove.keyboardShortcuts();
  8850. }
  8851. },
  8852. onComplete : function() {
  8853. settings.onHidden.call(element);
  8854. module.restore.focus();
  8855. callback();
  8856. }
  8857. })
  8858. ;
  8859. }
  8860. else {
  8861. module.error(error.noTransition);
  8862. }
  8863. }
  8864. },
  8865. showDimmer: function() {
  8866. if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
  8867. module.debug('Showing dimmer');
  8868. $dimmable.dimmer('show');
  8869. }
  8870. else {
  8871. module.debug('Dimmer already visible');
  8872. }
  8873. },
  8874. hideDimmer: function() {
  8875. if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
  8876. $dimmable.dimmer('hide', function() {
  8877. module.remove.clickaway();
  8878. module.remove.screenHeight();
  8879. });
  8880. }
  8881. else {
  8882. module.debug('Dimmer is not visible cannot hide');
  8883. return;
  8884. }
  8885. },
  8886. hideAll: function(callback) {
  8887. var
  8888. $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
  8889. ;
  8890. callback = $.isFunction(callback)
  8891. ? callback
  8892. : function(){}
  8893. ;
  8894. if( $visibleModals.length > 0 ) {
  8895. module.debug('Hiding all visible modals');
  8896. module.hideDimmer();
  8897. $visibleModals
  8898. .modal('hide modal', callback)
  8899. ;
  8900. }
  8901. },
  8902. hideOthers: function(callback) {
  8903. var
  8904. $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
  8905. ;
  8906. callback = $.isFunction(callback)
  8907. ? callback
  8908. : function(){}
  8909. ;
  8910. if( $visibleModals.length > 0 ) {
  8911. module.debug('Hiding other modals', $otherModals);
  8912. $visibleModals
  8913. .modal('hide modal', callback, true)
  8914. ;
  8915. }
  8916. },
  8917. others: {
  8918. active: function() {
  8919. return ($otherModals.filter('.' + className.active).length > 0);
  8920. },
  8921. animating: function() {
  8922. return ($otherModals.filter('.' + className.animating).length > 0);
  8923. }
  8924. },
  8925. add: {
  8926. keyboardShortcuts: function() {
  8927. module.verbose('Adding keyboard shortcuts');
  8928. $document
  8929. .on('keyup' + eventNamespace, module.event.keyboard)
  8930. ;
  8931. }
  8932. },
  8933. save: {
  8934. focus: function() {
  8935. var
  8936. $activeElement = $(document.activeElement),
  8937. inCurrentModal = $activeElement.closest($module).length > 0
  8938. ;
  8939. if(!inCurrentModal) {
  8940. $focusedElement = $(document.activeElement).blur();
  8941. }
  8942. }
  8943. },
  8944. restore: {
  8945. focus: function() {
  8946. if($focusedElement && $focusedElement.length > 0) {
  8947. $focusedElement.focus();
  8948. }
  8949. }
  8950. },
  8951. remove: {
  8952. active: function() {
  8953. $module.removeClass(className.active);
  8954. },
  8955. clickaway: function() {
  8956. $dimmer
  8957. .off('click' + elementEventNamespace)
  8958. ;
  8959. },
  8960. bodyStyle: function() {
  8961. if($body.attr('style') === '') {
  8962. module.verbose('Removing style attribute');
  8963. $body.removeAttr('style');
  8964. }
  8965. },
  8966. screenHeight: function() {
  8967. module.debug('Removing page height');
  8968. $body
  8969. .css('height', '')
  8970. ;
  8971. },
  8972. keyboardShortcuts: function() {
  8973. module.verbose('Removing keyboard shortcuts');
  8974. $document
  8975. .off('keyup' + eventNamespace)
  8976. ;
  8977. },
  8978. scrolling: function() {
  8979. $dimmable.removeClass(className.scrolling);
  8980. $module.removeClass(className.scrolling);
  8981. }
  8982. },
  8983. cacheSizes: function() {
  8984. $module.addClass(className.loading);
  8985. var
  8986. scrollHeight = $module.prop('scrollHeight'),
  8987. modalHeight = $module.outerHeight()
  8988. ;
  8989. if(module.cache === undefined || modalHeight !== 0) {
  8990. module.cache = {
  8991. pageHeight : $(document).outerHeight(),
  8992. height : modalHeight + settings.offset,
  8993. scrollHeight : scrollHeight + settings.offset,
  8994. contextHeight : (settings.context == 'body')
  8995. ? $(window).height()
  8996. : $dimmable.height(),
  8997. };
  8998. module.cache.topOffset = -(module.cache.height / 2);
  8999. }
  9000. $module.removeClass(className.loading);
  9001. module.debug('Caching modal and container sizes', module.cache);
  9002. },
  9003. can: {
  9004. fit: function() {
  9005. var
  9006. contextHeight = module.cache.contextHeight,
  9007. verticalCenter = module.cache.contextHeight / 2,
  9008. topOffset = module.cache.topOffset,
  9009. scrollHeight = module.cache.scrollHeight,
  9010. height = module.cache.height,
  9011. paddingHeight = settings.padding,
  9012. startPosition = (verticalCenter + topOffset)
  9013. ;
  9014. return (scrollHeight > height)
  9015. ? (startPosition + scrollHeight + paddingHeight < contextHeight)
  9016. : (height + (paddingHeight * 2) < contextHeight)
  9017. ;
  9018. }
  9019. },
  9020. is: {
  9021. active: function() {
  9022. return $module.hasClass(className.active);
  9023. },
  9024. animating: function() {
  9025. return $module.transition('is supported')
  9026. ? $module.transition('is animating')
  9027. : $module.is(':visible')
  9028. ;
  9029. },
  9030. scrolling: function() {
  9031. return $dimmable.hasClass(className.scrolling);
  9032. },
  9033. modernBrowser: function() {
  9034. // appName for IE11 reports 'Netscape' can no longer use
  9035. return !(window.ActiveXObject || "ActiveXObject" in window);
  9036. }
  9037. },
  9038. set: {
  9039. autofocus: function() {
  9040. var
  9041. $inputs = $module.find('[tabindex], :input').filter(':visible'),
  9042. $autofocus = $inputs.filter('[autofocus]'),
  9043. $input = ($autofocus.length > 0)
  9044. ? $autofocus.first()
  9045. : $inputs.first()
  9046. ;
  9047. if($input.length > 0) {
  9048. $input.focus();
  9049. }
  9050. },
  9051. clickaway: function() {
  9052. $dimmer
  9053. .on('click' + elementEventNamespace, module.event.click)
  9054. ;
  9055. },
  9056. dimmerSettings: function() {
  9057. if($.fn.dimmer === undefined) {
  9058. module.error(error.dimmer);
  9059. return;
  9060. }
  9061. var
  9062. defaultSettings = {
  9063. debug : settings.debug,
  9064. dimmerName : 'modals',
  9065. closable : 'auto',
  9066. variation : settings.centered
  9067. ? false
  9068. : 'top aligned'
  9069. ,
  9070. duration : {
  9071. show : settings.duration,
  9072. hide : settings.duration
  9073. }
  9074. },
  9075. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  9076. ;
  9077. if(settings.inverted) {
  9078. dimmerSettings.variation = (dimmerSettings.variation !== undefined)
  9079. ? dimmerSettings.variation + ' inverted'
  9080. : 'inverted'
  9081. ;
  9082. $dimmer.addClass(className.inverted);
  9083. }
  9084. else {
  9085. $dimmer.removeClass(className.inverted);
  9086. }
  9087. if(settings.blurring) {
  9088. $dimmable.addClass(className.blurring);
  9089. }
  9090. else {
  9091. $dimmable.removeClass(className.blurring);
  9092. }
  9093. $context.dimmer('setting', dimmerSettings);
  9094. },
  9095. screenHeight: function() {
  9096. if( module.can.fit() ) {
  9097. $body.css('height', '');
  9098. }
  9099. else {
  9100. module.debug('Modal is taller than page content, resizing page height');
  9101. $body
  9102. .css('height', module.cache.height + (settings.padding * 2) )
  9103. ;
  9104. }
  9105. },
  9106. active: function() {
  9107. $module.addClass(className.active);
  9108. },
  9109. scrolling: function() {
  9110. $dimmable.addClass(className.scrolling);
  9111. $module.addClass(className.scrolling);
  9112. },
  9113. type: function() {
  9114. if(module.can.fit()) {
  9115. module.verbose('Modal fits on screen');
  9116. if(!module.others.active() && !module.others.animating()) {
  9117. module.remove.scrolling();
  9118. }
  9119. }
  9120. else {
  9121. module.verbose('Modal cannot fit on screen setting to scrolling');
  9122. module.set.scrolling();
  9123. }
  9124. },
  9125. undetached: function() {
  9126. $dimmable.addClass(className.undetached);
  9127. }
  9128. },
  9129. setting: function(name, value) {
  9130. module.debug('Changing setting', name, value);
  9131. if( $.isPlainObject(name) ) {
  9132. $.extend(true, settings, name);
  9133. }
  9134. else if(value !== undefined) {
  9135. if($.isPlainObject(settings[name])) {
  9136. $.extend(true, settings[name], value);
  9137. }
  9138. else {
  9139. settings[name] = value;
  9140. }
  9141. }
  9142. else {
  9143. return settings[name];
  9144. }
  9145. },
  9146. internal: function(name, value) {
  9147. if( $.isPlainObject(name) ) {
  9148. $.extend(true, module, name);
  9149. }
  9150. else if(value !== undefined) {
  9151. module[name] = value;
  9152. }
  9153. else {
  9154. return module[name];
  9155. }
  9156. },
  9157. debug: function() {
  9158. if(!settings.silent && settings.debug) {
  9159. if(settings.performance) {
  9160. module.performance.log(arguments);
  9161. }
  9162. else {
  9163. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9164. module.debug.apply(console, arguments);
  9165. }
  9166. }
  9167. },
  9168. verbose: function() {
  9169. if(!settings.silent && settings.verbose && settings.debug) {
  9170. if(settings.performance) {
  9171. module.performance.log(arguments);
  9172. }
  9173. else {
  9174. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9175. module.verbose.apply(console, arguments);
  9176. }
  9177. }
  9178. },
  9179. error: function() {
  9180. if(!settings.silent) {
  9181. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9182. module.error.apply(console, arguments);
  9183. }
  9184. },
  9185. performance: {
  9186. log: function(message) {
  9187. var
  9188. currentTime,
  9189. executionTime,
  9190. previousTime
  9191. ;
  9192. if(settings.performance) {
  9193. currentTime = new Date().getTime();
  9194. previousTime = time || currentTime;
  9195. executionTime = currentTime - previousTime;
  9196. time = currentTime;
  9197. performance.push({
  9198. 'Name' : message[0],
  9199. 'Arguments' : [].slice.call(message, 1) || '',
  9200. 'Element' : element,
  9201. 'Execution Time' : executionTime
  9202. });
  9203. }
  9204. clearTimeout(module.performance.timer);
  9205. module.performance.timer = setTimeout(module.performance.display, 500);
  9206. },
  9207. display: function() {
  9208. var
  9209. title = settings.name + ':',
  9210. totalTime = 0
  9211. ;
  9212. time = false;
  9213. clearTimeout(module.performance.timer);
  9214. $.each(performance, function(index, data) {
  9215. totalTime += data['Execution Time'];
  9216. });
  9217. title += ' ' + totalTime + 'ms';
  9218. if(moduleSelector) {
  9219. title += ' \'' + moduleSelector + '\'';
  9220. }
  9221. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9222. console.groupCollapsed(title);
  9223. if(console.table) {
  9224. console.table(performance);
  9225. }
  9226. else {
  9227. $.each(performance, function(index, data) {
  9228. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9229. });
  9230. }
  9231. console.groupEnd();
  9232. }
  9233. performance = [];
  9234. }
  9235. },
  9236. invoke: function(query, passedArguments, context) {
  9237. var
  9238. object = instance,
  9239. maxDepth,
  9240. found,
  9241. response
  9242. ;
  9243. passedArguments = passedArguments || queryArguments;
  9244. context = element || context;
  9245. if(typeof query == 'string' && object !== undefined) {
  9246. query = query.split(/[\. ]/);
  9247. maxDepth = query.length - 1;
  9248. $.each(query, function(depth, value) {
  9249. var camelCaseValue = (depth != maxDepth)
  9250. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9251. : query
  9252. ;
  9253. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9254. object = object[camelCaseValue];
  9255. }
  9256. else if( object[camelCaseValue] !== undefined ) {
  9257. found = object[camelCaseValue];
  9258. return false;
  9259. }
  9260. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9261. object = object[value];
  9262. }
  9263. else if( object[value] !== undefined ) {
  9264. found = object[value];
  9265. return false;
  9266. }
  9267. else {
  9268. return false;
  9269. }
  9270. });
  9271. }
  9272. if ( $.isFunction( found ) ) {
  9273. response = found.apply(context, passedArguments);
  9274. }
  9275. else if(found !== undefined) {
  9276. response = found;
  9277. }
  9278. if($.isArray(returnedValue)) {
  9279. returnedValue.push(response);
  9280. }
  9281. else if(returnedValue !== undefined) {
  9282. returnedValue = [returnedValue, response];
  9283. }
  9284. else if(response !== undefined) {
  9285. returnedValue = response;
  9286. }
  9287. return found;
  9288. }
  9289. };
  9290. if(methodInvoked) {
  9291. if(instance === undefined) {
  9292. module.initialize();
  9293. }
  9294. module.invoke(query);
  9295. }
  9296. else {
  9297. if(instance !== undefined) {
  9298. instance.invoke('destroy');
  9299. }
  9300. module.initialize();
  9301. }
  9302. })
  9303. ;
  9304. return (returnedValue !== undefined)
  9305. ? returnedValue
  9306. : this
  9307. ;
  9308. };
  9309. $.fn.modal.settings = {
  9310. name : 'Modal',
  9311. namespace : 'modal',
  9312. silent : false,
  9313. debug : false,
  9314. verbose : false,
  9315. performance : true,
  9316. observeChanges : false,
  9317. allowMultiple : false,
  9318. detachable : true,
  9319. closable : true,
  9320. autofocus : true,
  9321. inverted : false,
  9322. blurring : false,
  9323. centered : true,
  9324. dimmerSettings : {
  9325. closable : false,
  9326. useCSS : true
  9327. },
  9328. // whether to use keyboard shortcuts
  9329. keyboardShortcuts: true,
  9330. context : 'body',
  9331. queue : false,
  9332. duration : 500,
  9333. offset : 0,
  9334. transition : 'scale',
  9335. // padding with edge of page
  9336. padding : 50,
  9337. // called before show animation
  9338. onShow : function(){},
  9339. // called after show animation
  9340. onVisible : function(){},
  9341. // called before hide animation
  9342. onHide : function(){ return true; },
  9343. // called after hide animation
  9344. onHidden : function(){},
  9345. // called after approve selector match
  9346. onApprove : function(){ return true; },
  9347. // called after deny selector match
  9348. onDeny : function(){ return true; },
  9349. selector : {
  9350. close : '> .close',
  9351. approve : '.actions .positive, .actions .approve, .actions .ok',
  9352. deny : '.actions .negative, .actions .deny, .actions .cancel',
  9353. modal : '.ui.modal'
  9354. },
  9355. error : {
  9356. dimmer : 'UI Dimmer, a required component is not included in this page',
  9357. method : 'The method you called is not defined.',
  9358. notFound : 'The element you specified could not be found'
  9359. },
  9360. className : {
  9361. active : 'active',
  9362. animating : 'animating',
  9363. blurring : 'blurring',
  9364. inverted : 'inverted',
  9365. loading : 'loading',
  9366. scrolling : 'scrolling',
  9367. undetached : 'undetached'
  9368. }
  9369. };
  9370. })( jQuery, window, document );
  9371. /*!
  9372. * # Semantic UI 2.3.3 - Nag
  9373. * http://github.com/semantic-org/semantic-ui/
  9374. *
  9375. *
  9376. * Released under the MIT license
  9377. * http://opensource.org/licenses/MIT
  9378. *
  9379. */
  9380. ;(function ($, window, document, undefined) {
  9381. 'use strict';
  9382. window = (typeof window != 'undefined' && window.Math == Math)
  9383. ? window
  9384. : (typeof self != 'undefined' && self.Math == Math)
  9385. ? self
  9386. : Function('return this')()
  9387. ;
  9388. $.fn.nag = function(parameters) {
  9389. var
  9390. $allModules = $(this),
  9391. moduleSelector = $allModules.selector || '',
  9392. time = new Date().getTime(),
  9393. performance = [],
  9394. query = arguments[0],
  9395. methodInvoked = (typeof query == 'string'),
  9396. queryArguments = [].slice.call(arguments, 1),
  9397. returnedValue
  9398. ;
  9399. $allModules
  9400. .each(function() {
  9401. var
  9402. settings = ( $.isPlainObject(parameters) )
  9403. ? $.extend(true, {}, $.fn.nag.settings, parameters)
  9404. : $.extend({}, $.fn.nag.settings),
  9405. className = settings.className,
  9406. selector = settings.selector,
  9407. error = settings.error,
  9408. namespace = settings.namespace,
  9409. eventNamespace = '.' + namespace,
  9410. moduleNamespace = namespace + '-module',
  9411. $module = $(this),
  9412. $close = $module.find(selector.close),
  9413. $context = (settings.context)
  9414. ? $(settings.context)
  9415. : $('body'),
  9416. element = this,
  9417. instance = $module.data(moduleNamespace),
  9418. moduleOffset,
  9419. moduleHeight,
  9420. contextWidth,
  9421. contextHeight,
  9422. contextOffset,
  9423. yOffset,
  9424. yPosition,
  9425. timer,
  9426. module,
  9427. requestAnimationFrame = window.requestAnimationFrame
  9428. || window.mozRequestAnimationFrame
  9429. || window.webkitRequestAnimationFrame
  9430. || window.msRequestAnimationFrame
  9431. || function(callback) { setTimeout(callback, 0); }
  9432. ;
  9433. module = {
  9434. initialize: function() {
  9435. module.verbose('Initializing element');
  9436. $module
  9437. .on('click' + eventNamespace, selector.close, module.dismiss)
  9438. .data(moduleNamespace, module)
  9439. ;
  9440. if(settings.detachable && $module.parent()[0] !== $context[0]) {
  9441. $module
  9442. .detach()
  9443. .prependTo($context)
  9444. ;
  9445. }
  9446. if(settings.displayTime > 0) {
  9447. setTimeout(module.hide, settings.displayTime);
  9448. }
  9449. module.show();
  9450. },
  9451. destroy: function() {
  9452. module.verbose('Destroying instance');
  9453. $module
  9454. .removeData(moduleNamespace)
  9455. .off(eventNamespace)
  9456. ;
  9457. },
  9458. show: function() {
  9459. if( module.should.show() && !$module.is(':visible') ) {
  9460. module.debug('Showing nag', settings.animation.show);
  9461. if(settings.animation.show == 'fade') {
  9462. $module
  9463. .fadeIn(settings.duration, settings.easing)
  9464. ;
  9465. }
  9466. else {
  9467. $module
  9468. .slideDown(settings.duration, settings.easing)
  9469. ;
  9470. }
  9471. }
  9472. },
  9473. hide: function() {
  9474. module.debug('Showing nag', settings.animation.hide);
  9475. if(settings.animation.show == 'fade') {
  9476. $module
  9477. .fadeIn(settings.duration, settings.easing)
  9478. ;
  9479. }
  9480. else {
  9481. $module
  9482. .slideUp(settings.duration, settings.easing)
  9483. ;
  9484. }
  9485. },
  9486. onHide: function() {
  9487. module.debug('Removing nag', settings.animation.hide);
  9488. $module.remove();
  9489. if (settings.onHide) {
  9490. settings.onHide();
  9491. }
  9492. },
  9493. dismiss: function(event) {
  9494. if(settings.storageMethod) {
  9495. module.storage.set(settings.key, settings.value);
  9496. }
  9497. module.hide();
  9498. event.stopImmediatePropagation();
  9499. event.preventDefault();
  9500. },
  9501. should: {
  9502. show: function() {
  9503. if(settings.persist) {
  9504. module.debug('Persistent nag is set, can show nag');
  9505. return true;
  9506. }
  9507. if( module.storage.get(settings.key) != settings.value.toString() ) {
  9508. module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
  9509. return true;
  9510. }
  9511. module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
  9512. return false;
  9513. }
  9514. },
  9515. get: {
  9516. storageOptions: function() {
  9517. var
  9518. options = {}
  9519. ;
  9520. if(settings.expires) {
  9521. options.expires = settings.expires;
  9522. }
  9523. if(settings.domain) {
  9524. options.domain = settings.domain;
  9525. }
  9526. if(settings.path) {
  9527. options.path = settings.path;
  9528. }
  9529. return options;
  9530. }
  9531. },
  9532. clear: function() {
  9533. module.storage.remove(settings.key);
  9534. },
  9535. storage: {
  9536. set: function(key, value) {
  9537. var
  9538. options = module.get.storageOptions()
  9539. ;
  9540. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9541. window.localStorage.setItem(key, value);
  9542. module.debug('Value stored using local storage', key, value);
  9543. }
  9544. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9545. window.sessionStorage.setItem(key, value);
  9546. module.debug('Value stored using session storage', key, value);
  9547. }
  9548. else if($.cookie !== undefined) {
  9549. $.cookie(key, value, options);
  9550. module.debug('Value stored using cookie', key, value, options);
  9551. }
  9552. else {
  9553. module.error(error.noCookieStorage);
  9554. return;
  9555. }
  9556. },
  9557. get: function(key, value) {
  9558. var
  9559. storedValue
  9560. ;
  9561. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9562. storedValue = window.localStorage.getItem(key);
  9563. }
  9564. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9565. storedValue = window.sessionStorage.getItem(key);
  9566. }
  9567. // get by cookie
  9568. else if($.cookie !== undefined) {
  9569. storedValue = $.cookie(key);
  9570. }
  9571. else {
  9572. module.error(error.noCookieStorage);
  9573. }
  9574. if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
  9575. storedValue = undefined;
  9576. }
  9577. return storedValue;
  9578. },
  9579. remove: function(key) {
  9580. var
  9581. options = module.get.storageOptions()
  9582. ;
  9583. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9584. window.localStorage.removeItem(key);
  9585. }
  9586. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9587. window.sessionStorage.removeItem(key);
  9588. }
  9589. // store by cookie
  9590. else if($.cookie !== undefined) {
  9591. $.removeCookie(key, options);
  9592. }
  9593. else {
  9594. module.error(error.noStorage);
  9595. }
  9596. }
  9597. },
  9598. setting: function(name, value) {
  9599. module.debug('Changing setting', name, value);
  9600. if( $.isPlainObject(name) ) {
  9601. $.extend(true, settings, name);
  9602. }
  9603. else if(value !== undefined) {
  9604. if($.isPlainObject(settings[name])) {
  9605. $.extend(true, settings[name], value);
  9606. }
  9607. else {
  9608. settings[name] = value;
  9609. }
  9610. }
  9611. else {
  9612. return settings[name];
  9613. }
  9614. },
  9615. internal: function(name, value) {
  9616. if( $.isPlainObject(name) ) {
  9617. $.extend(true, module, name);
  9618. }
  9619. else if(value !== undefined) {
  9620. module[name] = value;
  9621. }
  9622. else {
  9623. return module[name];
  9624. }
  9625. },
  9626. debug: function() {
  9627. if(!settings.silent && settings.debug) {
  9628. if(settings.performance) {
  9629. module.performance.log(arguments);
  9630. }
  9631. else {
  9632. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9633. module.debug.apply(console, arguments);
  9634. }
  9635. }
  9636. },
  9637. verbose: function() {
  9638. if(!settings.silent && settings.verbose && settings.debug) {
  9639. if(settings.performance) {
  9640. module.performance.log(arguments);
  9641. }
  9642. else {
  9643. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9644. module.verbose.apply(console, arguments);
  9645. }
  9646. }
  9647. },
  9648. error: function() {
  9649. if(!settings.silent) {
  9650. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9651. module.error.apply(console, arguments);
  9652. }
  9653. },
  9654. performance: {
  9655. log: function(message) {
  9656. var
  9657. currentTime,
  9658. executionTime,
  9659. previousTime
  9660. ;
  9661. if(settings.performance) {
  9662. currentTime = new Date().getTime();
  9663. previousTime = time || currentTime;
  9664. executionTime = currentTime - previousTime;
  9665. time = currentTime;
  9666. performance.push({
  9667. 'Name' : message[0],
  9668. 'Arguments' : [].slice.call(message, 1) || '',
  9669. 'Element' : element,
  9670. 'Execution Time' : executionTime
  9671. });
  9672. }
  9673. clearTimeout(module.performance.timer);
  9674. module.performance.timer = setTimeout(module.performance.display, 500);
  9675. },
  9676. display: function() {
  9677. var
  9678. title = settings.name + ':',
  9679. totalTime = 0
  9680. ;
  9681. time = false;
  9682. clearTimeout(module.performance.timer);
  9683. $.each(performance, function(index, data) {
  9684. totalTime += data['Execution Time'];
  9685. });
  9686. title += ' ' + totalTime + 'ms';
  9687. if(moduleSelector) {
  9688. title += ' \'' + moduleSelector + '\'';
  9689. }
  9690. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9691. console.groupCollapsed(title);
  9692. if(console.table) {
  9693. console.table(performance);
  9694. }
  9695. else {
  9696. $.each(performance, function(index, data) {
  9697. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9698. });
  9699. }
  9700. console.groupEnd();
  9701. }
  9702. performance = [];
  9703. }
  9704. },
  9705. invoke: function(query, passedArguments, context) {
  9706. var
  9707. object = instance,
  9708. maxDepth,
  9709. found,
  9710. response
  9711. ;
  9712. passedArguments = passedArguments || queryArguments;
  9713. context = element || context;
  9714. if(typeof query == 'string' && object !== undefined) {
  9715. query = query.split(/[\. ]/);
  9716. maxDepth = query.length - 1;
  9717. $.each(query, function(depth, value) {
  9718. var camelCaseValue = (depth != maxDepth)
  9719. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9720. : query
  9721. ;
  9722. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9723. object = object[camelCaseValue];
  9724. }
  9725. else if( object[camelCaseValue] !== undefined ) {
  9726. found = object[camelCaseValue];
  9727. return false;
  9728. }
  9729. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9730. object = object[value];
  9731. }
  9732. else if( object[value] !== undefined ) {
  9733. found = object[value];
  9734. return false;
  9735. }
  9736. else {
  9737. module.error(error.method, query);
  9738. return false;
  9739. }
  9740. });
  9741. }
  9742. if ( $.isFunction( found ) ) {
  9743. response = found.apply(context, passedArguments);
  9744. }
  9745. else if(found !== undefined) {
  9746. response = found;
  9747. }
  9748. if($.isArray(returnedValue)) {
  9749. returnedValue.push(response);
  9750. }
  9751. else if(returnedValue !== undefined) {
  9752. returnedValue = [returnedValue, response];
  9753. }
  9754. else if(response !== undefined) {
  9755. returnedValue = response;
  9756. }
  9757. return found;
  9758. }
  9759. };
  9760. if(methodInvoked) {
  9761. if(instance === undefined) {
  9762. module.initialize();
  9763. }
  9764. module.invoke(query);
  9765. }
  9766. else {
  9767. if(instance !== undefined) {
  9768. instance.invoke('destroy');
  9769. }
  9770. module.initialize();
  9771. }
  9772. })
  9773. ;
  9774. return (returnedValue !== undefined)
  9775. ? returnedValue
  9776. : this
  9777. ;
  9778. };
  9779. $.fn.nag.settings = {
  9780. name : 'Nag',
  9781. silent : false,
  9782. debug : false,
  9783. verbose : false,
  9784. performance : true,
  9785. namespace : 'Nag',
  9786. // allows cookie to be overridden
  9787. persist : false,
  9788. // set to zero to require manually dismissal, otherwise hides on its own
  9789. displayTime : 0,
  9790. animation : {
  9791. show : 'slide',
  9792. hide : 'slide'
  9793. },
  9794. context : false,
  9795. detachable : false,
  9796. expires : 30,
  9797. domain : false,
  9798. path : '/',
  9799. // type of storage to use
  9800. storageMethod : 'cookie',
  9801. // value to store in dismissed localstorage/cookie
  9802. key : 'nag',
  9803. value : 'dismiss',
  9804. error: {
  9805. noCookieStorage : '$.cookie is not included. A storage solution is required.',
  9806. noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
  9807. method : 'The method you called is not defined.'
  9808. },
  9809. className : {
  9810. bottom : 'bottom',
  9811. fixed : 'fixed'
  9812. },
  9813. selector : {
  9814. close : '.close.icon'
  9815. },
  9816. speed : 500,
  9817. easing : 'easeOutQuad',
  9818. onHide: function() {}
  9819. };
  9820. // Adds easing
  9821. $.extend( $.easing, {
  9822. easeOutQuad: function (x, t, b, c, d) {
  9823. return -c *(t/=d)*(t-2) + b;
  9824. }
  9825. });
  9826. })( jQuery, window, document );
  9827. /*!
  9828. * # Semantic UI 2.3.3 - Popup
  9829. * http://github.com/semantic-org/semantic-ui/
  9830. *
  9831. *
  9832. * Released under the MIT license
  9833. * http://opensource.org/licenses/MIT
  9834. *
  9835. */
  9836. ;(function ($, window, document, undefined) {
  9837. 'use strict';
  9838. window = (typeof window != 'undefined' && window.Math == Math)
  9839. ? window
  9840. : (typeof self != 'undefined' && self.Math == Math)
  9841. ? self
  9842. : Function('return this')()
  9843. ;
  9844. $.fn.popup = function(parameters) {
  9845. var
  9846. $allModules = $(this),
  9847. $document = $(document),
  9848. $window = $(window),
  9849. $body = $('body'),
  9850. moduleSelector = $allModules.selector || '',
  9851. hasTouch = (true),
  9852. time = new Date().getTime(),
  9853. performance = [],
  9854. query = arguments[0],
  9855. methodInvoked = (typeof query == 'string'),
  9856. queryArguments = [].slice.call(arguments, 1),
  9857. returnedValue
  9858. ;
  9859. $allModules
  9860. .each(function() {
  9861. var
  9862. settings = ( $.isPlainObject(parameters) )
  9863. ? $.extend(true, {}, $.fn.popup.settings, parameters)
  9864. : $.extend({}, $.fn.popup.settings),
  9865. selector = settings.selector,
  9866. className = settings.className,
  9867. error = settings.error,
  9868. metadata = settings.metadata,
  9869. namespace = settings.namespace,
  9870. eventNamespace = '.' + settings.namespace,
  9871. moduleNamespace = 'module-' + namespace,
  9872. $module = $(this),
  9873. $context = $(settings.context),
  9874. $scrollContext = $(settings.scrollContext),
  9875. $boundary = $(settings.boundary),
  9876. $target = (settings.target)
  9877. ? $(settings.target)
  9878. : $module,
  9879. $popup,
  9880. $offsetParent,
  9881. searchDepth = 0,
  9882. triedPositions = false,
  9883. openedWithTouch = false,
  9884. element = this,
  9885. instance = $module.data(moduleNamespace),
  9886. documentObserver,
  9887. elementNamespace,
  9888. id,
  9889. module
  9890. ;
  9891. module = {
  9892. // binds events
  9893. initialize: function() {
  9894. module.debug('Initializing', $module);
  9895. module.createID();
  9896. module.bind.events();
  9897. if(!module.exists() && settings.preserve) {
  9898. module.create();
  9899. }
  9900. if(settings.observeChanges) {
  9901. module.observeChanges();
  9902. }
  9903. module.instantiate();
  9904. },
  9905. instantiate: function() {
  9906. module.verbose('Storing instance', module);
  9907. instance = module;
  9908. $module
  9909. .data(moduleNamespace, instance)
  9910. ;
  9911. },
  9912. observeChanges: function() {
  9913. if('MutationObserver' in window) {
  9914. documentObserver = new MutationObserver(module.event.documentChanged);
  9915. documentObserver.observe(document, {
  9916. childList : true,
  9917. subtree : true
  9918. });
  9919. module.debug('Setting up mutation observer', documentObserver);
  9920. }
  9921. },
  9922. refresh: function() {
  9923. if(settings.popup) {
  9924. $popup = $(settings.popup).eq(0);
  9925. }
  9926. else {
  9927. if(settings.inline) {
  9928. $popup = $target.nextAll(selector.popup).eq(0);
  9929. settings.popup = $popup;
  9930. }
  9931. }
  9932. if(settings.popup) {
  9933. $popup.addClass(className.loading);
  9934. $offsetParent = module.get.offsetParent();
  9935. $popup.removeClass(className.loading);
  9936. if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
  9937. module.debug('Moving popup to the same offset parent as target');
  9938. $popup
  9939. .detach()
  9940. .appendTo($offsetParent)
  9941. ;
  9942. }
  9943. }
  9944. else {
  9945. $offsetParent = (settings.inline)
  9946. ? module.get.offsetParent($target)
  9947. : module.has.popup()
  9948. ? module.get.offsetParent($popup)
  9949. : $body
  9950. ;
  9951. }
  9952. if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
  9953. module.debug('Setting page as offset parent');
  9954. $offsetParent = $body;
  9955. }
  9956. if( module.get.variation() ) {
  9957. module.set.variation();
  9958. }
  9959. },
  9960. reposition: function() {
  9961. module.refresh();
  9962. module.set.position();
  9963. },
  9964. destroy: function() {
  9965. module.debug('Destroying previous module');
  9966. if(documentObserver) {
  9967. documentObserver.disconnect();
  9968. }
  9969. // remove element only if was created dynamically
  9970. if($popup && !settings.preserve) {
  9971. module.removePopup();
  9972. }
  9973. // clear all timeouts
  9974. clearTimeout(module.hideTimer);
  9975. clearTimeout(module.showTimer);
  9976. // remove events
  9977. module.unbind.close();
  9978. module.unbind.events();
  9979. $module
  9980. .removeData(moduleNamespace)
  9981. ;
  9982. },
  9983. event: {
  9984. start: function(event) {
  9985. var
  9986. delay = ($.isPlainObject(settings.delay))
  9987. ? settings.delay.show
  9988. : settings.delay
  9989. ;
  9990. clearTimeout(module.hideTimer);
  9991. if(!openedWithTouch) {
  9992. module.showTimer = setTimeout(module.show, delay);
  9993. }
  9994. },
  9995. end: function() {
  9996. var
  9997. delay = ($.isPlainObject(settings.delay))
  9998. ? settings.delay.hide
  9999. : settings.delay
  10000. ;
  10001. clearTimeout(module.showTimer);
  10002. module.hideTimer = setTimeout(module.hide, delay);
  10003. },
  10004. touchstart: function(event) {
  10005. openedWithTouch = true;
  10006. module.show();
  10007. },
  10008. resize: function() {
  10009. if( module.is.visible() ) {
  10010. module.set.position();
  10011. }
  10012. },
  10013. documentChanged: function(mutations) {
  10014. [].forEach.call(mutations, function(mutation) {
  10015. if(mutation.removedNodes) {
  10016. [].forEach.call(mutation.removedNodes, function(node) {
  10017. if(node == element || $(node).find(element).length > 0) {
  10018. module.debug('Element removed from DOM, tearing down events');
  10019. module.destroy();
  10020. }
  10021. });
  10022. }
  10023. });
  10024. },
  10025. hideGracefully: function(event) {
  10026. var
  10027. $target = $(event.target),
  10028. isInDOM = $.contains(document.documentElement, event.target),
  10029. inPopup = ($target.closest(selector.popup).length > 0)
  10030. ;
  10031. // don't close on clicks inside popup
  10032. if(event && !inPopup && isInDOM) {
  10033. module.debug('Click occurred outside popup hiding popup');
  10034. module.hide();
  10035. }
  10036. else {
  10037. module.debug('Click was inside popup, keeping popup open');
  10038. }
  10039. }
  10040. },
  10041. // generates popup html from metadata
  10042. create: function() {
  10043. var
  10044. html = module.get.html(),
  10045. title = module.get.title(),
  10046. content = module.get.content()
  10047. ;
  10048. if(html || content || title) {
  10049. module.debug('Creating pop-up html');
  10050. if(!html) {
  10051. html = settings.templates.popup({
  10052. title : title,
  10053. content : content
  10054. });
  10055. }
  10056. $popup = $('<div/>')
  10057. .addClass(className.popup)
  10058. .data(metadata.activator, $module)
  10059. .html(html)
  10060. ;
  10061. if(settings.inline) {
  10062. module.verbose('Inserting popup element inline', $popup);
  10063. $popup
  10064. .insertAfter($module)
  10065. ;
  10066. }
  10067. else {
  10068. module.verbose('Appending popup element to body', $popup);
  10069. $popup
  10070. .appendTo( $context )
  10071. ;
  10072. }
  10073. module.refresh();
  10074. module.set.variation();
  10075. if(settings.hoverable) {
  10076. module.bind.popup();
  10077. }
  10078. settings.onCreate.call($popup, element);
  10079. }
  10080. else if($target.next(selector.popup).length !== 0) {
  10081. module.verbose('Pre-existing popup found');
  10082. settings.inline = true;
  10083. settings.popup = $target.next(selector.popup).data(metadata.activator, $module);
  10084. module.refresh();
  10085. if(settings.hoverable) {
  10086. module.bind.popup();
  10087. }
  10088. }
  10089. else if(settings.popup) {
  10090. $(settings.popup).data(metadata.activator, $module);
  10091. module.verbose('Used popup specified in settings');
  10092. module.refresh();
  10093. if(settings.hoverable) {
  10094. module.bind.popup();
  10095. }
  10096. }
  10097. else {
  10098. module.debug('No content specified skipping display', element);
  10099. }
  10100. },
  10101. createID: function() {
  10102. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  10103. elementNamespace = '.' + id;
  10104. module.verbose('Creating unique id for element', id);
  10105. },
  10106. // determines popup state
  10107. toggle: function() {
  10108. module.debug('Toggling pop-up');
  10109. if( module.is.hidden() ) {
  10110. module.debug('Popup is hidden, showing pop-up');
  10111. module.unbind.close();
  10112. module.show();
  10113. }
  10114. else {
  10115. module.debug('Popup is visible, hiding pop-up');
  10116. module.hide();
  10117. }
  10118. },
  10119. show: function(callback) {
  10120. callback = callback || function(){};
  10121. module.debug('Showing pop-up', settings.transition);
  10122. if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
  10123. if( !module.exists() ) {
  10124. module.create();
  10125. }
  10126. if(settings.onShow.call($popup, element) === false) {
  10127. module.debug('onShow callback returned false, cancelling popup animation');
  10128. return;
  10129. }
  10130. else if(!settings.preserve && !settings.popup) {
  10131. module.refresh();
  10132. }
  10133. if( $popup && module.set.position() ) {
  10134. module.save.conditions();
  10135. if(settings.exclusive) {
  10136. module.hideAll();
  10137. }
  10138. module.animate.show(callback);
  10139. }
  10140. }
  10141. },
  10142. hide: function(callback) {
  10143. callback = callback || function(){};
  10144. if( module.is.visible() || module.is.animating() ) {
  10145. if(settings.onHide.call($popup, element) === false) {
  10146. module.debug('onHide callback returned false, cancelling popup animation');
  10147. return;
  10148. }
  10149. module.remove.visible();
  10150. module.unbind.close();
  10151. module.restore.conditions();
  10152. module.animate.hide(callback);
  10153. }
  10154. },
  10155. hideAll: function() {
  10156. $(selector.popup)
  10157. .filter('.' + className.popupVisible)
  10158. .each(function() {
  10159. $(this)
  10160. .data(metadata.activator)
  10161. .popup('hide')
  10162. ;
  10163. })
  10164. ;
  10165. },
  10166. exists: function() {
  10167. if(!$popup) {
  10168. return false;
  10169. }
  10170. if(settings.inline || settings.popup) {
  10171. return ( module.has.popup() );
  10172. }
  10173. else {
  10174. return ( $popup.closest($context).length >= 1 )
  10175. ? true
  10176. : false
  10177. ;
  10178. }
  10179. },
  10180. removePopup: function() {
  10181. if( module.has.popup() && !settings.popup) {
  10182. module.debug('Removing popup', $popup);
  10183. $popup.remove();
  10184. $popup = undefined;
  10185. settings.onRemove.call($popup, element);
  10186. }
  10187. },
  10188. save: {
  10189. conditions: function() {
  10190. module.cache = {
  10191. title: $module.attr('title')
  10192. };
  10193. if (module.cache.title) {
  10194. $module.removeAttr('title');
  10195. }
  10196. module.verbose('Saving original attributes', module.cache.title);
  10197. }
  10198. },
  10199. restore: {
  10200. conditions: function() {
  10201. if(module.cache && module.cache.title) {
  10202. $module.attr('title', module.cache.title);
  10203. module.verbose('Restoring original attributes', module.cache.title);
  10204. }
  10205. return true;
  10206. }
  10207. },
  10208. supports: {
  10209. svg: function() {
  10210. return (typeof SVGGraphicsElement === 'undefined');
  10211. }
  10212. },
  10213. animate: {
  10214. show: function(callback) {
  10215. callback = $.isFunction(callback) ? callback : function(){};
  10216. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  10217. module.set.visible();
  10218. $popup
  10219. .transition({
  10220. animation : settings.transition + ' in',
  10221. queue : false,
  10222. debug : settings.debug,
  10223. verbose : settings.verbose,
  10224. duration : settings.duration,
  10225. onComplete : function() {
  10226. module.bind.close();
  10227. callback.call($popup, element);
  10228. settings.onVisible.call($popup, element);
  10229. }
  10230. })
  10231. ;
  10232. }
  10233. else {
  10234. module.error(error.noTransition);
  10235. }
  10236. },
  10237. hide: function(callback) {
  10238. callback = $.isFunction(callback) ? callback : function(){};
  10239. module.debug('Hiding pop-up');
  10240. if(settings.onHide.call($popup, element) === false) {
  10241. module.debug('onHide callback returned false, cancelling popup animation');
  10242. return;
  10243. }
  10244. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  10245. $popup
  10246. .transition({
  10247. animation : settings.transition + ' out',
  10248. queue : false,
  10249. duration : settings.duration,
  10250. debug : settings.debug,
  10251. verbose : settings.verbose,
  10252. onComplete : function() {
  10253. module.reset();
  10254. callback.call($popup, element);
  10255. settings.onHidden.call($popup, element);
  10256. }
  10257. })
  10258. ;
  10259. }
  10260. else {
  10261. module.error(error.noTransition);
  10262. }
  10263. }
  10264. },
  10265. change: {
  10266. content: function(html) {
  10267. $popup.html(html);
  10268. }
  10269. },
  10270. get: {
  10271. html: function() {
  10272. $module.removeData(metadata.html);
  10273. return $module.data(metadata.html) || settings.html;
  10274. },
  10275. title: function() {
  10276. $module.removeData(metadata.title);
  10277. return $module.data(metadata.title) || settings.title;
  10278. },
  10279. content: function() {
  10280. $module.removeData(metadata.content);
  10281. return $module.data(metadata.content) || settings.content || $module.attr('title');
  10282. },
  10283. variation: function() {
  10284. $module.removeData(metadata.variation);
  10285. return $module.data(metadata.variation) || settings.variation;
  10286. },
  10287. popup: function() {
  10288. return $popup;
  10289. },
  10290. popupOffset: function() {
  10291. return $popup.offset();
  10292. },
  10293. calculations: function() {
  10294. var
  10295. $popupOffsetParent = module.get.offsetParent($popup),
  10296. targetElement = $target[0],
  10297. isWindow = ($boundary[0] == window),
  10298. targetPosition = (settings.inline || (settings.popup && settings.movePopup))
  10299. ? $target.position()
  10300. : $target.offset(),
  10301. screenPosition = (isWindow)
  10302. ? { top: 0, left: 0 }
  10303. : $boundary.offset(),
  10304. calculations = {},
  10305. scroll = (isWindow)
  10306. ? { top: $window.scrollTop(), left: $window.scrollLeft() }
  10307. : { top: 0, left: 0},
  10308. screen
  10309. ;
  10310. calculations = {
  10311. // element which is launching popup
  10312. target : {
  10313. element : $target[0],
  10314. width : $target.outerWidth(),
  10315. height : $target.outerHeight(),
  10316. top : targetPosition.top,
  10317. left : targetPosition.left,
  10318. margin : {}
  10319. },
  10320. // popup itself
  10321. popup : {
  10322. width : $popup.outerWidth(),
  10323. height : $popup.outerHeight()
  10324. },
  10325. // offset container (or 3d context)
  10326. parent : {
  10327. width : $offsetParent.outerWidth(),
  10328. height : $offsetParent.outerHeight()
  10329. },
  10330. // screen boundaries
  10331. screen : {
  10332. top : screenPosition.top,
  10333. left : screenPosition.left,
  10334. scroll: {
  10335. top : scroll.top,
  10336. left : scroll.left
  10337. },
  10338. width : $boundary.width(),
  10339. height : $boundary.height()
  10340. }
  10341. };
  10342. // if popup offset context is not same as target, then adjust calculations
  10343. if($popupOffsetParent.get(0) !== $offsetParent.get(0)) {
  10344. var
  10345. popupOffset = $popupOffsetParent.offset()
  10346. ;
  10347. calculations.target.top -= popupOffset.top;
  10348. calculations.target.left -= popupOffset.left;
  10349. calculations.parent.width = $popupOffsetParent.outerWidth();
  10350. calculations.parent.height = $popupOffsetParent.outerHeight();
  10351. }
  10352. // add in container calcs if fluid
  10353. if( settings.setFluidWidth && module.is.fluid() ) {
  10354. calculations.container = {
  10355. width: $popup.parent().outerWidth()
  10356. };
  10357. calculations.popup.width = calculations.container.width;
  10358. }
  10359. // add in margins if inline
  10360. calculations.target.margin.top = (settings.inline)
  10361. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
  10362. : 0
  10363. ;
  10364. calculations.target.margin.left = (settings.inline)
  10365. ? module.is.rtl()
  10366. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
  10367. : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
  10368. : 0
  10369. ;
  10370. // calculate screen boundaries
  10371. screen = calculations.screen;
  10372. calculations.boundary = {
  10373. top : screen.top + screen.scroll.top,
  10374. bottom : screen.top + screen.scroll.top + screen.height,
  10375. left : screen.left + screen.scroll.left,
  10376. right : screen.left + screen.scroll.left + screen.width
  10377. };
  10378. return calculations;
  10379. },
  10380. id: function() {
  10381. return id;
  10382. },
  10383. startEvent: function() {
  10384. if(settings.on == 'hover') {
  10385. return 'mouseenter';
  10386. }
  10387. else if(settings.on == 'focus') {
  10388. return 'focus';
  10389. }
  10390. return false;
  10391. },
  10392. scrollEvent: function() {
  10393. return 'scroll';
  10394. },
  10395. endEvent: function() {
  10396. if(settings.on == 'hover') {
  10397. return 'mouseleave';
  10398. }
  10399. else if(settings.on == 'focus') {
  10400. return 'blur';
  10401. }
  10402. return false;
  10403. },
  10404. distanceFromBoundary: function(offset, calculations) {
  10405. var
  10406. distanceFromBoundary = {},
  10407. popup,
  10408. boundary
  10409. ;
  10410. calculations = calculations || module.get.calculations();
  10411. // shorthand
  10412. popup = calculations.popup;
  10413. boundary = calculations.boundary;
  10414. if(offset) {
  10415. distanceFromBoundary = {
  10416. top : (offset.top - boundary.top),
  10417. left : (offset.left - boundary.left),
  10418. right : (boundary.right - (offset.left + popup.width) ),
  10419. bottom : (boundary.bottom - (offset.top + popup.height) )
  10420. };
  10421. module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
  10422. }
  10423. return distanceFromBoundary;
  10424. },
  10425. offsetParent: function($element) {
  10426. var
  10427. element = ($element !== undefined)
  10428. ? $element[0]
  10429. : $target[0],
  10430. parentNode = element.parentNode,
  10431. $node = $(parentNode)
  10432. ;
  10433. if(parentNode) {
  10434. var
  10435. is2D = ($node.css('transform') === 'none'),
  10436. isStatic = ($node.css('position') === 'static'),
  10437. isBody = $node.is('body')
  10438. ;
  10439. while(parentNode && !isBody && isStatic && is2D) {
  10440. parentNode = parentNode.parentNode;
  10441. $node = $(parentNode);
  10442. is2D = ($node.css('transform') === 'none');
  10443. isStatic = ($node.css('position') === 'static');
  10444. isBody = $node.is('body');
  10445. }
  10446. }
  10447. return ($node && $node.length > 0)
  10448. ? $node
  10449. : $()
  10450. ;
  10451. },
  10452. positions: function() {
  10453. return {
  10454. 'top left' : false,
  10455. 'top center' : false,
  10456. 'top right' : false,
  10457. 'bottom left' : false,
  10458. 'bottom center' : false,
  10459. 'bottom right' : false,
  10460. 'left center' : false,
  10461. 'right center' : false
  10462. };
  10463. },
  10464. nextPosition: function(position) {
  10465. var
  10466. positions = position.split(' '),
  10467. verticalPosition = positions[0],
  10468. horizontalPosition = positions[1],
  10469. opposite = {
  10470. top : 'bottom',
  10471. bottom : 'top',
  10472. left : 'right',
  10473. right : 'left'
  10474. },
  10475. adjacent = {
  10476. left : 'center',
  10477. center : 'right',
  10478. right : 'left'
  10479. },
  10480. backup = {
  10481. 'top left' : 'top center',
  10482. 'top center' : 'top right',
  10483. 'top right' : 'right center',
  10484. 'right center' : 'bottom right',
  10485. 'bottom right' : 'bottom center',
  10486. 'bottom center' : 'bottom left',
  10487. 'bottom left' : 'left center',
  10488. 'left center' : 'top left'
  10489. },
  10490. adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
  10491. oppositeTried = false,
  10492. adjacentTried = false,
  10493. nextPosition = false
  10494. ;
  10495. if(!triedPositions) {
  10496. module.verbose('All available positions available');
  10497. triedPositions = module.get.positions();
  10498. }
  10499. module.debug('Recording last position tried', position);
  10500. triedPositions[position] = true;
  10501. if(settings.prefer === 'opposite') {
  10502. nextPosition = [opposite[verticalPosition], horizontalPosition];
  10503. nextPosition = nextPosition.join(' ');
  10504. oppositeTried = (triedPositions[nextPosition] === true);
  10505. module.debug('Trying opposite strategy', nextPosition);
  10506. }
  10507. if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
  10508. nextPosition = [verticalPosition, adjacent[horizontalPosition]];
  10509. nextPosition = nextPosition.join(' ');
  10510. adjacentTried = (triedPositions[nextPosition] === true);
  10511. module.debug('Trying adjacent strategy', nextPosition);
  10512. }
  10513. if(adjacentTried || oppositeTried) {
  10514. module.debug('Using backup position', nextPosition);
  10515. nextPosition = backup[position];
  10516. }
  10517. return nextPosition;
  10518. }
  10519. },
  10520. set: {
  10521. position: function(position, calculations) {
  10522. // exit conditions
  10523. if($target.length === 0 || $popup.length === 0) {
  10524. module.error(error.notFound);
  10525. return;
  10526. }
  10527. var
  10528. offset,
  10529. distanceAway,
  10530. target,
  10531. popup,
  10532. parent,
  10533. positioning,
  10534. popupOffset,
  10535. distanceFromBoundary
  10536. ;
  10537. calculations = calculations || module.get.calculations();
  10538. position = position || $module.data(metadata.position) || settings.position;
  10539. offset = $module.data(metadata.offset) || settings.offset;
  10540. distanceAway = settings.distanceAway;
  10541. // shorthand
  10542. target = calculations.target;
  10543. popup = calculations.popup;
  10544. parent = calculations.parent;
  10545. if(module.should.centerArrow(calculations)) {
  10546. module.verbose('Adjusting offset to center arrow on small target element');
  10547. if(position == 'top left' || position == 'bottom left') {
  10548. offset += (target.width / 2)
  10549. offset -= settings.arrowPixelsFromEdge;
  10550. }
  10551. if(position == 'top right' || position == 'bottom right') {
  10552. offset -= (target.width / 2)
  10553. offset += settings.arrowPixelsFromEdge;
  10554. }
  10555. }
  10556. if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) {
  10557. module.debug('Popup target is hidden, no action taken');
  10558. return false;
  10559. }
  10560. if(settings.inline) {
  10561. module.debug('Adding margin to calculation', target.margin);
  10562. if(position == 'left center' || position == 'right center') {
  10563. offset += target.margin.top;
  10564. distanceAway += -target.margin.left;
  10565. }
  10566. else if (position == 'top left' || position == 'top center' || position == 'top right') {
  10567. offset += target.margin.left;
  10568. distanceAway -= target.margin.top;
  10569. }
  10570. else {
  10571. offset += target.margin.left;
  10572. distanceAway += target.margin.top;
  10573. }
  10574. }
  10575. module.debug('Determining popup position from calculations', position, calculations);
  10576. if (module.is.rtl()) {
  10577. position = position.replace(/left|right/g, function (match) {
  10578. return (match == 'left')
  10579. ? 'right'
  10580. : 'left'
  10581. ;
  10582. });
  10583. module.debug('RTL: Popup position updated', position);
  10584. }
  10585. // if last attempt use specified last resort position
  10586. if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
  10587. position = settings.lastResort;
  10588. }
  10589. switch (position) {
  10590. case 'top left':
  10591. positioning = {
  10592. top : 'auto',
  10593. bottom : parent.height - target.top + distanceAway,
  10594. left : target.left + offset,
  10595. right : 'auto'
  10596. };
  10597. break;
  10598. case 'top center':
  10599. positioning = {
  10600. bottom : parent.height - target.top + distanceAway,
  10601. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  10602. top : 'auto',
  10603. right : 'auto'
  10604. };
  10605. break;
  10606. case 'top right':
  10607. positioning = {
  10608. bottom : parent.height - target.top + distanceAway,
  10609. right : parent.width - target.left - target.width - offset,
  10610. top : 'auto',
  10611. left : 'auto'
  10612. };
  10613. break;
  10614. case 'left center':
  10615. positioning = {
  10616. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  10617. right : parent.width - target.left + distanceAway,
  10618. left : 'auto',
  10619. bottom : 'auto'
  10620. };
  10621. break;
  10622. case 'right center':
  10623. positioning = {
  10624. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  10625. left : target.left + target.width + distanceAway,
  10626. bottom : 'auto',
  10627. right : 'auto'
  10628. };
  10629. break;
  10630. case 'bottom left':
  10631. positioning = {
  10632. top : target.top + target.height + distanceAway,
  10633. left : target.left + offset,
  10634. bottom : 'auto',
  10635. right : 'auto'
  10636. };
  10637. break;
  10638. case 'bottom center':
  10639. positioning = {
  10640. top : target.top + target.height + distanceAway,
  10641. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  10642. bottom : 'auto',
  10643. right : 'auto'
  10644. };
  10645. break;
  10646. case 'bottom right':
  10647. positioning = {
  10648. top : target.top + target.height + distanceAway,
  10649. right : parent.width - target.left - target.width - offset,
  10650. left : 'auto',
  10651. bottom : 'auto'
  10652. };
  10653. break;
  10654. }
  10655. if(positioning === undefined) {
  10656. module.error(error.invalidPosition, position);
  10657. }
  10658. module.debug('Calculated popup positioning values', positioning);
  10659. // tentatively place on stage
  10660. $popup
  10661. .css(positioning)
  10662. .removeClass(className.position)
  10663. .addClass(position)
  10664. .addClass(className.loading)
  10665. ;
  10666. popupOffset = module.get.popupOffset();
  10667. // see if any boundaries are surpassed with this tentative position
  10668. distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
  10669. if( module.is.offstage(distanceFromBoundary, position) ) {
  10670. module.debug('Position is outside viewport', position);
  10671. if(searchDepth < settings.maxSearchDepth) {
  10672. searchDepth++;
  10673. position = module.get.nextPosition(position);
  10674. module.debug('Trying new position', position);
  10675. return ($popup)
  10676. ? module.set.position(position, calculations)
  10677. : false
  10678. ;
  10679. }
  10680. else {
  10681. if(settings.lastResort) {
  10682. module.debug('No position found, showing with last position');
  10683. }
  10684. else {
  10685. module.debug('Popup could not find a position to display', $popup);
  10686. module.error(error.cannotPlace, element);
  10687. module.remove.attempts();
  10688. module.remove.loading();
  10689. module.reset();
  10690. settings.onUnplaceable.call($popup, element);
  10691. return false;
  10692. }
  10693. }
  10694. }
  10695. module.debug('Position is on stage', position);
  10696. module.remove.attempts();
  10697. module.remove.loading();
  10698. if( settings.setFluidWidth && module.is.fluid() ) {
  10699. module.set.fluidWidth(calculations);
  10700. }
  10701. return true;
  10702. },
  10703. fluidWidth: function(calculations) {
  10704. calculations = calculations || module.get.calculations();
  10705. module.debug('Automatically setting element width to parent width', calculations.parent.width);
  10706. $popup.css('width', calculations.container.width);
  10707. },
  10708. variation: function(variation) {
  10709. variation = variation || module.get.variation();
  10710. if(variation && module.has.popup() ) {
  10711. module.verbose('Adding variation to popup', variation);
  10712. $popup.addClass(variation);
  10713. }
  10714. },
  10715. visible: function() {
  10716. $module.addClass(className.visible);
  10717. }
  10718. },
  10719. remove: {
  10720. loading: function() {
  10721. $popup.removeClass(className.loading);
  10722. },
  10723. variation: function(variation) {
  10724. variation = variation || module.get.variation();
  10725. if(variation) {
  10726. module.verbose('Removing variation', variation);
  10727. $popup.removeClass(variation);
  10728. }
  10729. },
  10730. visible: function() {
  10731. $module.removeClass(className.visible);
  10732. },
  10733. attempts: function() {
  10734. module.verbose('Resetting all searched positions');
  10735. searchDepth = 0;
  10736. triedPositions = false;
  10737. }
  10738. },
  10739. bind: {
  10740. events: function() {
  10741. module.debug('Binding popup events to module');
  10742. if(settings.on == 'click') {
  10743. $module
  10744. .on('click' + eventNamespace, module.toggle)
  10745. ;
  10746. }
  10747. if(settings.on == 'hover' && hasTouch) {
  10748. $module
  10749. .on('touchstart' + eventNamespace, module.event.touchstart)
  10750. ;
  10751. }
  10752. if( module.get.startEvent() ) {
  10753. $module
  10754. .on(module.get.startEvent() + eventNamespace, module.event.start)
  10755. .on(module.get.endEvent() + eventNamespace, module.event.end)
  10756. ;
  10757. }
  10758. if(settings.target) {
  10759. module.debug('Target set to element', $target);
  10760. }
  10761. $window.on('resize' + elementNamespace, module.event.resize);
  10762. },
  10763. popup: function() {
  10764. module.verbose('Allowing hover events on popup to prevent closing');
  10765. if( $popup && module.has.popup() ) {
  10766. $popup
  10767. .on('mouseenter' + eventNamespace, module.event.start)
  10768. .on('mouseleave' + eventNamespace, module.event.end)
  10769. ;
  10770. }
  10771. },
  10772. close: function() {
  10773. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  10774. module.bind.closeOnScroll();
  10775. }
  10776. if(settings.on == 'hover' && openedWithTouch) {
  10777. module.bind.touchClose();
  10778. }
  10779. if(settings.on == 'click' && settings.closable) {
  10780. module.bind.clickaway();
  10781. }
  10782. },
  10783. closeOnScroll: function() {
  10784. module.verbose('Binding scroll close event to document');
  10785. $scrollContext
  10786. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  10787. ;
  10788. },
  10789. touchClose: function() {
  10790. module.verbose('Binding popup touchclose event to document');
  10791. $document
  10792. .on('touchstart' + elementNamespace, function(event) {
  10793. module.verbose('Touched away from popup');
  10794. module.event.hideGracefully.call(element, event);
  10795. })
  10796. ;
  10797. },
  10798. clickaway: function() {
  10799. module.verbose('Binding popup close event to document');
  10800. $document
  10801. .on('click' + elementNamespace, function(event) {
  10802. module.verbose('Clicked away from popup');
  10803. module.event.hideGracefully.call(element, event);
  10804. })
  10805. ;
  10806. }
  10807. },
  10808. unbind: {
  10809. events: function() {
  10810. $window
  10811. .off(elementNamespace)
  10812. ;
  10813. $module
  10814. .off(eventNamespace)
  10815. ;
  10816. },
  10817. close: function() {
  10818. $document
  10819. .off(elementNamespace)
  10820. ;
  10821. $scrollContext
  10822. .off(elementNamespace)
  10823. ;
  10824. },
  10825. },
  10826. has: {
  10827. popup: function() {
  10828. return ($popup && $popup.length > 0);
  10829. }
  10830. },
  10831. should: {
  10832. centerArrow: function(calculations) {
  10833. return !module.is.basic() && calculations.target.width <= (settings.arrowPixelsFromEdge * 2);
  10834. }
  10835. },
  10836. is: {
  10837. offstage: function(distanceFromBoundary, position) {
  10838. var
  10839. offstage = []
  10840. ;
  10841. // return boundaries that have been surpassed
  10842. $.each(distanceFromBoundary, function(direction, distance) {
  10843. if(distance < -settings.jitter) {
  10844. module.debug('Position exceeds allowable distance from edge', direction, distance, position);
  10845. offstage.push(direction);
  10846. }
  10847. });
  10848. if(offstage.length > 0) {
  10849. return true;
  10850. }
  10851. else {
  10852. return false;
  10853. }
  10854. },
  10855. svg: function(element) {
  10856. return module.supports.svg() && (element instanceof SVGGraphicsElement);
  10857. },
  10858. basic: function() {
  10859. return $module.hasClass(className.basic);
  10860. },
  10861. active: function() {
  10862. return $module.hasClass(className.active);
  10863. },
  10864. animating: function() {
  10865. return ($popup !== undefined && $popup.hasClass(className.animating) );
  10866. },
  10867. fluid: function() {
  10868. return ($popup !== undefined && $popup.hasClass(className.fluid));
  10869. },
  10870. visible: function() {
  10871. return ($popup !== undefined && $popup.hasClass(className.popupVisible));
  10872. },
  10873. dropdown: function() {
  10874. return $module.hasClass(className.dropdown);
  10875. },
  10876. hidden: function() {
  10877. return !module.is.visible();
  10878. },
  10879. rtl: function () {
  10880. return $module.css('direction') == 'rtl';
  10881. }
  10882. },
  10883. reset: function() {
  10884. module.remove.visible();
  10885. if(settings.preserve) {
  10886. if($.fn.transition !== undefined) {
  10887. $popup
  10888. .transition('remove transition')
  10889. ;
  10890. }
  10891. }
  10892. else {
  10893. module.removePopup();
  10894. }
  10895. },
  10896. setting: function(name, value) {
  10897. if( $.isPlainObject(name) ) {
  10898. $.extend(true, settings, name);
  10899. }
  10900. else if(value !== undefined) {
  10901. settings[name] = value;
  10902. }
  10903. else {
  10904. return settings[name];
  10905. }
  10906. },
  10907. internal: function(name, value) {
  10908. if( $.isPlainObject(name) ) {
  10909. $.extend(true, module, name);
  10910. }
  10911. else if(value !== undefined) {
  10912. module[name] = value;
  10913. }
  10914. else {
  10915. return module[name];
  10916. }
  10917. },
  10918. debug: function() {
  10919. if(!settings.silent && settings.debug) {
  10920. if(settings.performance) {
  10921. module.performance.log(arguments);
  10922. }
  10923. else {
  10924. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10925. module.debug.apply(console, arguments);
  10926. }
  10927. }
  10928. },
  10929. verbose: function() {
  10930. if(!settings.silent && settings.verbose && settings.debug) {
  10931. if(settings.performance) {
  10932. module.performance.log(arguments);
  10933. }
  10934. else {
  10935. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10936. module.verbose.apply(console, arguments);
  10937. }
  10938. }
  10939. },
  10940. error: function() {
  10941. if(!settings.silent) {
  10942. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  10943. module.error.apply(console, arguments);
  10944. }
  10945. },
  10946. performance: {
  10947. log: function(message) {
  10948. var
  10949. currentTime,
  10950. executionTime,
  10951. previousTime
  10952. ;
  10953. if(settings.performance) {
  10954. currentTime = new Date().getTime();
  10955. previousTime = time || currentTime;
  10956. executionTime = currentTime - previousTime;
  10957. time = currentTime;
  10958. performance.push({
  10959. 'Name' : message[0],
  10960. 'Arguments' : [].slice.call(message, 1) || '',
  10961. 'Element' : element,
  10962. 'Execution Time' : executionTime
  10963. });
  10964. }
  10965. clearTimeout(module.performance.timer);
  10966. module.performance.timer = setTimeout(module.performance.display, 500);
  10967. },
  10968. display: function() {
  10969. var
  10970. title = settings.name + ':',
  10971. totalTime = 0
  10972. ;
  10973. time = false;
  10974. clearTimeout(module.performance.timer);
  10975. $.each(performance, function(index, data) {
  10976. totalTime += data['Execution Time'];
  10977. });
  10978. title += ' ' + totalTime + 'ms';
  10979. if(moduleSelector) {
  10980. title += ' \'' + moduleSelector + '\'';
  10981. }
  10982. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  10983. console.groupCollapsed(title);
  10984. if(console.table) {
  10985. console.table(performance);
  10986. }
  10987. else {
  10988. $.each(performance, function(index, data) {
  10989. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  10990. });
  10991. }
  10992. console.groupEnd();
  10993. }
  10994. performance = [];
  10995. }
  10996. },
  10997. invoke: function(query, passedArguments, context) {
  10998. var
  10999. object = instance,
  11000. maxDepth,
  11001. found,
  11002. response
  11003. ;
  11004. passedArguments = passedArguments || queryArguments;
  11005. context = element || context;
  11006. if(typeof query == 'string' && object !== undefined) {
  11007. query = query.split(/[\. ]/);
  11008. maxDepth = query.length - 1;
  11009. $.each(query, function(depth, value) {
  11010. var camelCaseValue = (depth != maxDepth)
  11011. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  11012. : query
  11013. ;
  11014. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  11015. object = object[camelCaseValue];
  11016. }
  11017. else if( object[camelCaseValue] !== undefined ) {
  11018. found = object[camelCaseValue];
  11019. return false;
  11020. }
  11021. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  11022. object = object[value];
  11023. }
  11024. else if( object[value] !== undefined ) {
  11025. found = object[value];
  11026. return false;
  11027. }
  11028. else {
  11029. return false;
  11030. }
  11031. });
  11032. }
  11033. if ( $.isFunction( found ) ) {
  11034. response = found.apply(context, passedArguments);
  11035. }
  11036. else if(found !== undefined) {
  11037. response = found;
  11038. }
  11039. if($.isArray(returnedValue)) {
  11040. returnedValue.push(response);
  11041. }
  11042. else if(returnedValue !== undefined) {
  11043. returnedValue = [returnedValue, response];
  11044. }
  11045. else if(response !== undefined) {
  11046. returnedValue = response;
  11047. }
  11048. return found;
  11049. }
  11050. };
  11051. if(methodInvoked) {
  11052. if(instance === undefined) {
  11053. module.initialize();
  11054. }
  11055. module.invoke(query);
  11056. }
  11057. else {
  11058. if(instance !== undefined) {
  11059. instance.invoke('destroy');
  11060. }
  11061. module.initialize();
  11062. }
  11063. })
  11064. ;
  11065. return (returnedValue !== undefined)
  11066. ? returnedValue
  11067. : this
  11068. ;
  11069. };
  11070. $.fn.popup.settings = {
  11071. name : 'Popup',
  11072. // module settings
  11073. silent : false,
  11074. debug : false,
  11075. verbose : false,
  11076. performance : true,
  11077. namespace : 'popup',
  11078. // whether it should use dom mutation observers
  11079. observeChanges : true,
  11080. // callback only when element added to dom
  11081. onCreate : function(){},
  11082. // callback before element removed from dom
  11083. onRemove : function(){},
  11084. // callback before show animation
  11085. onShow : function(){},
  11086. // callback after show animation
  11087. onVisible : function(){},
  11088. // callback before hide animation
  11089. onHide : function(){},
  11090. // callback when popup cannot be positioned in visible screen
  11091. onUnplaceable : function(){},
  11092. // callback after hide animation
  11093. onHidden : function(){},
  11094. // when to show popup
  11095. on : 'hover',
  11096. // element to use to determine if popup is out of boundary
  11097. boundary : window,
  11098. // whether to add touchstart events when using hover
  11099. addTouchEvents : true,
  11100. // default position relative to element
  11101. position : 'top left',
  11102. // name of variation to use
  11103. variation : '',
  11104. // whether popup should be moved to context
  11105. movePopup : true,
  11106. // element which popup should be relative to
  11107. target : false,
  11108. // jq selector or element that should be used as popup
  11109. popup : false,
  11110. // popup should remain inline next to activator
  11111. inline : false,
  11112. // popup should be removed from page on hide
  11113. preserve : false,
  11114. // popup should not close when being hovered on
  11115. hoverable : false,
  11116. // explicitly set content
  11117. content : false,
  11118. // explicitly set html
  11119. html : false,
  11120. // explicitly set title
  11121. title : false,
  11122. // whether automatically close on clickaway when on click
  11123. closable : true,
  11124. // automatically hide on scroll
  11125. hideOnScroll : 'auto',
  11126. // hide other popups on show
  11127. exclusive : false,
  11128. // context to attach popups
  11129. context : 'body',
  11130. // context for binding scroll events
  11131. scrollContext : window,
  11132. // position to prefer when calculating new position
  11133. prefer : 'opposite',
  11134. // specify position to appear even if it doesn't fit
  11135. lastResort : false,
  11136. // number of pixels from edge of popup to pointing arrow center (used from centering)
  11137. arrowPixelsFromEdge: 20,
  11138. // delay used to prevent accidental refiring of animations due to user error
  11139. delay : {
  11140. show : 50,
  11141. hide : 70
  11142. },
  11143. // whether fluid variation should assign width explicitly
  11144. setFluidWidth : true,
  11145. // transition settings
  11146. duration : 200,
  11147. transition : 'scale',
  11148. // distance away from activating element in px
  11149. distanceAway : 0,
  11150. // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
  11151. jitter : 2,
  11152. // offset on aligning axis from calculated position
  11153. offset : 0,
  11154. // maximum times to look for a position before failing (9 positions total)
  11155. maxSearchDepth : 15,
  11156. error: {
  11157. invalidPosition : 'The position you specified is not a valid position',
  11158. cannotPlace : 'Popup does not fit within the boundaries of the viewport',
  11159. method : 'The method you called is not defined.',
  11160. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  11161. notFound : 'The target or popup you specified does not exist on the page'
  11162. },
  11163. metadata: {
  11164. activator : 'activator',
  11165. content : 'content',
  11166. html : 'html',
  11167. offset : 'offset',
  11168. position : 'position',
  11169. title : 'title',
  11170. variation : 'variation'
  11171. },
  11172. className : {
  11173. active : 'active',
  11174. basic : 'basic',
  11175. animating : 'animating',
  11176. dropdown : 'dropdown',
  11177. fluid : 'fluid',
  11178. loading : 'loading',
  11179. popup : 'ui popup',
  11180. position : 'top left center bottom right',
  11181. visible : 'visible',
  11182. popupVisible : 'visible'
  11183. },
  11184. selector : {
  11185. popup : '.ui.popup'
  11186. },
  11187. templates: {
  11188. escape: function(string) {
  11189. var
  11190. badChars = /[&<>"'`]/g,
  11191. shouldEscape = /[&<>"'`]/,
  11192. escape = {
  11193. "&": "&amp;",
  11194. "<": "&lt;",
  11195. ">": "&gt;",
  11196. '"': "&quot;",
  11197. "'": "&#x27;",
  11198. "`": "&#x60;"
  11199. },
  11200. escapedChar = function(chr) {
  11201. return escape[chr];
  11202. }
  11203. ;
  11204. if(shouldEscape.test(string)) {
  11205. return string.replace(badChars, escapedChar);
  11206. }
  11207. return string;
  11208. },
  11209. popup: function(text) {
  11210. var
  11211. html = '',
  11212. escape = $.fn.popup.settings.templates.escape
  11213. ;
  11214. if(typeof text !== undefined) {
  11215. if(typeof text.title !== undefined && text.title) {
  11216. text.title = escape(text.title);
  11217. html += '<div class="header">' + text.title + '</div>';
  11218. }
  11219. if(typeof text.content !== undefined && text.content) {
  11220. text.content = escape(text.content);
  11221. html += '<div class="content">' + text.content + '</div>';
  11222. }
  11223. }
  11224. return html;
  11225. }
  11226. }
  11227. };
  11228. })( jQuery, window, document );
  11229. /*!
  11230. * # Semantic UI 2.3.3 - Progress
  11231. * http://github.com/semantic-org/semantic-ui/
  11232. *
  11233. *
  11234. * Released under the MIT license
  11235. * http://opensource.org/licenses/MIT
  11236. *
  11237. */
  11238. ;(function ($, window, document, undefined) {
  11239. 'use strict';
  11240. window = (typeof window != 'undefined' && window.Math == Math)
  11241. ? window
  11242. : (typeof self != 'undefined' && self.Math == Math)
  11243. ? self
  11244. : Function('return this')()
  11245. ;
  11246. var
  11247. global = (typeof window != 'undefined' && window.Math == Math)
  11248. ? window
  11249. : (typeof self != 'undefined' && self.Math == Math)
  11250. ? self
  11251. : Function('return this')()
  11252. ;
  11253. $.fn.progress = function(parameters) {
  11254. var
  11255. $allModules = $(this),
  11256. moduleSelector = $allModules.selector || '',
  11257. time = new Date().getTime(),
  11258. performance = [],
  11259. query = arguments[0],
  11260. methodInvoked = (typeof query == 'string'),
  11261. queryArguments = [].slice.call(arguments, 1),
  11262. returnedValue
  11263. ;
  11264. $allModules
  11265. .each(function() {
  11266. var
  11267. settings = ( $.isPlainObject(parameters) )
  11268. ? $.extend(true, {}, $.fn.progress.settings, parameters)
  11269. : $.extend({}, $.fn.progress.settings),
  11270. className = settings.className,
  11271. metadata = settings.metadata,
  11272. namespace = settings.namespace,
  11273. selector = settings.selector,
  11274. error = settings.error,
  11275. eventNamespace = '.' + namespace,
  11276. moduleNamespace = 'module-' + namespace,
  11277. $module = $(this),
  11278. $bar = $(this).find(selector.bar),
  11279. $progress = $(this).find(selector.progress),
  11280. $label = $(this).find(selector.label),
  11281. element = this,
  11282. instance = $module.data(moduleNamespace),
  11283. animating = false,
  11284. transitionEnd,
  11285. module
  11286. ;
  11287. module = {
  11288. initialize: function() {
  11289. module.debug('Initializing progress bar', settings);
  11290. module.set.duration();
  11291. module.set.transitionEvent();
  11292. module.read.metadata();
  11293. module.read.settings();
  11294. module.instantiate();
  11295. },
  11296. instantiate: function() {
  11297. module.verbose('Storing instance of progress', module);
  11298. instance = module;
  11299. $module
  11300. .data(moduleNamespace, module)
  11301. ;
  11302. },
  11303. destroy: function() {
  11304. module.verbose('Destroying previous progress for', $module);
  11305. clearInterval(instance.interval);
  11306. module.remove.state();
  11307. $module.removeData(moduleNamespace);
  11308. instance = undefined;
  11309. },
  11310. reset: function() {
  11311. module.remove.nextValue();
  11312. module.update.progress(0);
  11313. },
  11314. complete: function() {
  11315. if(module.percent === undefined || module.percent < 100) {
  11316. module.remove.progressPoll();
  11317. module.set.percent(100);
  11318. }
  11319. },
  11320. read: {
  11321. metadata: function() {
  11322. var
  11323. data = {
  11324. percent : $module.data(metadata.percent),
  11325. total : $module.data(metadata.total),
  11326. value : $module.data(metadata.value)
  11327. }
  11328. ;
  11329. if(data.percent) {
  11330. module.debug('Current percent value set from metadata', data.percent);
  11331. module.set.percent(data.percent);
  11332. }
  11333. if(data.total) {
  11334. module.debug('Total value set from metadata', data.total);
  11335. module.set.total(data.total);
  11336. }
  11337. if(data.value) {
  11338. module.debug('Current value set from metadata', data.value);
  11339. module.set.value(data.value);
  11340. module.set.progress(data.value);
  11341. }
  11342. },
  11343. settings: function() {
  11344. if(settings.total !== false) {
  11345. module.debug('Current total set in settings', settings.total);
  11346. module.set.total(settings.total);
  11347. }
  11348. if(settings.value !== false) {
  11349. module.debug('Current value set in settings', settings.value);
  11350. module.set.value(settings.value);
  11351. module.set.progress(module.value);
  11352. }
  11353. if(settings.percent !== false) {
  11354. module.debug('Current percent set in settings', settings.percent);
  11355. module.set.percent(settings.percent);
  11356. }
  11357. }
  11358. },
  11359. bind: {
  11360. transitionEnd: function(callback) {
  11361. var
  11362. transitionEnd = module.get.transitionEnd()
  11363. ;
  11364. $bar
  11365. .one(transitionEnd + eventNamespace, function(event) {
  11366. clearTimeout(module.failSafeTimer);
  11367. callback.call(this, event);
  11368. })
  11369. ;
  11370. module.failSafeTimer = setTimeout(function() {
  11371. $bar.triggerHandler(transitionEnd);
  11372. }, settings.duration + settings.failSafeDelay);
  11373. module.verbose('Adding fail safe timer', module.timer);
  11374. }
  11375. },
  11376. increment: function(incrementValue) {
  11377. var
  11378. maxValue,
  11379. startValue,
  11380. newValue
  11381. ;
  11382. if( module.has.total() ) {
  11383. startValue = module.get.value();
  11384. incrementValue = incrementValue || 1;
  11385. newValue = startValue + incrementValue;
  11386. }
  11387. else {
  11388. startValue = module.get.percent();
  11389. incrementValue = incrementValue || module.get.randomValue();
  11390. newValue = startValue + incrementValue;
  11391. maxValue = 100;
  11392. module.debug('Incrementing percentage by', startValue, newValue);
  11393. }
  11394. newValue = module.get.normalizedValue(newValue);
  11395. module.set.progress(newValue);
  11396. },
  11397. decrement: function(decrementValue) {
  11398. var
  11399. total = module.get.total(),
  11400. startValue,
  11401. newValue
  11402. ;
  11403. if(total) {
  11404. startValue = module.get.value();
  11405. decrementValue = decrementValue || 1;
  11406. newValue = startValue - decrementValue;
  11407. module.debug('Decrementing value by', decrementValue, startValue);
  11408. }
  11409. else {
  11410. startValue = module.get.percent();
  11411. decrementValue = decrementValue || module.get.randomValue();
  11412. newValue = startValue - decrementValue;
  11413. module.debug('Decrementing percentage by', decrementValue, startValue);
  11414. }
  11415. newValue = module.get.normalizedValue(newValue);
  11416. module.set.progress(newValue);
  11417. },
  11418. has: {
  11419. progressPoll: function() {
  11420. return module.progressPoll;
  11421. },
  11422. total: function() {
  11423. return (module.get.total() !== false);
  11424. }
  11425. },
  11426. get: {
  11427. text: function(templateText) {
  11428. var
  11429. value = module.value || 0,
  11430. total = module.total || 0,
  11431. percent = (animating)
  11432. ? module.get.displayPercent()
  11433. : module.percent || 0,
  11434. left = (module.total > 0)
  11435. ? (total - value)
  11436. : (100 - percent)
  11437. ;
  11438. templateText = templateText || '';
  11439. templateText = templateText
  11440. .replace('{value}', value)
  11441. .replace('{total}', total)
  11442. .replace('{left}', left)
  11443. .replace('{percent}', percent)
  11444. ;
  11445. module.verbose('Adding variables to progress bar text', templateText);
  11446. return templateText;
  11447. },
  11448. normalizedValue: function(value) {
  11449. if(value < 0) {
  11450. module.debug('Value cannot decrement below 0');
  11451. return 0;
  11452. }
  11453. if(module.has.total()) {
  11454. if(value > module.total) {
  11455. module.debug('Value cannot increment above total', module.total);
  11456. return module.total;
  11457. }
  11458. }
  11459. else if(value > 100 ) {
  11460. module.debug('Value cannot increment above 100 percent');
  11461. return 100;
  11462. }
  11463. return value;
  11464. },
  11465. updateInterval: function() {
  11466. if(settings.updateInterval == 'auto') {
  11467. return settings.duration;
  11468. }
  11469. return settings.updateInterval;
  11470. },
  11471. randomValue: function() {
  11472. module.debug('Generating random increment percentage');
  11473. return Math.floor((Math.random() * settings.random.max) + settings.random.min);
  11474. },
  11475. numericValue: function(value) {
  11476. return (typeof value === 'string')
  11477. ? (value.replace(/[^\d.]/g, '') !== '')
  11478. ? +(value.replace(/[^\d.]/g, ''))
  11479. : false
  11480. : value
  11481. ;
  11482. },
  11483. transitionEnd: function() {
  11484. var
  11485. element = document.createElement('element'),
  11486. transitions = {
  11487. 'transition' :'transitionend',
  11488. 'OTransition' :'oTransitionEnd',
  11489. 'MozTransition' :'transitionend',
  11490. 'WebkitTransition' :'webkitTransitionEnd'
  11491. },
  11492. transition
  11493. ;
  11494. for(transition in transitions){
  11495. if( element.style[transition] !== undefined ){
  11496. return transitions[transition];
  11497. }
  11498. }
  11499. },
  11500. // gets current displayed percentage (if animating values this is the intermediary value)
  11501. displayPercent: function() {
  11502. var
  11503. barWidth = $bar.width(),
  11504. totalWidth = $module.width(),
  11505. minDisplay = parseInt($bar.css('min-width'), 10),
  11506. displayPercent = (barWidth > minDisplay)
  11507. ? (barWidth / totalWidth * 100)
  11508. : module.percent
  11509. ;
  11510. return (settings.precision > 0)
  11511. ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
  11512. : Math.round(displayPercent)
  11513. ;
  11514. },
  11515. percent: function() {
  11516. return module.percent || 0;
  11517. },
  11518. value: function() {
  11519. return module.nextValue || module.value || 0;
  11520. },
  11521. total: function() {
  11522. return module.total || false;
  11523. }
  11524. },
  11525. create: {
  11526. progressPoll: function() {
  11527. module.progressPoll = setTimeout(function() {
  11528. module.update.toNextValue();
  11529. module.remove.progressPoll();
  11530. }, module.get.updateInterval());
  11531. },
  11532. },
  11533. is: {
  11534. complete: function() {
  11535. return module.is.success() || module.is.warning() || module.is.error();
  11536. },
  11537. success: function() {
  11538. return $module.hasClass(className.success);
  11539. },
  11540. warning: function() {
  11541. return $module.hasClass(className.warning);
  11542. },
  11543. error: function() {
  11544. return $module.hasClass(className.error);
  11545. },
  11546. active: function() {
  11547. return $module.hasClass(className.active);
  11548. },
  11549. visible: function() {
  11550. return $module.is(':visible');
  11551. }
  11552. },
  11553. remove: {
  11554. progressPoll: function() {
  11555. module.verbose('Removing progress poll timer');
  11556. if(module.progressPoll) {
  11557. clearTimeout(module.progressPoll);
  11558. delete module.progressPoll;
  11559. }
  11560. },
  11561. nextValue: function() {
  11562. module.verbose('Removing progress value stored for next update');
  11563. delete module.nextValue;
  11564. },
  11565. state: function() {
  11566. module.verbose('Removing stored state');
  11567. delete module.total;
  11568. delete module.percent;
  11569. delete module.value;
  11570. },
  11571. active: function() {
  11572. module.verbose('Removing active state');
  11573. $module.removeClass(className.active);
  11574. },
  11575. success: function() {
  11576. module.verbose('Removing success state');
  11577. $module.removeClass(className.success);
  11578. },
  11579. warning: function() {
  11580. module.verbose('Removing warning state');
  11581. $module.removeClass(className.warning);
  11582. },
  11583. error: function() {
  11584. module.verbose('Removing error state');
  11585. $module.removeClass(className.error);
  11586. }
  11587. },
  11588. set: {
  11589. barWidth: function(value) {
  11590. if(value > 100) {
  11591. module.error(error.tooHigh, value);
  11592. }
  11593. else if (value < 0) {
  11594. module.error(error.tooLow, value);
  11595. }
  11596. else {
  11597. $bar
  11598. .css('width', value + '%')
  11599. ;
  11600. $module
  11601. .attr('data-percent', parseInt(value, 10))
  11602. ;
  11603. }
  11604. },
  11605. duration: function(duration) {
  11606. duration = duration || settings.duration;
  11607. duration = (typeof duration == 'number')
  11608. ? duration + 'ms'
  11609. : duration
  11610. ;
  11611. module.verbose('Setting progress bar transition duration', duration);
  11612. $bar
  11613. .css({
  11614. 'transition-duration': duration
  11615. })
  11616. ;
  11617. },
  11618. percent: function(percent) {
  11619. percent = (typeof percent == 'string')
  11620. ? +(percent.replace('%', ''))
  11621. : percent
  11622. ;
  11623. // round display percentage
  11624. percent = (settings.precision > 0)
  11625. ? Math.round(percent * (10 * settings.precision)) / (10 * settings.precision)
  11626. : Math.round(percent)
  11627. ;
  11628. module.percent = percent;
  11629. if( !module.has.total() ) {
  11630. module.value = (settings.precision > 0)
  11631. ? Math.round( (percent / 100) * module.total * (10 * settings.precision)) / (10 * settings.precision)
  11632. : Math.round( (percent / 100) * module.total * 10) / 10
  11633. ;
  11634. if(settings.limitValues) {
  11635. module.value = (module.value > 100)
  11636. ? 100
  11637. : (module.value < 0)
  11638. ? 0
  11639. : module.value
  11640. ;
  11641. }
  11642. }
  11643. module.set.barWidth(percent);
  11644. module.set.labelInterval();
  11645. module.set.labels();
  11646. settings.onChange.call(element, percent, module.value, module.total);
  11647. },
  11648. labelInterval: function() {
  11649. var
  11650. animationCallback = function() {
  11651. module.verbose('Bar finished animating, removing continuous label updates');
  11652. clearInterval(module.interval);
  11653. animating = false;
  11654. module.set.labels();
  11655. }
  11656. ;
  11657. clearInterval(module.interval);
  11658. module.bind.transitionEnd(animationCallback);
  11659. animating = true;
  11660. module.interval = setInterval(function() {
  11661. var
  11662. isInDOM = $.contains(document.documentElement, element)
  11663. ;
  11664. if(!isInDOM) {
  11665. clearInterval(module.interval);
  11666. animating = false;
  11667. }
  11668. module.set.labels();
  11669. }, settings.framerate);
  11670. },
  11671. labels: function() {
  11672. module.verbose('Setting both bar progress and outer label text');
  11673. module.set.barLabel();
  11674. module.set.state();
  11675. },
  11676. label: function(text) {
  11677. text = text || '';
  11678. if(text) {
  11679. text = module.get.text(text);
  11680. module.verbose('Setting label to text', text);
  11681. $label.text(text);
  11682. }
  11683. },
  11684. state: function(percent) {
  11685. percent = (percent !== undefined)
  11686. ? percent
  11687. : module.percent
  11688. ;
  11689. if(percent === 100) {
  11690. if(settings.autoSuccess && !(module.is.warning() || module.is.error() || module.is.success())) {
  11691. module.set.success();
  11692. module.debug('Automatically triggering success at 100%');
  11693. }
  11694. else {
  11695. module.verbose('Reached 100% removing active state');
  11696. module.remove.active();
  11697. module.remove.progressPoll();
  11698. }
  11699. }
  11700. else if(percent > 0) {
  11701. module.verbose('Adjusting active progress bar label', percent);
  11702. module.set.active();
  11703. }
  11704. else {
  11705. module.remove.active();
  11706. module.set.label(settings.text.active);
  11707. }
  11708. },
  11709. barLabel: function(text) {
  11710. if(text !== undefined) {
  11711. $progress.text( module.get.text(text) );
  11712. }
  11713. else if(settings.label == 'ratio' && module.total) {
  11714. module.verbose('Adding ratio to bar label');
  11715. $progress.text( module.get.text(settings.text.ratio) );
  11716. }
  11717. else if(settings.label == 'percent') {
  11718. module.verbose('Adding percentage to bar label');
  11719. $progress.text( module.get.text(settings.text.percent) );
  11720. }
  11721. },
  11722. active: function(text) {
  11723. text = text || settings.text.active;
  11724. module.debug('Setting active state');
  11725. if(settings.showActivity && !module.is.active() ) {
  11726. $module.addClass(className.active);
  11727. }
  11728. module.remove.warning();
  11729. module.remove.error();
  11730. module.remove.success();
  11731. text = settings.onLabelUpdate('active', text, module.value, module.total);
  11732. if(text) {
  11733. module.set.label(text);
  11734. }
  11735. module.bind.transitionEnd(function() {
  11736. settings.onActive.call(element, module.value, module.total);
  11737. });
  11738. },
  11739. success : function(text) {
  11740. text = text || settings.text.success || settings.text.active;
  11741. module.debug('Setting success state');
  11742. $module.addClass(className.success);
  11743. module.remove.active();
  11744. module.remove.warning();
  11745. module.remove.error();
  11746. module.complete();
  11747. if(settings.text.success) {
  11748. text = settings.onLabelUpdate('success', text, module.value, module.total);
  11749. module.set.label(text);
  11750. }
  11751. else {
  11752. text = settings.onLabelUpdate('active', text, module.value, module.total);
  11753. module.set.label(text);
  11754. }
  11755. module.bind.transitionEnd(function() {
  11756. settings.onSuccess.call(element, module.total);
  11757. });
  11758. },
  11759. warning : function(text) {
  11760. text = text || settings.text.warning;
  11761. module.debug('Setting warning state');
  11762. $module.addClass(className.warning);
  11763. module.remove.active();
  11764. module.remove.success();
  11765. module.remove.error();
  11766. module.complete();
  11767. text = settings.onLabelUpdate('warning', text, module.value, module.total);
  11768. if(text) {
  11769. module.set.label(text);
  11770. }
  11771. module.bind.transitionEnd(function() {
  11772. settings.onWarning.call(element, module.value, module.total);
  11773. });
  11774. },
  11775. error : function(text) {
  11776. text = text || settings.text.error;
  11777. module.debug('Setting error state');
  11778. $module.addClass(className.error);
  11779. module.remove.active();
  11780. module.remove.success();
  11781. module.remove.warning();
  11782. module.complete();
  11783. text = settings.onLabelUpdate('error', text, module.value, module.total);
  11784. if(text) {
  11785. module.set.label(text);
  11786. }
  11787. module.bind.transitionEnd(function() {
  11788. settings.onError.call(element, module.value, module.total);
  11789. });
  11790. },
  11791. transitionEvent: function() {
  11792. transitionEnd = module.get.transitionEnd();
  11793. },
  11794. total: function(totalValue) {
  11795. module.total = totalValue;
  11796. },
  11797. value: function(value) {
  11798. module.value = value;
  11799. },
  11800. progress: function(value) {
  11801. if(!module.has.progressPoll()) {
  11802. module.debug('First update in progress update interval, immediately updating', value);
  11803. module.update.progress(value);
  11804. module.create.progressPoll();
  11805. }
  11806. else {
  11807. module.debug('Updated within interval, setting next update to use new value', value);
  11808. module.set.nextValue(value);
  11809. }
  11810. },
  11811. nextValue: function(value) {
  11812. module.nextValue = value;
  11813. }
  11814. },
  11815. update: {
  11816. toNextValue: function() {
  11817. var
  11818. nextValue = module.nextValue
  11819. ;
  11820. if(nextValue) {
  11821. module.debug('Update interval complete using last updated value', nextValue);
  11822. module.update.progress(nextValue);
  11823. module.remove.nextValue();
  11824. }
  11825. },
  11826. progress: function(value) {
  11827. var
  11828. percentComplete
  11829. ;
  11830. value = module.get.numericValue(value);
  11831. if(value === false) {
  11832. module.error(error.nonNumeric, value);
  11833. }
  11834. value = module.get.normalizedValue(value);
  11835. if( module.has.total() ) {
  11836. module.set.value(value);
  11837. percentComplete = (value / module.total) * 100;
  11838. module.debug('Calculating percent complete from total', percentComplete);
  11839. module.set.percent( percentComplete );
  11840. }
  11841. else {
  11842. percentComplete = value;
  11843. module.debug('Setting value to exact percentage value', percentComplete);
  11844. module.set.percent( percentComplete );
  11845. }
  11846. }
  11847. },
  11848. setting: function(name, value) {
  11849. module.debug('Changing setting', name, value);
  11850. if( $.isPlainObject(name) ) {
  11851. $.extend(true, settings, name);
  11852. }
  11853. else if(value !== undefined) {
  11854. if($.isPlainObject(settings[name])) {
  11855. $.extend(true, settings[name], value);
  11856. }
  11857. else {
  11858. settings[name] = value;
  11859. }
  11860. }
  11861. else {
  11862. return settings[name];
  11863. }
  11864. },
  11865. internal: function(name, value) {
  11866. if( $.isPlainObject(name) ) {
  11867. $.extend(true, module, name);
  11868. }
  11869. else if(value !== undefined) {
  11870. module[name] = value;
  11871. }
  11872. else {
  11873. return module[name];
  11874. }
  11875. },
  11876. debug: function() {
  11877. if(!settings.silent && settings.debug) {
  11878. if(settings.performance) {
  11879. module.performance.log(arguments);
  11880. }
  11881. else {
  11882. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11883. module.debug.apply(console, arguments);
  11884. }
  11885. }
  11886. },
  11887. verbose: function() {
  11888. if(!settings.silent && settings.verbose && settings.debug) {
  11889. if(settings.performance) {
  11890. module.performance.log(arguments);
  11891. }
  11892. else {
  11893. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11894. module.verbose.apply(console, arguments);
  11895. }
  11896. }
  11897. },
  11898. error: function() {
  11899. if(!settings.silent) {
  11900. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  11901. module.error.apply(console, arguments);
  11902. }
  11903. },
  11904. performance: {
  11905. log: function(message) {
  11906. var
  11907. currentTime,
  11908. executionTime,
  11909. previousTime
  11910. ;
  11911. if(settings.performance) {
  11912. currentTime = new Date().getTime();
  11913. previousTime = time || currentTime;
  11914. executionTime = currentTime - previousTime;
  11915. time = currentTime;
  11916. performance.push({
  11917. 'Name' : message[0],
  11918. 'Arguments' : [].slice.call(message, 1) || '',
  11919. 'Element' : element,
  11920. 'Execution Time' : executionTime
  11921. });
  11922. }
  11923. clearTimeout(module.performance.timer);
  11924. module.performance.timer = setTimeout(module.performance.display, 500);
  11925. },
  11926. display: function() {
  11927. var
  11928. title = settings.name + ':',
  11929. totalTime = 0
  11930. ;
  11931. time = false;
  11932. clearTimeout(module.performance.timer);
  11933. $.each(performance, function(index, data) {
  11934. totalTime += data['Execution Time'];
  11935. });
  11936. title += ' ' + totalTime + 'ms';
  11937. if(moduleSelector) {
  11938. title += ' \'' + moduleSelector + '\'';
  11939. }
  11940. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  11941. console.groupCollapsed(title);
  11942. if(console.table) {
  11943. console.table(performance);
  11944. }
  11945. else {
  11946. $.each(performance, function(index, data) {
  11947. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  11948. });
  11949. }
  11950. console.groupEnd();
  11951. }
  11952. performance = [];
  11953. }
  11954. },
  11955. invoke: function(query, passedArguments, context) {
  11956. var
  11957. object = instance,
  11958. maxDepth,
  11959. found,
  11960. response
  11961. ;
  11962. passedArguments = passedArguments || queryArguments;
  11963. context = element || context;
  11964. if(typeof query == 'string' && object !== undefined) {
  11965. query = query.split(/[\. ]/);
  11966. maxDepth = query.length - 1;
  11967. $.each(query, function(depth, value) {
  11968. var camelCaseValue = (depth != maxDepth)
  11969. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  11970. : query
  11971. ;
  11972. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  11973. object = object[camelCaseValue];
  11974. }
  11975. else if( object[camelCaseValue] !== undefined ) {
  11976. found = object[camelCaseValue];
  11977. return false;
  11978. }
  11979. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  11980. object = object[value];
  11981. }
  11982. else if( object[value] !== undefined ) {
  11983. found = object[value];
  11984. return false;
  11985. }
  11986. else {
  11987. module.error(error.method, query);
  11988. return false;
  11989. }
  11990. });
  11991. }
  11992. if ( $.isFunction( found ) ) {
  11993. response = found.apply(context, passedArguments);
  11994. }
  11995. else if(found !== undefined) {
  11996. response = found;
  11997. }
  11998. if($.isArray(returnedValue)) {
  11999. returnedValue.push(response);
  12000. }
  12001. else if(returnedValue !== undefined) {
  12002. returnedValue = [returnedValue, response];
  12003. }
  12004. else if(response !== undefined) {
  12005. returnedValue = response;
  12006. }
  12007. return found;
  12008. }
  12009. };
  12010. if(methodInvoked) {
  12011. if(instance === undefined) {
  12012. module.initialize();
  12013. }
  12014. module.invoke(query);
  12015. }
  12016. else {
  12017. if(instance !== undefined) {
  12018. instance.invoke('destroy');
  12019. }
  12020. module.initialize();
  12021. }
  12022. })
  12023. ;
  12024. return (returnedValue !== undefined)
  12025. ? returnedValue
  12026. : this
  12027. ;
  12028. };
  12029. $.fn.progress.settings = {
  12030. name : 'Progress',
  12031. namespace : 'progress',
  12032. silent : false,
  12033. debug : false,
  12034. verbose : false,
  12035. performance : true,
  12036. random : {
  12037. min : 2,
  12038. max : 5
  12039. },
  12040. duration : 300,
  12041. updateInterval : 'auto',
  12042. autoSuccess : true,
  12043. showActivity : true,
  12044. limitValues : true,
  12045. label : 'percent',
  12046. precision : 0,
  12047. framerate : (1000 / 30), /// 30 fps
  12048. percent : false,
  12049. total : false,
  12050. value : false,
  12051. // delay in ms for fail safe animation callback
  12052. failSafeDelay : 100,
  12053. onLabelUpdate : function(state, text, value, total){
  12054. return text;
  12055. },
  12056. onChange : function(percent, value, total){},
  12057. onSuccess : function(total){},
  12058. onActive : function(value, total){},
  12059. onError : function(value, total){},
  12060. onWarning : function(value, total){},
  12061. error : {
  12062. method : 'The method you called is not defined.',
  12063. nonNumeric : 'Progress value is non numeric',
  12064. tooHigh : 'Value specified is above 100%',
  12065. tooLow : 'Value specified is below 0%'
  12066. },
  12067. regExp: {
  12068. variable: /\{\$*[A-z0-9]+\}/g
  12069. },
  12070. metadata: {
  12071. percent : 'percent',
  12072. total : 'total',
  12073. value : 'value'
  12074. },
  12075. selector : {
  12076. bar : '> .bar',
  12077. label : '> .label',
  12078. progress : '.bar > .progress'
  12079. },
  12080. text : {
  12081. active : false,
  12082. error : false,
  12083. success : false,
  12084. warning : false,
  12085. percent : '{percent}%',
  12086. ratio : '{value} of {total}'
  12087. },
  12088. className : {
  12089. active : 'active',
  12090. error : 'error',
  12091. success : 'success',
  12092. warning : 'warning'
  12093. }
  12094. };
  12095. })( jQuery, window, document );
  12096. /*!
  12097. * # Semantic UI 2.3.3 - Rating
  12098. * http://github.com/semantic-org/semantic-ui/
  12099. *
  12100. *
  12101. * Released under the MIT license
  12102. * http://opensource.org/licenses/MIT
  12103. *
  12104. */
  12105. ;(function ($, window, document, undefined) {
  12106. 'use strict';
  12107. window = (typeof window != 'undefined' && window.Math == Math)
  12108. ? window
  12109. : (typeof self != 'undefined' && self.Math == Math)
  12110. ? self
  12111. : Function('return this')()
  12112. ;
  12113. $.fn.rating = function(parameters) {
  12114. var
  12115. $allModules = $(this),
  12116. moduleSelector = $allModules.selector || '',
  12117. time = new Date().getTime(),
  12118. performance = [],
  12119. query = arguments[0],
  12120. methodInvoked = (typeof query == 'string'),
  12121. queryArguments = [].slice.call(arguments, 1),
  12122. returnedValue
  12123. ;
  12124. $allModules
  12125. .each(function() {
  12126. var
  12127. settings = ( $.isPlainObject(parameters) )
  12128. ? $.extend(true, {}, $.fn.rating.settings, parameters)
  12129. : $.extend({}, $.fn.rating.settings),
  12130. namespace = settings.namespace,
  12131. className = settings.className,
  12132. metadata = settings.metadata,
  12133. selector = settings.selector,
  12134. error = settings.error,
  12135. eventNamespace = '.' + namespace,
  12136. moduleNamespace = 'module-' + namespace,
  12137. element = this,
  12138. instance = $(this).data(moduleNamespace),
  12139. $module = $(this),
  12140. $icon = $module.find(selector.icon),
  12141. initialLoad,
  12142. module
  12143. ;
  12144. module = {
  12145. initialize: function() {
  12146. module.verbose('Initializing rating module', settings);
  12147. if($icon.length === 0) {
  12148. module.setup.layout();
  12149. }
  12150. if(settings.interactive) {
  12151. module.enable();
  12152. }
  12153. else {
  12154. module.disable();
  12155. }
  12156. module.set.initialLoad();
  12157. module.set.rating( module.get.initialRating() );
  12158. module.remove.initialLoad();
  12159. module.instantiate();
  12160. },
  12161. instantiate: function() {
  12162. module.verbose('Instantiating module', settings);
  12163. instance = module;
  12164. $module
  12165. .data(moduleNamespace, module)
  12166. ;
  12167. },
  12168. destroy: function() {
  12169. module.verbose('Destroying previous instance', instance);
  12170. module.remove.events();
  12171. $module
  12172. .removeData(moduleNamespace)
  12173. ;
  12174. },
  12175. refresh: function() {
  12176. $icon = $module.find(selector.icon);
  12177. },
  12178. setup: {
  12179. layout: function() {
  12180. var
  12181. maxRating = module.get.maxRating(),
  12182. html = $.fn.rating.settings.templates.icon(maxRating)
  12183. ;
  12184. module.debug('Generating icon html dynamically');
  12185. $module
  12186. .html(html)
  12187. ;
  12188. module.refresh();
  12189. }
  12190. },
  12191. event: {
  12192. mouseenter: function() {
  12193. var
  12194. $activeIcon = $(this)
  12195. ;
  12196. $activeIcon
  12197. .nextAll()
  12198. .removeClass(className.selected)
  12199. ;
  12200. $module
  12201. .addClass(className.selected)
  12202. ;
  12203. $activeIcon
  12204. .addClass(className.selected)
  12205. .prevAll()
  12206. .addClass(className.selected)
  12207. ;
  12208. },
  12209. mouseleave: function() {
  12210. $module
  12211. .removeClass(className.selected)
  12212. ;
  12213. $icon
  12214. .removeClass(className.selected)
  12215. ;
  12216. },
  12217. click: function() {
  12218. var
  12219. $activeIcon = $(this),
  12220. currentRating = module.get.rating(),
  12221. rating = $icon.index($activeIcon) + 1,
  12222. canClear = (settings.clearable == 'auto')
  12223. ? ($icon.length === 1)
  12224. : settings.clearable
  12225. ;
  12226. if(canClear && currentRating == rating) {
  12227. module.clearRating();
  12228. }
  12229. else {
  12230. module.set.rating( rating );
  12231. }
  12232. }
  12233. },
  12234. clearRating: function() {
  12235. module.debug('Clearing current rating');
  12236. module.set.rating(0);
  12237. },
  12238. bind: {
  12239. events: function() {
  12240. module.verbose('Binding events');
  12241. $module
  12242. .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
  12243. .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
  12244. .on('click' + eventNamespace, selector.icon, module.event.click)
  12245. ;
  12246. }
  12247. },
  12248. remove: {
  12249. events: function() {
  12250. module.verbose('Removing events');
  12251. $module
  12252. .off(eventNamespace)
  12253. ;
  12254. },
  12255. initialLoad: function() {
  12256. initialLoad = false;
  12257. }
  12258. },
  12259. enable: function() {
  12260. module.debug('Setting rating to interactive mode');
  12261. module.bind.events();
  12262. $module
  12263. .removeClass(className.disabled)
  12264. ;
  12265. },
  12266. disable: function() {
  12267. module.debug('Setting rating to read-only mode');
  12268. module.remove.events();
  12269. $module
  12270. .addClass(className.disabled)
  12271. ;
  12272. },
  12273. is: {
  12274. initialLoad: function() {
  12275. return initialLoad;
  12276. }
  12277. },
  12278. get: {
  12279. initialRating: function() {
  12280. if($module.data(metadata.rating) !== undefined) {
  12281. $module.removeData(metadata.rating);
  12282. return $module.data(metadata.rating);
  12283. }
  12284. return settings.initialRating;
  12285. },
  12286. maxRating: function() {
  12287. if($module.data(metadata.maxRating) !== undefined) {
  12288. $module.removeData(metadata.maxRating);
  12289. return $module.data(metadata.maxRating);
  12290. }
  12291. return settings.maxRating;
  12292. },
  12293. rating: function() {
  12294. var
  12295. currentRating = $icon.filter('.' + className.active).length
  12296. ;
  12297. module.verbose('Current rating retrieved', currentRating);
  12298. return currentRating;
  12299. }
  12300. },
  12301. set: {
  12302. rating: function(rating) {
  12303. var
  12304. ratingIndex = (rating - 1 >= 0)
  12305. ? (rating - 1)
  12306. : 0,
  12307. $activeIcon = $icon.eq(ratingIndex)
  12308. ;
  12309. $module
  12310. .removeClass(className.selected)
  12311. ;
  12312. $icon
  12313. .removeClass(className.selected)
  12314. .removeClass(className.active)
  12315. ;
  12316. if(rating > 0) {
  12317. module.verbose('Setting current rating to', rating);
  12318. $activeIcon
  12319. .prevAll()
  12320. .addBack()
  12321. .addClass(className.active)
  12322. ;
  12323. }
  12324. if(!module.is.initialLoad()) {
  12325. settings.onRate.call(element, rating);
  12326. }
  12327. },
  12328. initialLoad: function() {
  12329. initialLoad = true;
  12330. }
  12331. },
  12332. setting: function(name, value) {
  12333. module.debug('Changing setting', name, value);
  12334. if( $.isPlainObject(name) ) {
  12335. $.extend(true, settings, name);
  12336. }
  12337. else if(value !== undefined) {
  12338. if($.isPlainObject(settings[name])) {
  12339. $.extend(true, settings[name], value);
  12340. }
  12341. else {
  12342. settings[name] = value;
  12343. }
  12344. }
  12345. else {
  12346. return settings[name];
  12347. }
  12348. },
  12349. internal: function(name, value) {
  12350. if( $.isPlainObject(name) ) {
  12351. $.extend(true, module, name);
  12352. }
  12353. else if(value !== undefined) {
  12354. module[name] = value;
  12355. }
  12356. else {
  12357. return module[name];
  12358. }
  12359. },
  12360. debug: function() {
  12361. if(!settings.silent && settings.debug) {
  12362. if(settings.performance) {
  12363. module.performance.log(arguments);
  12364. }
  12365. else {
  12366. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12367. module.debug.apply(console, arguments);
  12368. }
  12369. }
  12370. },
  12371. verbose: function() {
  12372. if(!settings.silent && settings.verbose && settings.debug) {
  12373. if(settings.performance) {
  12374. module.performance.log(arguments);
  12375. }
  12376. else {
  12377. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12378. module.verbose.apply(console, arguments);
  12379. }
  12380. }
  12381. },
  12382. error: function() {
  12383. if(!settings.silent) {
  12384. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  12385. module.error.apply(console, arguments);
  12386. }
  12387. },
  12388. performance: {
  12389. log: function(message) {
  12390. var
  12391. currentTime,
  12392. executionTime,
  12393. previousTime
  12394. ;
  12395. if(settings.performance) {
  12396. currentTime = new Date().getTime();
  12397. previousTime = time || currentTime;
  12398. executionTime = currentTime - previousTime;
  12399. time = currentTime;
  12400. performance.push({
  12401. 'Name' : message[0],
  12402. 'Arguments' : [].slice.call(message, 1) || '',
  12403. 'Element' : element,
  12404. 'Execution Time' : executionTime
  12405. });
  12406. }
  12407. clearTimeout(module.performance.timer);
  12408. module.performance.timer = setTimeout(module.performance.display, 500);
  12409. },
  12410. display: function() {
  12411. var
  12412. title = settings.name + ':',
  12413. totalTime = 0
  12414. ;
  12415. time = false;
  12416. clearTimeout(module.performance.timer);
  12417. $.each(performance, function(index, data) {
  12418. totalTime += data['Execution Time'];
  12419. });
  12420. title += ' ' + totalTime + 'ms';
  12421. if(moduleSelector) {
  12422. title += ' \'' + moduleSelector + '\'';
  12423. }
  12424. if($allModules.length > 1) {
  12425. title += ' ' + '(' + $allModules.length + ')';
  12426. }
  12427. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  12428. console.groupCollapsed(title);
  12429. if(console.table) {
  12430. console.table(performance);
  12431. }
  12432. else {
  12433. $.each(performance, function(index, data) {
  12434. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  12435. });
  12436. }
  12437. console.groupEnd();
  12438. }
  12439. performance = [];
  12440. }
  12441. },
  12442. invoke: function(query, passedArguments, context) {
  12443. var
  12444. object = instance,
  12445. maxDepth,
  12446. found,
  12447. response
  12448. ;
  12449. passedArguments = passedArguments || queryArguments;
  12450. context = element || context;
  12451. if(typeof query == 'string' && object !== undefined) {
  12452. query = query.split(/[\. ]/);
  12453. maxDepth = query.length - 1;
  12454. $.each(query, function(depth, value) {
  12455. var camelCaseValue = (depth != maxDepth)
  12456. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  12457. : query
  12458. ;
  12459. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  12460. object = object[camelCaseValue];
  12461. }
  12462. else if( object[camelCaseValue] !== undefined ) {
  12463. found = object[camelCaseValue];
  12464. return false;
  12465. }
  12466. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  12467. object = object[value];
  12468. }
  12469. else if( object[value] !== undefined ) {
  12470. found = object[value];
  12471. return false;
  12472. }
  12473. else {
  12474. return false;
  12475. }
  12476. });
  12477. }
  12478. if ( $.isFunction( found ) ) {
  12479. response = found.apply(context, passedArguments);
  12480. }
  12481. else if(found !== undefined) {
  12482. response = found;
  12483. }
  12484. if($.isArray(returnedValue)) {
  12485. returnedValue.push(response);
  12486. }
  12487. else if(returnedValue !== undefined) {
  12488. returnedValue = [returnedValue, response];
  12489. }
  12490. else if(response !== undefined) {
  12491. returnedValue = response;
  12492. }
  12493. return found;
  12494. }
  12495. };
  12496. if(methodInvoked) {
  12497. if(instance === undefined) {
  12498. module.initialize();
  12499. }
  12500. module.invoke(query);
  12501. }
  12502. else {
  12503. if(instance !== undefined) {
  12504. instance.invoke('destroy');
  12505. }
  12506. module.initialize();
  12507. }
  12508. })
  12509. ;
  12510. return (returnedValue !== undefined)
  12511. ? returnedValue
  12512. : this
  12513. ;
  12514. };
  12515. $.fn.rating.settings = {
  12516. name : 'Rating',
  12517. namespace : 'rating',
  12518. slent : false,
  12519. debug : false,
  12520. verbose : false,
  12521. performance : true,
  12522. initialRating : 0,
  12523. interactive : true,
  12524. maxRating : 4,
  12525. clearable : 'auto',
  12526. fireOnInit : false,
  12527. onRate : function(rating){},
  12528. error : {
  12529. method : 'The method you called is not defined',
  12530. noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
  12531. },
  12532. metadata: {
  12533. rating : 'rating',
  12534. maxRating : 'maxRating'
  12535. },
  12536. className : {
  12537. active : 'active',
  12538. disabled : 'disabled',
  12539. selected : 'selected',
  12540. loading : 'loading'
  12541. },
  12542. selector : {
  12543. icon : '.icon'
  12544. },
  12545. templates: {
  12546. icon: function(maxRating) {
  12547. var
  12548. icon = 1,
  12549. html = ''
  12550. ;
  12551. while(icon <= maxRating) {
  12552. html += '<i class="icon"></i>';
  12553. icon++;
  12554. }
  12555. return html;
  12556. }
  12557. }
  12558. };
  12559. })( jQuery, window, document );
  12560. /*!
  12561. * # Semantic UI 2.3.3 - Search
  12562. * http://github.com/semantic-org/semantic-ui/
  12563. *
  12564. *
  12565. * Released under the MIT license
  12566. * http://opensource.org/licenses/MIT
  12567. *
  12568. */
  12569. ;(function ($, window, document, undefined) {
  12570. 'use strict';
  12571. window = (typeof window != 'undefined' && window.Math == Math)
  12572. ? window
  12573. : (typeof self != 'undefined' && self.Math == Math)
  12574. ? self
  12575. : Function('return this')()
  12576. ;
  12577. $.fn.search = function(parameters) {
  12578. var
  12579. $allModules = $(this),
  12580. moduleSelector = $allModules.selector || '',
  12581. time = new Date().getTime(),
  12582. performance = [],
  12583. query = arguments[0],
  12584. methodInvoked = (typeof query == 'string'),
  12585. queryArguments = [].slice.call(arguments, 1),
  12586. returnedValue
  12587. ;
  12588. $(this)
  12589. .each(function() {
  12590. var
  12591. settings = ( $.isPlainObject(parameters) )
  12592. ? $.extend(true, {}, $.fn.search.settings, parameters)
  12593. : $.extend({}, $.fn.search.settings),
  12594. className = settings.className,
  12595. metadata = settings.metadata,
  12596. regExp = settings.regExp,
  12597. fields = settings.fields,
  12598. selector = settings.selector,
  12599. error = settings.error,
  12600. namespace = settings.namespace,
  12601. eventNamespace = '.' + namespace,
  12602. moduleNamespace = namespace + '-module',
  12603. $module = $(this),
  12604. $prompt = $module.find(selector.prompt),
  12605. $searchButton = $module.find(selector.searchButton),
  12606. $results = $module.find(selector.results),
  12607. $result = $module.find(selector.result),
  12608. $category = $module.find(selector.category),
  12609. element = this,
  12610. instance = $module.data(moduleNamespace),
  12611. disabledBubbled = false,
  12612. resultsDismissed = false,
  12613. module
  12614. ;
  12615. module = {
  12616. initialize: function() {
  12617. module.verbose('Initializing module');
  12618. module.get.settings();
  12619. module.determine.searchFields();
  12620. module.bind.events();
  12621. module.set.type();
  12622. module.create.results();
  12623. module.instantiate();
  12624. },
  12625. instantiate: function() {
  12626. module.verbose('Storing instance of module', module);
  12627. instance = module;
  12628. $module
  12629. .data(moduleNamespace, module)
  12630. ;
  12631. },
  12632. destroy: function() {
  12633. module.verbose('Destroying instance');
  12634. $module
  12635. .off(eventNamespace)
  12636. .removeData(moduleNamespace)
  12637. ;
  12638. },
  12639. refresh: function() {
  12640. module.debug('Refreshing selector cache');
  12641. $prompt = $module.find(selector.prompt);
  12642. $searchButton = $module.find(selector.searchButton);
  12643. $category = $module.find(selector.category);
  12644. $results = $module.find(selector.results);
  12645. $result = $module.find(selector.result);
  12646. },
  12647. refreshResults: function() {
  12648. $results = $module.find(selector.results);
  12649. $result = $module.find(selector.result);
  12650. },
  12651. bind: {
  12652. events: function() {
  12653. module.verbose('Binding events to search');
  12654. if(settings.automatic) {
  12655. $module
  12656. .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
  12657. ;
  12658. $prompt
  12659. .attr('autocomplete', 'off')
  12660. ;
  12661. }
  12662. $module
  12663. // prompt
  12664. .on('focus' + eventNamespace, selector.prompt, module.event.focus)
  12665. .on('blur' + eventNamespace, selector.prompt, module.event.blur)
  12666. .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
  12667. // search button
  12668. .on('click' + eventNamespace, selector.searchButton, module.query)
  12669. // results
  12670. .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
  12671. .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
  12672. .on('click' + eventNamespace, selector.result, module.event.result.click)
  12673. ;
  12674. }
  12675. },
  12676. determine: {
  12677. searchFields: function() {
  12678. // this makes sure $.extend does not add specified search fields to default fields
  12679. // this is the only setting which should not extend defaults
  12680. if(parameters && parameters.searchFields !== undefined) {
  12681. settings.searchFields = parameters.searchFields;
  12682. }
  12683. }
  12684. },
  12685. event: {
  12686. input: function() {
  12687. if(settings.searchDelay) {
  12688. clearTimeout(module.timer);
  12689. module.timer = setTimeout(function() {
  12690. if(module.is.focused()) {
  12691. module.query();
  12692. }
  12693. }, settings.searchDelay);
  12694. }
  12695. else {
  12696. module.query();
  12697. }
  12698. },
  12699. focus: function() {
  12700. module.set.focus();
  12701. if(settings.searchOnFocus && module.has.minimumCharacters() ) {
  12702. module.query(function() {
  12703. if(module.can.show() ) {
  12704. module.showResults();
  12705. }
  12706. });
  12707. }
  12708. },
  12709. blur: function(event) {
  12710. var
  12711. pageLostFocus = (document.activeElement === this),
  12712. callback = function() {
  12713. module.cancel.query();
  12714. module.remove.focus();
  12715. module.timer = setTimeout(module.hideResults, settings.hideDelay);
  12716. }
  12717. ;
  12718. if(pageLostFocus) {
  12719. return;
  12720. }
  12721. resultsDismissed = false;
  12722. if(module.resultsClicked) {
  12723. module.debug('Determining if user action caused search to close');
  12724. $module
  12725. .one('click.close' + eventNamespace, selector.results, function(event) {
  12726. if(module.is.inMessage(event) || disabledBubbled) {
  12727. $prompt.focus();
  12728. return;
  12729. }
  12730. disabledBubbled = false;
  12731. if( !module.is.animating() && !module.is.hidden()) {
  12732. callback();
  12733. }
  12734. })
  12735. ;
  12736. }
  12737. else {
  12738. module.debug('Input blurred without user action, closing results');
  12739. callback();
  12740. }
  12741. },
  12742. result: {
  12743. mousedown: function() {
  12744. module.resultsClicked = true;
  12745. },
  12746. mouseup: function() {
  12747. module.resultsClicked = false;
  12748. },
  12749. click: function(event) {
  12750. module.debug('Search result selected');
  12751. var
  12752. $result = $(this),
  12753. $title = $result.find(selector.title).eq(0),
  12754. $link = $result.is('a[href]')
  12755. ? $result
  12756. : $result.find('a[href]').eq(0),
  12757. href = $link.attr('href') || false,
  12758. target = $link.attr('target') || false,
  12759. title = $title.html(),
  12760. // title is used for result lookup
  12761. value = ($title.length > 0)
  12762. ? $title.text()
  12763. : false,
  12764. results = module.get.results(),
  12765. result = $result.data(metadata.result) || module.get.result(value, results),
  12766. returnedValue
  12767. ;
  12768. if( $.isFunction(settings.onSelect) ) {
  12769. if(settings.onSelect.call(element, result, results) === false) {
  12770. module.debug('Custom onSelect callback cancelled default select action');
  12771. disabledBubbled = true;
  12772. return;
  12773. }
  12774. }
  12775. module.hideResults();
  12776. if(value) {
  12777. module.set.value(value);
  12778. }
  12779. if(href) {
  12780. module.verbose('Opening search link found in result', $link);
  12781. if(target == '_blank' || event.ctrlKey) {
  12782. window.open(href);
  12783. }
  12784. else {
  12785. window.location.href = (href);
  12786. }
  12787. }
  12788. }
  12789. }
  12790. },
  12791. handleKeyboard: function(event) {
  12792. var
  12793. // force selector refresh
  12794. $result = $module.find(selector.result),
  12795. $category = $module.find(selector.category),
  12796. $activeResult = $result.filter('.' + className.active),
  12797. currentIndex = $result.index( $activeResult ),
  12798. resultSize = $result.length,
  12799. hasActiveResult = $activeResult.length > 0,
  12800. keyCode = event.which,
  12801. keys = {
  12802. backspace : 8,
  12803. enter : 13,
  12804. escape : 27,
  12805. upArrow : 38,
  12806. downArrow : 40
  12807. },
  12808. newIndex
  12809. ;
  12810. // search shortcuts
  12811. if(keyCode == keys.escape) {
  12812. module.verbose('Escape key pressed, blurring search field');
  12813. module.hideResults();
  12814. resultsDismissed = true;
  12815. }
  12816. if( module.is.visible() ) {
  12817. if(keyCode == keys.enter) {
  12818. module.verbose('Enter key pressed, selecting active result');
  12819. if( $result.filter('.' + className.active).length > 0 ) {
  12820. module.event.result.click.call($result.filter('.' + className.active), event);
  12821. event.preventDefault();
  12822. return false;
  12823. }
  12824. }
  12825. else if(keyCode == keys.upArrow && hasActiveResult) {
  12826. module.verbose('Up key pressed, changing active result');
  12827. newIndex = (currentIndex - 1 < 0)
  12828. ? currentIndex
  12829. : currentIndex - 1
  12830. ;
  12831. $category
  12832. .removeClass(className.active)
  12833. ;
  12834. $result
  12835. .removeClass(className.active)
  12836. .eq(newIndex)
  12837. .addClass(className.active)
  12838. .closest($category)
  12839. .addClass(className.active)
  12840. ;
  12841. event.preventDefault();
  12842. }
  12843. else if(keyCode == keys.downArrow) {
  12844. module.verbose('Down key pressed, changing active result');
  12845. newIndex = (currentIndex + 1 >= resultSize)
  12846. ? currentIndex
  12847. : currentIndex + 1
  12848. ;
  12849. $category
  12850. .removeClass(className.active)
  12851. ;
  12852. $result
  12853. .removeClass(className.active)
  12854. .eq(newIndex)
  12855. .addClass(className.active)
  12856. .closest($category)
  12857. .addClass(className.active)
  12858. ;
  12859. event.preventDefault();
  12860. }
  12861. }
  12862. else {
  12863. // query shortcuts
  12864. if(keyCode == keys.enter) {
  12865. module.verbose('Enter key pressed, executing query');
  12866. module.query();
  12867. module.set.buttonPressed();
  12868. $prompt.one('keyup', module.remove.buttonFocus);
  12869. }
  12870. }
  12871. },
  12872. setup: {
  12873. api: function(searchTerm, callback) {
  12874. var
  12875. apiSettings = {
  12876. debug : settings.debug,
  12877. on : false,
  12878. cache : settings.cache,
  12879. action : 'search',
  12880. urlData : {
  12881. query : searchTerm
  12882. },
  12883. onSuccess : function(response) {
  12884. module.parse.response.call(element, response, searchTerm);
  12885. callback();
  12886. },
  12887. onFailure : function() {
  12888. module.displayMessage(error.serverError);
  12889. callback();
  12890. },
  12891. onAbort : function(response) {
  12892. },
  12893. onError : module.error
  12894. },
  12895. searchHTML
  12896. ;
  12897. $.extend(true, apiSettings, settings.apiSettings);
  12898. module.verbose('Setting up API request', apiSettings);
  12899. $module.api(apiSettings);
  12900. }
  12901. },
  12902. can: {
  12903. useAPI: function() {
  12904. return $.fn.api !== undefined;
  12905. },
  12906. show: function() {
  12907. return module.is.focused() && !module.is.visible() && !module.is.empty();
  12908. },
  12909. transition: function() {
  12910. return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
  12911. }
  12912. },
  12913. is: {
  12914. animating: function() {
  12915. return $results.hasClass(className.animating);
  12916. },
  12917. hidden: function() {
  12918. return $results.hasClass(className.hidden);
  12919. },
  12920. inMessage: function(event) {
  12921. if(!event.target) {
  12922. return;
  12923. }
  12924. var
  12925. $target = $(event.target),
  12926. isInDOM = $.contains(document.documentElement, event.target)
  12927. ;
  12928. return (isInDOM && $target.closest(selector.message).length > 0);
  12929. },
  12930. empty: function() {
  12931. return ($results.html() === '');
  12932. },
  12933. visible: function() {
  12934. return ($results.filter(':visible').length > 0);
  12935. },
  12936. focused: function() {
  12937. return ($prompt.filter(':focus').length > 0);
  12938. }
  12939. },
  12940. get: {
  12941. settings: function() {
  12942. if($.isPlainObject(parameters) && parameters.searchFullText) {
  12943. settings.fullTextSearch = parameters.searchFullText;
  12944. module.error(settings.error.oldSearchSyntax, element);
  12945. }
  12946. },
  12947. inputEvent: function() {
  12948. var
  12949. prompt = $prompt[0],
  12950. inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
  12951. ? 'input'
  12952. : (prompt !== undefined && prompt.onpropertychange !== undefined)
  12953. ? 'propertychange'
  12954. : 'keyup'
  12955. ;
  12956. return inputEvent;
  12957. },
  12958. value: function() {
  12959. return $prompt.val();
  12960. },
  12961. results: function() {
  12962. var
  12963. results = $module.data(metadata.results)
  12964. ;
  12965. return results;
  12966. },
  12967. result: function(value, results) {
  12968. var
  12969. lookupFields = ['title', 'id'],
  12970. result = false
  12971. ;
  12972. value = (value !== undefined)
  12973. ? value
  12974. : module.get.value()
  12975. ;
  12976. results = (results !== undefined)
  12977. ? results
  12978. : module.get.results()
  12979. ;
  12980. if(settings.type === 'category') {
  12981. module.debug('Finding result that matches', value);
  12982. $.each(results, function(index, category) {
  12983. if($.isArray(category.results)) {
  12984. result = module.search.object(value, category.results, lookupFields)[0];
  12985. // don't continue searching if a result is found
  12986. if(result) {
  12987. return false;
  12988. }
  12989. }
  12990. });
  12991. }
  12992. else {
  12993. module.debug('Finding result in results object', value);
  12994. result = module.search.object(value, results, lookupFields)[0];
  12995. }
  12996. return result || false;
  12997. },
  12998. },
  12999. select: {
  13000. firstResult: function() {
  13001. module.verbose('Selecting first result');
  13002. $result.first().addClass(className.active);
  13003. }
  13004. },
  13005. set: {
  13006. focus: function() {
  13007. $module.addClass(className.focus);
  13008. },
  13009. loading: function() {
  13010. $module.addClass(className.loading);
  13011. },
  13012. value: function(value) {
  13013. module.verbose('Setting search input value', value);
  13014. $prompt
  13015. .val(value)
  13016. ;
  13017. },
  13018. type: function(type) {
  13019. type = type || settings.type;
  13020. if(settings.type == 'category') {
  13021. $module.addClass(settings.type);
  13022. }
  13023. },
  13024. buttonPressed: function() {
  13025. $searchButton.addClass(className.pressed);
  13026. }
  13027. },
  13028. remove: {
  13029. loading: function() {
  13030. $module.removeClass(className.loading);
  13031. },
  13032. focus: function() {
  13033. $module.removeClass(className.focus);
  13034. },
  13035. buttonPressed: function() {
  13036. $searchButton.removeClass(className.pressed);
  13037. }
  13038. },
  13039. query: function(callback) {
  13040. callback = $.isFunction(callback)
  13041. ? callback
  13042. : function(){}
  13043. ;
  13044. var
  13045. searchTerm = module.get.value(),
  13046. cache = module.read.cache(searchTerm)
  13047. ;
  13048. callback = callback || function() {};
  13049. if( module.has.minimumCharacters() ) {
  13050. if(cache) {
  13051. module.debug('Reading result from cache', searchTerm);
  13052. module.save.results(cache.results);
  13053. module.addResults(cache.html);
  13054. module.inject.id(cache.results);
  13055. callback();
  13056. }
  13057. else {
  13058. module.debug('Querying for', searchTerm);
  13059. if($.isPlainObject(settings.source) || $.isArray(settings.source)) {
  13060. module.search.local(searchTerm);
  13061. callback();
  13062. }
  13063. else if( module.can.useAPI() ) {
  13064. module.search.remote(searchTerm, callback);
  13065. }
  13066. else {
  13067. module.error(error.source);
  13068. callback();
  13069. }
  13070. }
  13071. settings.onSearchQuery.call(element, searchTerm);
  13072. }
  13073. else {
  13074. module.hideResults();
  13075. }
  13076. },
  13077. search: {
  13078. local: function(searchTerm) {
  13079. var
  13080. results = module.search.object(searchTerm, settings.content),
  13081. searchHTML
  13082. ;
  13083. module.set.loading();
  13084. module.save.results(results);
  13085. module.debug('Returned full local search results', results);
  13086. if(settings.maxResults > 0) {
  13087. module.debug('Using specified max results', results);
  13088. results = results.slice(0, settings.maxResults);
  13089. }
  13090. if(settings.type == 'category') {
  13091. results = module.create.categoryResults(results);
  13092. }
  13093. searchHTML = module.generateResults({
  13094. results: results
  13095. });
  13096. module.remove.loading();
  13097. module.addResults(searchHTML);
  13098. module.inject.id(results);
  13099. module.write.cache(searchTerm, {
  13100. html : searchHTML,
  13101. results : results
  13102. });
  13103. },
  13104. remote: function(searchTerm, callback) {
  13105. callback = $.isFunction(callback)
  13106. ? callback
  13107. : function(){}
  13108. ;
  13109. if($module.api('is loading')) {
  13110. $module.api('abort');
  13111. }
  13112. module.setup.api(searchTerm, callback);
  13113. $module
  13114. .api('query')
  13115. ;
  13116. },
  13117. object: function(searchTerm, source, searchFields) {
  13118. var
  13119. results = [],
  13120. exactResults = [],
  13121. fuzzyResults = [],
  13122. searchExp = searchTerm.toString().replace(regExp.escape, '\\$&'),
  13123. matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
  13124. // avoid duplicates when pushing results
  13125. addResult = function(array, result) {
  13126. var
  13127. notResult = ($.inArray(result, results) == -1),
  13128. notFuzzyResult = ($.inArray(result, fuzzyResults) == -1),
  13129. notExactResults = ($.inArray(result, exactResults) == -1)
  13130. ;
  13131. if(notResult && notFuzzyResult && notExactResults) {
  13132. array.push(result);
  13133. }
  13134. }
  13135. ;
  13136. source = source || settings.source;
  13137. searchFields = (searchFields !== undefined)
  13138. ? searchFields
  13139. : settings.searchFields
  13140. ;
  13141. // search fields should be array to loop correctly
  13142. if(!$.isArray(searchFields)) {
  13143. searchFields = [searchFields];
  13144. }
  13145. // exit conditions if no source
  13146. if(source === undefined || source === false) {
  13147. module.error(error.source);
  13148. return [];
  13149. }
  13150. // iterate through search fields looking for matches
  13151. $.each(searchFields, function(index, field) {
  13152. $.each(source, function(label, content) {
  13153. var
  13154. fieldExists = (typeof content[field] == 'string')
  13155. ;
  13156. if(fieldExists) {
  13157. if( content[field].search(matchRegExp) !== -1) {
  13158. // content starts with value (first in results)
  13159. addResult(results, content);
  13160. }
  13161. else if(settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, content[field]) ) {
  13162. // content fuzzy matches (last in results)
  13163. addResult(exactResults, content);
  13164. }
  13165. else if(settings.fullTextSearch == true && module.fuzzySearch(searchTerm, content[field]) ) {
  13166. // content fuzzy matches (last in results)
  13167. addResult(fuzzyResults, content);
  13168. }
  13169. }
  13170. });
  13171. });
  13172. $.merge(exactResults, fuzzyResults)
  13173. $.merge(results, exactResults);
  13174. return results;
  13175. }
  13176. },
  13177. exactSearch: function (query, term) {
  13178. query = query.toLowerCase();
  13179. term = term.toLowerCase();
  13180. if(term.indexOf(query) > -1) {
  13181. return true;
  13182. }
  13183. return false;
  13184. },
  13185. fuzzySearch: function(query, term) {
  13186. var
  13187. termLength = term.length,
  13188. queryLength = query.length
  13189. ;
  13190. if(typeof query !== 'string') {
  13191. return false;
  13192. }
  13193. query = query.toLowerCase();
  13194. term = term.toLowerCase();
  13195. if(queryLength > termLength) {
  13196. return false;
  13197. }
  13198. if(queryLength === termLength) {
  13199. return (query === term);
  13200. }
  13201. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  13202. var
  13203. queryCharacter = query.charCodeAt(characterIndex)
  13204. ;
  13205. while(nextCharacterIndex < termLength) {
  13206. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  13207. continue search;
  13208. }
  13209. }
  13210. return false;
  13211. }
  13212. return true;
  13213. },
  13214. parse: {
  13215. response: function(response, searchTerm) {
  13216. var
  13217. searchHTML = module.generateResults(response)
  13218. ;
  13219. module.verbose('Parsing server response', response);
  13220. if(response !== undefined) {
  13221. if(searchTerm !== undefined && response[fields.results] !== undefined) {
  13222. module.addResults(searchHTML);
  13223. module.inject.id(response[fields.results]);
  13224. module.write.cache(searchTerm, {
  13225. html : searchHTML,
  13226. results : response[fields.results]
  13227. });
  13228. module.save.results(response[fields.results]);
  13229. }
  13230. }
  13231. }
  13232. },
  13233. cancel: {
  13234. query: function() {
  13235. if( module.can.useAPI() ) {
  13236. $module.api('abort');
  13237. }
  13238. }
  13239. },
  13240. has: {
  13241. minimumCharacters: function() {
  13242. var
  13243. searchTerm = module.get.value(),
  13244. numCharacters = searchTerm.length
  13245. ;
  13246. return (numCharacters >= settings.minCharacters);
  13247. },
  13248. results: function() {
  13249. if($results.length === 0) {
  13250. return false;
  13251. }
  13252. var
  13253. html = $results.html()
  13254. ;
  13255. return html != '';
  13256. }
  13257. },
  13258. clear: {
  13259. cache: function(value) {
  13260. var
  13261. cache = $module.data(metadata.cache)
  13262. ;
  13263. if(!value) {
  13264. module.debug('Clearing cache', value);
  13265. $module.removeData(metadata.cache);
  13266. }
  13267. else if(value && cache && cache[value]) {
  13268. module.debug('Removing value from cache', value);
  13269. delete cache[value];
  13270. $module.data(metadata.cache, cache);
  13271. }
  13272. }
  13273. },
  13274. read: {
  13275. cache: function(name) {
  13276. var
  13277. cache = $module.data(metadata.cache)
  13278. ;
  13279. if(settings.cache) {
  13280. module.verbose('Checking cache for generated html for query', name);
  13281. return (typeof cache == 'object') && (cache[name] !== undefined)
  13282. ? cache[name]
  13283. : false
  13284. ;
  13285. }
  13286. return false;
  13287. }
  13288. },
  13289. create: {
  13290. categoryResults: function(results) {
  13291. var
  13292. categoryResults = {}
  13293. ;
  13294. $.each(results, function(index, result) {
  13295. if(!result.category) {
  13296. return;
  13297. }
  13298. if(categoryResults[result.category] === undefined) {
  13299. module.verbose('Creating new category of results', result.category);
  13300. categoryResults[result.category] = {
  13301. name : result.category,
  13302. results : [result]
  13303. }
  13304. }
  13305. else {
  13306. categoryResults[result.category].results.push(result);
  13307. }
  13308. });
  13309. return categoryResults;
  13310. },
  13311. id: function(resultIndex, categoryIndex) {
  13312. var
  13313. resultID = (resultIndex + 1), // not zero indexed
  13314. categoryID = (categoryIndex + 1),
  13315. firstCharCode,
  13316. letterID,
  13317. id
  13318. ;
  13319. if(categoryIndex !== undefined) {
  13320. // start char code for "A"
  13321. letterID = String.fromCharCode(97 + categoryIndex);
  13322. id = letterID + resultID;
  13323. module.verbose('Creating category result id', id);
  13324. }
  13325. else {
  13326. id = resultID;
  13327. module.verbose('Creating result id', id);
  13328. }
  13329. return id;
  13330. },
  13331. results: function() {
  13332. if($results.length === 0) {
  13333. $results = $('<div />')
  13334. .addClass(className.results)
  13335. .appendTo($module)
  13336. ;
  13337. }
  13338. }
  13339. },
  13340. inject: {
  13341. result: function(result, resultIndex, categoryIndex) {
  13342. module.verbose('Injecting result into results');
  13343. var
  13344. $selectedResult = (categoryIndex !== undefined)
  13345. ? $results
  13346. .children().eq(categoryIndex)
  13347. .children(selector.results)
  13348. .first()
  13349. .children(selector.result)
  13350. .eq(resultIndex)
  13351. : $results
  13352. .children(selector.result).eq(resultIndex)
  13353. ;
  13354. module.verbose('Injecting results metadata', $selectedResult);
  13355. $selectedResult
  13356. .data(metadata.result, result)
  13357. ;
  13358. },
  13359. id: function(results) {
  13360. module.debug('Injecting unique ids into results');
  13361. var
  13362. // since results may be object, we must use counters
  13363. categoryIndex = 0,
  13364. resultIndex = 0
  13365. ;
  13366. if(settings.type === 'category') {
  13367. // iterate through each category result
  13368. $.each(results, function(index, category) {
  13369. resultIndex = 0;
  13370. $.each(category.results, function(index, value) {
  13371. var
  13372. result = category.results[index]
  13373. ;
  13374. if(result.id === undefined) {
  13375. result.id = module.create.id(resultIndex, categoryIndex);
  13376. }
  13377. module.inject.result(result, resultIndex, categoryIndex);
  13378. resultIndex++;
  13379. });
  13380. categoryIndex++;
  13381. });
  13382. }
  13383. else {
  13384. // top level
  13385. $.each(results, function(index, value) {
  13386. var
  13387. result = results[index]
  13388. ;
  13389. if(result.id === undefined) {
  13390. result.id = module.create.id(resultIndex);
  13391. }
  13392. module.inject.result(result, resultIndex);
  13393. resultIndex++;
  13394. });
  13395. }
  13396. return results;
  13397. }
  13398. },
  13399. save: {
  13400. results: function(results) {
  13401. module.verbose('Saving current search results to metadata', results);
  13402. $module.data(metadata.results, results);
  13403. }
  13404. },
  13405. write: {
  13406. cache: function(name, value) {
  13407. var
  13408. cache = ($module.data(metadata.cache) !== undefined)
  13409. ? $module.data(metadata.cache)
  13410. : {}
  13411. ;
  13412. if(settings.cache) {
  13413. module.verbose('Writing generated html to cache', name, value);
  13414. cache[name] = value;
  13415. $module
  13416. .data(metadata.cache, cache)
  13417. ;
  13418. }
  13419. }
  13420. },
  13421. addResults: function(html) {
  13422. if( $.isFunction(settings.onResultsAdd) ) {
  13423. if( settings.onResultsAdd.call($results, html) === false ) {
  13424. module.debug('onResultsAdd callback cancelled default action');
  13425. return false;
  13426. }
  13427. }
  13428. if(html) {
  13429. $results
  13430. .html(html)
  13431. ;
  13432. module.refreshResults();
  13433. if(settings.selectFirstResult) {
  13434. module.select.firstResult();
  13435. }
  13436. module.showResults();
  13437. }
  13438. else {
  13439. module.hideResults(function() {
  13440. $results.empty();
  13441. });
  13442. }
  13443. },
  13444. showResults: function(callback) {
  13445. callback = $.isFunction(callback)
  13446. ? callback
  13447. : function(){}
  13448. ;
  13449. if(resultsDismissed) {
  13450. return;
  13451. }
  13452. if(!module.is.visible() && module.has.results()) {
  13453. if( module.can.transition() ) {
  13454. module.debug('Showing results with css animations');
  13455. $results
  13456. .transition({
  13457. animation : settings.transition + ' in',
  13458. debug : settings.debug,
  13459. verbose : settings.verbose,
  13460. duration : settings.duration,
  13461. onComplete : function() {
  13462. callback();
  13463. },
  13464. queue : true
  13465. })
  13466. ;
  13467. }
  13468. else {
  13469. module.debug('Showing results with javascript');
  13470. $results
  13471. .stop()
  13472. .fadeIn(settings.duration, settings.easing)
  13473. ;
  13474. }
  13475. settings.onResultsOpen.call($results);
  13476. }
  13477. },
  13478. hideResults: function(callback) {
  13479. callback = $.isFunction(callback)
  13480. ? callback
  13481. : function(){}
  13482. ;
  13483. if( module.is.visible() ) {
  13484. if( module.can.transition() ) {
  13485. module.debug('Hiding results with css animations');
  13486. $results
  13487. .transition({
  13488. animation : settings.transition + ' out',
  13489. debug : settings.debug,
  13490. verbose : settings.verbose,
  13491. duration : settings.duration,
  13492. onComplete : function() {
  13493. callback();
  13494. },
  13495. queue : true
  13496. })
  13497. ;
  13498. }
  13499. else {
  13500. module.debug('Hiding results with javascript');
  13501. $results
  13502. .stop()
  13503. .fadeOut(settings.duration, settings.easing)
  13504. ;
  13505. }
  13506. settings.onResultsClose.call($results);
  13507. }
  13508. },
  13509. generateResults: function(response) {
  13510. module.debug('Generating html from response', response);
  13511. var
  13512. template = settings.templates[settings.type],
  13513. isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])),
  13514. isProperArray = ($.isArray(response[fields.results]) && response[fields.results].length > 0),
  13515. html = ''
  13516. ;
  13517. if(isProperObject || isProperArray ) {
  13518. if(settings.maxResults > 0) {
  13519. if(isProperObject) {
  13520. if(settings.type == 'standard') {
  13521. module.error(error.maxResults);
  13522. }
  13523. }
  13524. else {
  13525. response[fields.results] = response[fields.results].slice(0, settings.maxResults);
  13526. }
  13527. }
  13528. if($.isFunction(template)) {
  13529. html = template(response, fields);
  13530. }
  13531. else {
  13532. module.error(error.noTemplate, false);
  13533. }
  13534. }
  13535. else if(settings.showNoResults) {
  13536. html = module.displayMessage(error.noResults, 'empty');
  13537. }
  13538. settings.onResults.call(element, response);
  13539. return html;
  13540. },
  13541. displayMessage: function(text, type) {
  13542. type = type || 'standard';
  13543. module.debug('Displaying message', text, type);
  13544. module.addResults( settings.templates.message(text, type) );
  13545. return settings.templates.message(text, type);
  13546. },
  13547. setting: function(name, value) {
  13548. if( $.isPlainObject(name) ) {
  13549. $.extend(true, settings, name);
  13550. }
  13551. else if(value !== undefined) {
  13552. settings[name] = value;
  13553. }
  13554. else {
  13555. return settings[name];
  13556. }
  13557. },
  13558. internal: function(name, value) {
  13559. if( $.isPlainObject(name) ) {
  13560. $.extend(true, module, name);
  13561. }
  13562. else if(value !== undefined) {
  13563. module[name] = value;
  13564. }
  13565. else {
  13566. return module[name];
  13567. }
  13568. },
  13569. debug: function() {
  13570. if(!settings.silent && settings.debug) {
  13571. if(settings.performance) {
  13572. module.performance.log(arguments);
  13573. }
  13574. else {
  13575. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13576. module.debug.apply(console, arguments);
  13577. }
  13578. }
  13579. },
  13580. verbose: function() {
  13581. if(!settings.silent && settings.verbose && settings.debug) {
  13582. if(settings.performance) {
  13583. module.performance.log(arguments);
  13584. }
  13585. else {
  13586. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13587. module.verbose.apply(console, arguments);
  13588. }
  13589. }
  13590. },
  13591. error: function() {
  13592. if(!settings.silent) {
  13593. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  13594. module.error.apply(console, arguments);
  13595. }
  13596. },
  13597. performance: {
  13598. log: function(message) {
  13599. var
  13600. currentTime,
  13601. executionTime,
  13602. previousTime
  13603. ;
  13604. if(settings.performance) {
  13605. currentTime = new Date().getTime();
  13606. previousTime = time || currentTime;
  13607. executionTime = currentTime - previousTime;
  13608. time = currentTime;
  13609. performance.push({
  13610. 'Name' : message[0],
  13611. 'Arguments' : [].slice.call(message, 1) || '',
  13612. 'Element' : element,
  13613. 'Execution Time' : executionTime
  13614. });
  13615. }
  13616. clearTimeout(module.performance.timer);
  13617. module.performance.timer = setTimeout(module.performance.display, 500);
  13618. },
  13619. display: function() {
  13620. var
  13621. title = settings.name + ':',
  13622. totalTime = 0
  13623. ;
  13624. time = false;
  13625. clearTimeout(module.performance.timer);
  13626. $.each(performance, function(index, data) {
  13627. totalTime += data['Execution Time'];
  13628. });
  13629. title += ' ' + totalTime + 'ms';
  13630. if(moduleSelector) {
  13631. title += ' \'' + moduleSelector + '\'';
  13632. }
  13633. if($allModules.length > 1) {
  13634. title += ' ' + '(' + $allModules.length + ')';
  13635. }
  13636. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  13637. console.groupCollapsed(title);
  13638. if(console.table) {
  13639. console.table(performance);
  13640. }
  13641. else {
  13642. $.each(performance, function(index, data) {
  13643. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  13644. });
  13645. }
  13646. console.groupEnd();
  13647. }
  13648. performance = [];
  13649. }
  13650. },
  13651. invoke: function(query, passedArguments, context) {
  13652. var
  13653. object = instance,
  13654. maxDepth,
  13655. found,
  13656. response
  13657. ;
  13658. passedArguments = passedArguments || queryArguments;
  13659. context = element || context;
  13660. if(typeof query == 'string' && object !== undefined) {
  13661. query = query.split(/[\. ]/);
  13662. maxDepth = query.length - 1;
  13663. $.each(query, function(depth, value) {
  13664. var camelCaseValue = (depth != maxDepth)
  13665. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  13666. : query
  13667. ;
  13668. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  13669. object = object[camelCaseValue];
  13670. }
  13671. else if( object[camelCaseValue] !== undefined ) {
  13672. found = object[camelCaseValue];
  13673. return false;
  13674. }
  13675. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  13676. object = object[value];
  13677. }
  13678. else if( object[value] !== undefined ) {
  13679. found = object[value];
  13680. return false;
  13681. }
  13682. else {
  13683. return false;
  13684. }
  13685. });
  13686. }
  13687. if( $.isFunction( found ) ) {
  13688. response = found.apply(context, passedArguments);
  13689. }
  13690. else if(found !== undefined) {
  13691. response = found;
  13692. }
  13693. if($.isArray(returnedValue)) {
  13694. returnedValue.push(response);
  13695. }
  13696. else if(returnedValue !== undefined) {
  13697. returnedValue = [returnedValue, response];
  13698. }
  13699. else if(response !== undefined) {
  13700. returnedValue = response;
  13701. }
  13702. return found;
  13703. }
  13704. };
  13705. if(methodInvoked) {
  13706. if(instance === undefined) {
  13707. module.initialize();
  13708. }
  13709. module.invoke(query);
  13710. }
  13711. else {
  13712. if(instance !== undefined) {
  13713. instance.invoke('destroy');
  13714. }
  13715. module.initialize();
  13716. }
  13717. })
  13718. ;
  13719. return (returnedValue !== undefined)
  13720. ? returnedValue
  13721. : this
  13722. ;
  13723. };
  13724. $.fn.search.settings = {
  13725. name : 'Search',
  13726. namespace : 'search',
  13727. silent : false,
  13728. debug : false,
  13729. verbose : false,
  13730. performance : true,
  13731. // template to use (specified in settings.templates)
  13732. type : 'standard',
  13733. // minimum characters required to search
  13734. minCharacters : 1,
  13735. // whether to select first result after searching automatically
  13736. selectFirstResult : false,
  13737. // API config
  13738. apiSettings : false,
  13739. // object to search
  13740. source : false,
  13741. // Whether search should query current term on focus
  13742. searchOnFocus : true,
  13743. // fields to search
  13744. searchFields : [
  13745. 'title',
  13746. 'description'
  13747. ],
  13748. // field to display in standard results template
  13749. displayField : '',
  13750. // search anywhere in value (set to 'exact' to require exact matches
  13751. fullTextSearch : 'exact',
  13752. // whether to add events to prompt automatically
  13753. automatic : true,
  13754. // delay before hiding menu after blur
  13755. hideDelay : 0,
  13756. // delay before searching
  13757. searchDelay : 200,
  13758. // maximum results returned from search
  13759. maxResults : 7,
  13760. // whether to store lookups in local cache
  13761. cache : true,
  13762. // whether no results errors should be shown
  13763. showNoResults : true,
  13764. // transition settings
  13765. transition : 'scale',
  13766. duration : 200,
  13767. easing : 'easeOutExpo',
  13768. // callbacks
  13769. onSelect : false,
  13770. onResultsAdd : false,
  13771. onSearchQuery : function(query){},
  13772. onResults : function(response){},
  13773. onResultsOpen : function(){},
  13774. onResultsClose : function(){},
  13775. className: {
  13776. animating : 'animating',
  13777. active : 'active',
  13778. empty : 'empty',
  13779. focus : 'focus',
  13780. hidden : 'hidden',
  13781. loading : 'loading',
  13782. results : 'results',
  13783. pressed : 'down'
  13784. },
  13785. error : {
  13786. source : 'Cannot search. No source used, and Semantic API module was not included',
  13787. noResults : 'Your search returned no results',
  13788. logging : 'Error in debug logging, exiting.',
  13789. noEndpoint : 'No search endpoint was specified',
  13790. noTemplate : 'A valid template name was not specified.',
  13791. oldSearchSyntax : 'searchFullText setting has been renamed fullTextSearch for consistency, please adjust your settings.',
  13792. serverError : 'There was an issue querying the server.',
  13793. maxResults : 'Results must be an array to use maxResults setting',
  13794. method : 'The method you called is not defined.'
  13795. },
  13796. metadata: {
  13797. cache : 'cache',
  13798. results : 'results',
  13799. result : 'result'
  13800. },
  13801. regExp: {
  13802. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  13803. beginsWith : '(?:\s|^)'
  13804. },
  13805. // maps api response attributes to internal representation
  13806. fields: {
  13807. categories : 'results', // array of categories (category view)
  13808. categoryName : 'name', // name of category (category view)
  13809. categoryResults : 'results', // array of results (category view)
  13810. description : 'description', // result description
  13811. image : 'image', // result image
  13812. price : 'price', // result price
  13813. results : 'results', // array of results (standard)
  13814. title : 'title', // result title
  13815. url : 'url', // result url
  13816. action : 'action', // "view more" object name
  13817. actionText : 'text', // "view more" text
  13818. actionURL : 'url' // "view more" url
  13819. },
  13820. selector : {
  13821. prompt : '.prompt',
  13822. searchButton : '.search.button',
  13823. results : '.results',
  13824. message : '.results > .message',
  13825. category : '.category',
  13826. result : '.result',
  13827. title : '.title, .name'
  13828. },
  13829. templates: {
  13830. escape: function(string) {
  13831. var
  13832. badChars = /[&<>"'`]/g,
  13833. shouldEscape = /[&<>"'`]/,
  13834. escape = {
  13835. "&": "&amp;",
  13836. "<": "&lt;",
  13837. ">": "&gt;",
  13838. '"': "&quot;",
  13839. "'": "&#x27;",
  13840. "`": "&#x60;"
  13841. },
  13842. escapedChar = function(chr) {
  13843. return escape[chr];
  13844. }
  13845. ;
  13846. if(shouldEscape.test(string)) {
  13847. return string.replace(badChars, escapedChar);
  13848. }
  13849. return string;
  13850. },
  13851. message: function(message, type) {
  13852. var
  13853. html = ''
  13854. ;
  13855. if(message !== undefined && type !== undefined) {
  13856. html += ''
  13857. + '<div class="message ' + type + '">'
  13858. ;
  13859. // message type
  13860. if(type == 'empty') {
  13861. html += ''
  13862. + '<div class="header">No Results</div class="header">'
  13863. + '<div class="description">' + message + '</div class="description">'
  13864. ;
  13865. }
  13866. else {
  13867. html += ' <div class="description">' + message + '</div>';
  13868. }
  13869. html += '</div>';
  13870. }
  13871. return html;
  13872. },
  13873. category: function(response, fields) {
  13874. var
  13875. html = '',
  13876. escape = $.fn.search.settings.templates.escape
  13877. ;
  13878. if(response[fields.categoryResults] !== undefined) {
  13879. // each category
  13880. $.each(response[fields.categoryResults], function(index, category) {
  13881. if(category[fields.results] !== undefined && category.results.length > 0) {
  13882. html += '<div class="category">';
  13883. if(category[fields.categoryName] !== undefined) {
  13884. html += '<div class="name">' + category[fields.categoryName] + '</div>';
  13885. }
  13886. // each item inside category
  13887. html += '<div class="results">';
  13888. $.each(category.results, function(index, result) {
  13889. if(result[fields.url]) {
  13890. html += '<a class="result" href="' + result[fields.url] + '">';
  13891. }
  13892. else {
  13893. html += '<a class="result">';
  13894. }
  13895. if(result[fields.image] !== undefined) {
  13896. html += ''
  13897. + '<div class="image">'
  13898. + ' <img src="' + result[fields.image] + '">'
  13899. + '</div>'
  13900. ;
  13901. }
  13902. html += '<div class="content">';
  13903. if(result[fields.price] !== undefined) {
  13904. html += '<div class="price">' + result[fields.price] + '</div>';
  13905. }
  13906. if(result[fields.title] !== undefined) {
  13907. html += '<div class="title">' + result[fields.title] + '</div>';
  13908. }
  13909. if(result[fields.description] !== undefined) {
  13910. html += '<div class="description">' + result[fields.description] + '</div>';
  13911. }
  13912. html += ''
  13913. + '</div>'
  13914. ;
  13915. html += '</a>';
  13916. });
  13917. html += '</div>';
  13918. html += ''
  13919. + '</div>'
  13920. ;
  13921. }
  13922. });
  13923. if(response[fields.action]) {
  13924. html += ''
  13925. + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">'
  13926. + response[fields.action][fields.actionText]
  13927. + '</a>';
  13928. }
  13929. return html;
  13930. }
  13931. return false;
  13932. },
  13933. standard: function(response, fields) {
  13934. var
  13935. html = ''
  13936. ;
  13937. if(response[fields.results] !== undefined) {
  13938. // each result
  13939. $.each(response[fields.results], function(index, result) {
  13940. if(result[fields.url]) {
  13941. html += '<a class="result" href="' + result[fields.url] + '">';
  13942. }
  13943. else {
  13944. html += '<a class="result">';
  13945. }
  13946. if(result[fields.image] !== undefined) {
  13947. html += ''
  13948. + '<div class="image">'
  13949. + ' <img src="' + result[fields.image] + '">'
  13950. + '</div>'
  13951. ;
  13952. }
  13953. html += '<div class="content">';
  13954. if(result[fields.price] !== undefined) {
  13955. html += '<div class="price">' + result[fields.price] + '</div>';
  13956. }
  13957. if(result[fields.title] !== undefined) {
  13958. html += '<div class="title">' + result[fields.title] + '</div>';
  13959. }
  13960. if(result[fields.description] !== undefined) {
  13961. html += '<div class="description">' + result[fields.description] + '</div>';
  13962. }
  13963. html += ''
  13964. + '</div>'
  13965. ;
  13966. html += '</a>';
  13967. });
  13968. if(response[fields.action]) {
  13969. html += ''
  13970. + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">'
  13971. + response[fields.action][fields.actionText]
  13972. + '</a>';
  13973. }
  13974. return html;
  13975. }
  13976. return false;
  13977. }
  13978. }
  13979. };
  13980. })( jQuery, window, document );
  13981. /*!
  13982. * # Semantic UI 2.3.3 - Shape
  13983. * http://github.com/semantic-org/semantic-ui/
  13984. *
  13985. *
  13986. * Released under the MIT license
  13987. * http://opensource.org/licenses/MIT
  13988. *
  13989. */
  13990. ;(function ($, window, document, undefined) {
  13991. 'use strict';
  13992. window = (typeof window != 'undefined' && window.Math == Math)
  13993. ? window
  13994. : (typeof self != 'undefined' && self.Math == Math)
  13995. ? self
  13996. : Function('return this')()
  13997. ;
  13998. $.fn.shape = function(parameters) {
  13999. var
  14000. $allModules = $(this),
  14001. $body = $('body'),
  14002. time = new Date().getTime(),
  14003. performance = [],
  14004. query = arguments[0],
  14005. methodInvoked = (typeof query == 'string'),
  14006. queryArguments = [].slice.call(arguments, 1),
  14007. requestAnimationFrame = window.requestAnimationFrame
  14008. || window.mozRequestAnimationFrame
  14009. || window.webkitRequestAnimationFrame
  14010. || window.msRequestAnimationFrame
  14011. || function(callback) { setTimeout(callback, 0); },
  14012. returnedValue
  14013. ;
  14014. $allModules
  14015. .each(function() {
  14016. var
  14017. moduleSelector = $allModules.selector || '',
  14018. settings = ( $.isPlainObject(parameters) )
  14019. ? $.extend(true, {}, $.fn.shape.settings, parameters)
  14020. : $.extend({}, $.fn.shape.settings),
  14021. // internal aliases
  14022. namespace = settings.namespace,
  14023. selector = settings.selector,
  14024. error = settings.error,
  14025. className = settings.className,
  14026. // define namespaces for modules
  14027. eventNamespace = '.' + namespace,
  14028. moduleNamespace = 'module-' + namespace,
  14029. // selector cache
  14030. $module = $(this),
  14031. $sides = $module.find(selector.sides),
  14032. $side = $module.find(selector.side),
  14033. // private variables
  14034. nextIndex = false,
  14035. $activeSide,
  14036. $nextSide,
  14037. // standard module
  14038. element = this,
  14039. instance = $module.data(moduleNamespace),
  14040. module
  14041. ;
  14042. module = {
  14043. initialize: function() {
  14044. module.verbose('Initializing module for', element);
  14045. module.set.defaultSide();
  14046. module.instantiate();
  14047. },
  14048. instantiate: function() {
  14049. module.verbose('Storing instance of module', module);
  14050. instance = module;
  14051. $module
  14052. .data(moduleNamespace, instance)
  14053. ;
  14054. },
  14055. destroy: function() {
  14056. module.verbose('Destroying previous module for', element);
  14057. $module
  14058. .removeData(moduleNamespace)
  14059. .off(eventNamespace)
  14060. ;
  14061. },
  14062. refresh: function() {
  14063. module.verbose('Refreshing selector cache for', element);
  14064. $module = $(element);
  14065. $sides = $(this).find(selector.shape);
  14066. $side = $(this).find(selector.side);
  14067. },
  14068. repaint: function() {
  14069. module.verbose('Forcing repaint event');
  14070. var
  14071. shape = $sides[0] || document.createElement('div'),
  14072. fakeAssignment = shape.offsetWidth
  14073. ;
  14074. },
  14075. animate: function(propertyObject, callback) {
  14076. module.verbose('Animating box with properties', propertyObject);
  14077. callback = callback || function(event) {
  14078. module.verbose('Executing animation callback');
  14079. if(event !== undefined) {
  14080. event.stopPropagation();
  14081. }
  14082. module.reset();
  14083. module.set.active();
  14084. };
  14085. settings.beforeChange.call($nextSide[0]);
  14086. if(module.get.transitionEvent()) {
  14087. module.verbose('Starting CSS animation');
  14088. $module
  14089. .addClass(className.animating)
  14090. ;
  14091. $sides
  14092. .css(propertyObject)
  14093. .one(module.get.transitionEvent(), callback)
  14094. ;
  14095. module.set.duration(settings.duration);
  14096. requestAnimationFrame(function() {
  14097. $module
  14098. .addClass(className.animating)
  14099. ;
  14100. $activeSide
  14101. .addClass(className.hidden)
  14102. ;
  14103. });
  14104. }
  14105. else {
  14106. callback();
  14107. }
  14108. },
  14109. queue: function(method) {
  14110. module.debug('Queueing animation of', method);
  14111. $sides
  14112. .one(module.get.transitionEvent(), function() {
  14113. module.debug('Executing queued animation');
  14114. setTimeout(function(){
  14115. $module.shape(method);
  14116. }, 0);
  14117. })
  14118. ;
  14119. },
  14120. reset: function() {
  14121. module.verbose('Animating states reset');
  14122. $module
  14123. .removeClass(className.animating)
  14124. .attr('style', '')
  14125. .removeAttr('style')
  14126. ;
  14127. // removeAttr style does not consistently work in safari
  14128. $sides
  14129. .attr('style', '')
  14130. .removeAttr('style')
  14131. ;
  14132. $side
  14133. .attr('style', '')
  14134. .removeAttr('style')
  14135. .removeClass(className.hidden)
  14136. ;
  14137. $nextSide
  14138. .removeClass(className.animating)
  14139. .attr('style', '')
  14140. .removeAttr('style')
  14141. ;
  14142. },
  14143. is: {
  14144. complete: function() {
  14145. return ($side.filter('.' + className.active)[0] == $nextSide[0]);
  14146. },
  14147. animating: function() {
  14148. return $module.hasClass(className.animating);
  14149. }
  14150. },
  14151. set: {
  14152. defaultSide: function() {
  14153. $activeSide = $module.find('.' + settings.className.active);
  14154. $nextSide = ( $activeSide.next(selector.side).length > 0 )
  14155. ? $activeSide.next(selector.side)
  14156. : $module.find(selector.side).first()
  14157. ;
  14158. nextIndex = false;
  14159. module.verbose('Active side set to', $activeSide);
  14160. module.verbose('Next side set to', $nextSide);
  14161. },
  14162. duration: function(duration) {
  14163. duration = duration || settings.duration;
  14164. duration = (typeof duration == 'number')
  14165. ? duration + 'ms'
  14166. : duration
  14167. ;
  14168. module.verbose('Setting animation duration', duration);
  14169. if(settings.duration || settings.duration === 0) {
  14170. $sides.add($side)
  14171. .css({
  14172. '-webkit-transition-duration': duration,
  14173. '-moz-transition-duration': duration,
  14174. '-ms-transition-duration': duration,
  14175. '-o-transition-duration': duration,
  14176. 'transition-duration': duration
  14177. })
  14178. ;
  14179. }
  14180. },
  14181. currentStageSize: function() {
  14182. var
  14183. $activeSide = $module.find('.' + settings.className.active),
  14184. width = $activeSide.outerWidth(true),
  14185. height = $activeSide.outerHeight(true)
  14186. ;
  14187. $module
  14188. .css({
  14189. width: width,
  14190. height: height
  14191. })
  14192. ;
  14193. },
  14194. stageSize: function() {
  14195. var
  14196. $clone = $module.clone().addClass(className.loading),
  14197. $activeSide = $clone.find('.' + settings.className.active),
  14198. $nextSide = (nextIndex)
  14199. ? $clone.find(selector.side).eq(nextIndex)
  14200. : ( $activeSide.next(selector.side).length > 0 )
  14201. ? $activeSide.next(selector.side)
  14202. : $clone.find(selector.side).first(),
  14203. newWidth = (settings.width == 'next')
  14204. ? $nextSide.outerWidth(true)
  14205. : (settings.width == 'initial')
  14206. ? $module.width()
  14207. : settings.width,
  14208. newHeight = (settings.height == 'next')
  14209. ? $nextSide.outerHeight(true)
  14210. : (settings.height == 'initial')
  14211. ? $module.height()
  14212. : settings.height
  14213. ;
  14214. $activeSide.removeClass(className.active);
  14215. $nextSide.addClass(className.active);
  14216. $clone.insertAfter($module);
  14217. $clone.remove();
  14218. if(settings.width != 'auto') {
  14219. $module.css('width', newWidth + settings.jitter);
  14220. module.verbose('Specifying width during animation', newWidth);
  14221. }
  14222. if(settings.height != 'auto') {
  14223. $module.css('height', newHeight + settings.jitter);
  14224. module.verbose('Specifying height during animation', newHeight);
  14225. }
  14226. },
  14227. nextSide: function(selector) {
  14228. nextIndex = selector;
  14229. $nextSide = $side.filter(selector);
  14230. nextIndex = $side.index($nextSide);
  14231. if($nextSide.length === 0) {
  14232. module.set.defaultSide();
  14233. module.error(error.side);
  14234. }
  14235. module.verbose('Next side manually set to', $nextSide);
  14236. },
  14237. active: function() {
  14238. module.verbose('Setting new side to active', $nextSide);
  14239. $side
  14240. .removeClass(className.active)
  14241. ;
  14242. $nextSide
  14243. .addClass(className.active)
  14244. ;
  14245. settings.onChange.call($nextSide[0]);
  14246. module.set.defaultSide();
  14247. }
  14248. },
  14249. flip: {
  14250. up: function() {
  14251. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14252. module.debug('Side already visible', $nextSide);
  14253. return;
  14254. }
  14255. if( !module.is.animating()) {
  14256. module.debug('Flipping up', $nextSide);
  14257. var
  14258. transform = module.get.transform.up()
  14259. ;
  14260. module.set.stageSize();
  14261. module.stage.above();
  14262. module.animate(transform);
  14263. }
  14264. else {
  14265. module.queue('flip up');
  14266. }
  14267. },
  14268. down: function() {
  14269. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14270. module.debug('Side already visible', $nextSide);
  14271. return;
  14272. }
  14273. if( !module.is.animating()) {
  14274. module.debug('Flipping down', $nextSide);
  14275. var
  14276. transform = module.get.transform.down()
  14277. ;
  14278. module.set.stageSize();
  14279. module.stage.below();
  14280. module.animate(transform);
  14281. }
  14282. else {
  14283. module.queue('flip down');
  14284. }
  14285. },
  14286. left: function() {
  14287. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14288. module.debug('Side already visible', $nextSide);
  14289. return;
  14290. }
  14291. if( !module.is.animating()) {
  14292. module.debug('Flipping left', $nextSide);
  14293. var
  14294. transform = module.get.transform.left()
  14295. ;
  14296. module.set.stageSize();
  14297. module.stage.left();
  14298. module.animate(transform);
  14299. }
  14300. else {
  14301. module.queue('flip left');
  14302. }
  14303. },
  14304. right: function() {
  14305. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14306. module.debug('Side already visible', $nextSide);
  14307. return;
  14308. }
  14309. if( !module.is.animating()) {
  14310. module.debug('Flipping right', $nextSide);
  14311. var
  14312. transform = module.get.transform.right()
  14313. ;
  14314. module.set.stageSize();
  14315. module.stage.right();
  14316. module.animate(transform);
  14317. }
  14318. else {
  14319. module.queue('flip right');
  14320. }
  14321. },
  14322. over: function() {
  14323. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14324. module.debug('Side already visible', $nextSide);
  14325. return;
  14326. }
  14327. if( !module.is.animating()) {
  14328. module.debug('Flipping over', $nextSide);
  14329. module.set.stageSize();
  14330. module.stage.behind();
  14331. module.animate(module.get.transform.over() );
  14332. }
  14333. else {
  14334. module.queue('flip over');
  14335. }
  14336. },
  14337. back: function() {
  14338. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14339. module.debug('Side already visible', $nextSide);
  14340. return;
  14341. }
  14342. if( !module.is.animating()) {
  14343. module.debug('Flipping back', $nextSide);
  14344. module.set.stageSize();
  14345. module.stage.behind();
  14346. module.animate(module.get.transform.back() );
  14347. }
  14348. else {
  14349. module.queue('flip back');
  14350. }
  14351. }
  14352. },
  14353. get: {
  14354. transform: {
  14355. up: function() {
  14356. var
  14357. translate = {
  14358. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14359. z: -($activeSide.outerHeight(true) / 2)
  14360. }
  14361. ;
  14362. return {
  14363. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)'
  14364. };
  14365. },
  14366. down: function() {
  14367. var
  14368. translate = {
  14369. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14370. z: -($activeSide.outerHeight(true) / 2)
  14371. }
  14372. ;
  14373. return {
  14374. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)'
  14375. };
  14376. },
  14377. left: function() {
  14378. var
  14379. translate = {
  14380. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  14381. z : -($activeSide.outerWidth(true) / 2)
  14382. }
  14383. ;
  14384. return {
  14385. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)'
  14386. };
  14387. },
  14388. right: function() {
  14389. var
  14390. translate = {
  14391. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  14392. z : -($activeSide.outerWidth(true) / 2)
  14393. }
  14394. ;
  14395. return {
  14396. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)'
  14397. };
  14398. },
  14399. over: function() {
  14400. var
  14401. translate = {
  14402. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  14403. }
  14404. ;
  14405. return {
  14406. transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
  14407. };
  14408. },
  14409. back: function() {
  14410. var
  14411. translate = {
  14412. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  14413. }
  14414. ;
  14415. return {
  14416. transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
  14417. };
  14418. }
  14419. },
  14420. transitionEvent: function() {
  14421. var
  14422. element = document.createElement('element'),
  14423. transitions = {
  14424. 'transition' :'transitionend',
  14425. 'OTransition' :'oTransitionEnd',
  14426. 'MozTransition' :'transitionend',
  14427. 'WebkitTransition' :'webkitTransitionEnd'
  14428. },
  14429. transition
  14430. ;
  14431. for(transition in transitions){
  14432. if( element.style[transition] !== undefined ){
  14433. return transitions[transition];
  14434. }
  14435. }
  14436. },
  14437. nextSide: function() {
  14438. return ( $activeSide.next(selector.side).length > 0 )
  14439. ? $activeSide.next(selector.side)
  14440. : $module.find(selector.side).first()
  14441. ;
  14442. }
  14443. },
  14444. stage: {
  14445. above: function() {
  14446. var
  14447. box = {
  14448. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14449. depth : {
  14450. active : ($nextSide.outerHeight(true) / 2),
  14451. next : ($activeSide.outerHeight(true) / 2)
  14452. }
  14453. }
  14454. ;
  14455. module.verbose('Setting the initial animation position as above', $nextSide, box);
  14456. $sides
  14457. .css({
  14458. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14459. })
  14460. ;
  14461. $activeSide
  14462. .css({
  14463. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14464. })
  14465. ;
  14466. $nextSide
  14467. .addClass(className.animating)
  14468. .css({
  14469. 'top' : box.origin + 'px',
  14470. 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)'
  14471. })
  14472. ;
  14473. },
  14474. below: function() {
  14475. var
  14476. box = {
  14477. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14478. depth : {
  14479. active : ($nextSide.outerHeight(true) / 2),
  14480. next : ($activeSide.outerHeight(true) / 2)
  14481. }
  14482. }
  14483. ;
  14484. module.verbose('Setting the initial animation position as below', $nextSide, box);
  14485. $sides
  14486. .css({
  14487. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14488. })
  14489. ;
  14490. $activeSide
  14491. .css({
  14492. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14493. })
  14494. ;
  14495. $nextSide
  14496. .addClass(className.animating)
  14497. .css({
  14498. 'top' : box.origin + 'px',
  14499. 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)'
  14500. })
  14501. ;
  14502. },
  14503. left: function() {
  14504. var
  14505. height = {
  14506. active : $activeSide.outerWidth(true),
  14507. next : $nextSide.outerWidth(true)
  14508. },
  14509. box = {
  14510. origin : ( ( height.active - height.next ) / 2),
  14511. depth : {
  14512. active : (height.next / 2),
  14513. next : (height.active / 2)
  14514. }
  14515. }
  14516. ;
  14517. module.verbose('Setting the initial animation position as left', $nextSide, box);
  14518. $sides
  14519. .css({
  14520. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14521. })
  14522. ;
  14523. $activeSide
  14524. .css({
  14525. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14526. })
  14527. ;
  14528. $nextSide
  14529. .addClass(className.animating)
  14530. .css({
  14531. 'left' : box.origin + 'px',
  14532. 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)'
  14533. })
  14534. ;
  14535. },
  14536. right: function() {
  14537. var
  14538. height = {
  14539. active : $activeSide.outerWidth(true),
  14540. next : $nextSide.outerWidth(true)
  14541. },
  14542. box = {
  14543. origin : ( ( height.active - height.next ) / 2),
  14544. depth : {
  14545. active : (height.next / 2),
  14546. next : (height.active / 2)
  14547. }
  14548. }
  14549. ;
  14550. module.verbose('Setting the initial animation position as left', $nextSide, box);
  14551. $sides
  14552. .css({
  14553. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14554. })
  14555. ;
  14556. $activeSide
  14557. .css({
  14558. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14559. })
  14560. ;
  14561. $nextSide
  14562. .addClass(className.animating)
  14563. .css({
  14564. 'left' : box.origin + 'px',
  14565. 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)'
  14566. })
  14567. ;
  14568. },
  14569. behind: function() {
  14570. var
  14571. height = {
  14572. active : $activeSide.outerWidth(true),
  14573. next : $nextSide.outerWidth(true)
  14574. },
  14575. box = {
  14576. origin : ( ( height.active - height.next ) / 2),
  14577. depth : {
  14578. active : (height.next / 2),
  14579. next : (height.active / 2)
  14580. }
  14581. }
  14582. ;
  14583. module.verbose('Setting the initial animation position as behind', $nextSide, box);
  14584. $activeSide
  14585. .css({
  14586. 'transform' : 'rotateY(0deg)'
  14587. })
  14588. ;
  14589. $nextSide
  14590. .addClass(className.animating)
  14591. .css({
  14592. 'left' : box.origin + 'px',
  14593. 'transform' : 'rotateY(-180deg)'
  14594. })
  14595. ;
  14596. }
  14597. },
  14598. setting: function(name, value) {
  14599. module.debug('Changing setting', name, value);
  14600. if( $.isPlainObject(name) ) {
  14601. $.extend(true, settings, name);
  14602. }
  14603. else if(value !== undefined) {
  14604. if($.isPlainObject(settings[name])) {
  14605. $.extend(true, settings[name], value);
  14606. }
  14607. else {
  14608. settings[name] = value;
  14609. }
  14610. }
  14611. else {
  14612. return settings[name];
  14613. }
  14614. },
  14615. internal: function(name, value) {
  14616. if( $.isPlainObject(name) ) {
  14617. $.extend(true, module, name);
  14618. }
  14619. else if(value !== undefined) {
  14620. module[name] = value;
  14621. }
  14622. else {
  14623. return module[name];
  14624. }
  14625. },
  14626. debug: function() {
  14627. if(!settings.silent && settings.debug) {
  14628. if(settings.performance) {
  14629. module.performance.log(arguments);
  14630. }
  14631. else {
  14632. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14633. module.debug.apply(console, arguments);
  14634. }
  14635. }
  14636. },
  14637. verbose: function() {
  14638. if(!settings.silent && settings.verbose && settings.debug) {
  14639. if(settings.performance) {
  14640. module.performance.log(arguments);
  14641. }
  14642. else {
  14643. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14644. module.verbose.apply(console, arguments);
  14645. }
  14646. }
  14647. },
  14648. error: function() {
  14649. if(!settings.silent) {
  14650. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  14651. module.error.apply(console, arguments);
  14652. }
  14653. },
  14654. performance: {
  14655. log: function(message) {
  14656. var
  14657. currentTime,
  14658. executionTime,
  14659. previousTime
  14660. ;
  14661. if(settings.performance) {
  14662. currentTime = new Date().getTime();
  14663. previousTime = time || currentTime;
  14664. executionTime = currentTime - previousTime;
  14665. time = currentTime;
  14666. performance.push({
  14667. 'Name' : message[0],
  14668. 'Arguments' : [].slice.call(message, 1) || '',
  14669. 'Element' : element,
  14670. 'Execution Time' : executionTime
  14671. });
  14672. }
  14673. clearTimeout(module.performance.timer);
  14674. module.performance.timer = setTimeout(module.performance.display, 500);
  14675. },
  14676. display: function() {
  14677. var
  14678. title = settings.name + ':',
  14679. totalTime = 0
  14680. ;
  14681. time = false;
  14682. clearTimeout(module.performance.timer);
  14683. $.each(performance, function(index, data) {
  14684. totalTime += data['Execution Time'];
  14685. });
  14686. title += ' ' + totalTime + 'ms';
  14687. if(moduleSelector) {
  14688. title += ' \'' + moduleSelector + '\'';
  14689. }
  14690. if($allModules.length > 1) {
  14691. title += ' ' + '(' + $allModules.length + ')';
  14692. }
  14693. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  14694. console.groupCollapsed(title);
  14695. if(console.table) {
  14696. console.table(performance);
  14697. }
  14698. else {
  14699. $.each(performance, function(index, data) {
  14700. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  14701. });
  14702. }
  14703. console.groupEnd();
  14704. }
  14705. performance = [];
  14706. }
  14707. },
  14708. invoke: function(query, passedArguments, context) {
  14709. var
  14710. object = instance,
  14711. maxDepth,
  14712. found,
  14713. response
  14714. ;
  14715. passedArguments = passedArguments || queryArguments;
  14716. context = element || context;
  14717. if(typeof query == 'string' && object !== undefined) {
  14718. query = query.split(/[\. ]/);
  14719. maxDepth = query.length - 1;
  14720. $.each(query, function(depth, value) {
  14721. var camelCaseValue = (depth != maxDepth)
  14722. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  14723. : query
  14724. ;
  14725. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  14726. object = object[camelCaseValue];
  14727. }
  14728. else if( object[camelCaseValue] !== undefined ) {
  14729. found = object[camelCaseValue];
  14730. return false;
  14731. }
  14732. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  14733. object = object[value];
  14734. }
  14735. else if( object[value] !== undefined ) {
  14736. found = object[value];
  14737. return false;
  14738. }
  14739. else {
  14740. return false;
  14741. }
  14742. });
  14743. }
  14744. if ( $.isFunction( found ) ) {
  14745. response = found.apply(context, passedArguments);
  14746. }
  14747. else if(found !== undefined) {
  14748. response = found;
  14749. }
  14750. if($.isArray(returnedValue)) {
  14751. returnedValue.push(response);
  14752. }
  14753. else if(returnedValue !== undefined) {
  14754. returnedValue = [returnedValue, response];
  14755. }
  14756. else if(response !== undefined) {
  14757. returnedValue = response;
  14758. }
  14759. return found;
  14760. }
  14761. };
  14762. if(methodInvoked) {
  14763. if(instance === undefined) {
  14764. module.initialize();
  14765. }
  14766. module.invoke(query);
  14767. }
  14768. else {
  14769. if(instance !== undefined) {
  14770. instance.invoke('destroy');
  14771. }
  14772. module.initialize();
  14773. }
  14774. })
  14775. ;
  14776. return (returnedValue !== undefined)
  14777. ? returnedValue
  14778. : this
  14779. ;
  14780. };
  14781. $.fn.shape.settings = {
  14782. // module info
  14783. name : 'Shape',
  14784. // hide all debug content
  14785. silent : false,
  14786. // debug content outputted to console
  14787. debug : false,
  14788. // verbose debug output
  14789. verbose : false,
  14790. // fudge factor in pixels when swapping from 2d to 3d (can be useful to correct rounding errors)
  14791. jitter : 0,
  14792. // performance data output
  14793. performance: true,
  14794. // event namespace
  14795. namespace : 'shape',
  14796. // width during animation, can be set to 'auto', initial', 'next' or pixel amount
  14797. width: 'initial',
  14798. // height during animation, can be set to 'auto', 'initial', 'next' or pixel amount
  14799. height: 'initial',
  14800. // callback occurs on side change
  14801. beforeChange : function() {},
  14802. onChange : function() {},
  14803. // allow animation to same side
  14804. allowRepeats: false,
  14805. // animation duration
  14806. duration : false,
  14807. // possible errors
  14808. error: {
  14809. side : 'You tried to switch to a side that does not exist.',
  14810. method : 'The method you called is not defined'
  14811. },
  14812. // classnames used
  14813. className : {
  14814. animating : 'animating',
  14815. hidden : 'hidden',
  14816. loading : 'loading',
  14817. active : 'active'
  14818. },
  14819. // selectors used
  14820. selector : {
  14821. sides : '.sides',
  14822. side : '.side'
  14823. }
  14824. };
  14825. })( jQuery, window, document );
  14826. /*!
  14827. * # Semantic UI 2.3.3 - Sidebar
  14828. * http://github.com/semantic-org/semantic-ui/
  14829. *
  14830. *
  14831. * Released under the MIT license
  14832. * http://opensource.org/licenses/MIT
  14833. *
  14834. */
  14835. ;(function ($, window, document, undefined) {
  14836. 'use strict';
  14837. window = (typeof window != 'undefined' && window.Math == Math)
  14838. ? window
  14839. : (typeof self != 'undefined' && self.Math == Math)
  14840. ? self
  14841. : Function('return this')()
  14842. ;
  14843. $.fn.sidebar = function(parameters) {
  14844. var
  14845. $allModules = $(this),
  14846. $window = $(window),
  14847. $document = $(document),
  14848. $html = $('html'),
  14849. $head = $('head'),
  14850. moduleSelector = $allModules.selector || '',
  14851. time = new Date().getTime(),
  14852. performance = [],
  14853. query = arguments[0],
  14854. methodInvoked = (typeof query == 'string'),
  14855. queryArguments = [].slice.call(arguments, 1),
  14856. requestAnimationFrame = window.requestAnimationFrame
  14857. || window.mozRequestAnimationFrame
  14858. || window.webkitRequestAnimationFrame
  14859. || window.msRequestAnimationFrame
  14860. || function(callback) { setTimeout(callback, 0); },
  14861. returnedValue
  14862. ;
  14863. $allModules
  14864. .each(function() {
  14865. var
  14866. settings = ( $.isPlainObject(parameters) )
  14867. ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
  14868. : $.extend({}, $.fn.sidebar.settings),
  14869. selector = settings.selector,
  14870. className = settings.className,
  14871. namespace = settings.namespace,
  14872. regExp = settings.regExp,
  14873. error = settings.error,
  14874. eventNamespace = '.' + namespace,
  14875. moduleNamespace = 'module-' + namespace,
  14876. $module = $(this),
  14877. $context = $(settings.context),
  14878. $sidebars = $module.children(selector.sidebar),
  14879. $fixed = $context.children(selector.fixed),
  14880. $pusher = $context.children(selector.pusher),
  14881. $style,
  14882. element = this,
  14883. instance = $module.data(moduleNamespace),
  14884. elementNamespace,
  14885. id,
  14886. currentScroll,
  14887. transitionEvent,
  14888. module
  14889. ;
  14890. module = {
  14891. initialize: function() {
  14892. module.debug('Initializing sidebar', parameters);
  14893. module.create.id();
  14894. transitionEvent = module.get.transitionEvent();
  14895. // avoids locking rendering if initialized in onReady
  14896. if(settings.delaySetup) {
  14897. requestAnimationFrame(module.setup.layout);
  14898. }
  14899. else {
  14900. module.setup.layout();
  14901. }
  14902. requestAnimationFrame(function() {
  14903. module.setup.cache();
  14904. });
  14905. module.instantiate();
  14906. },
  14907. instantiate: function() {
  14908. module.verbose('Storing instance of module', module);
  14909. instance = module;
  14910. $module
  14911. .data(moduleNamespace, module)
  14912. ;
  14913. },
  14914. create: {
  14915. id: function() {
  14916. id = (Math.random().toString(16) + '000000000').substr(2,8);
  14917. elementNamespace = '.' + id;
  14918. module.verbose('Creating unique id for element', id);
  14919. }
  14920. },
  14921. destroy: function() {
  14922. module.verbose('Destroying previous module for', $module);
  14923. $module
  14924. .off(eventNamespace)
  14925. .removeData(moduleNamespace)
  14926. ;
  14927. if(module.is.ios()) {
  14928. module.remove.ios();
  14929. }
  14930. // bound by uuid
  14931. $context.off(elementNamespace);
  14932. $window.off(elementNamespace);
  14933. $document.off(elementNamespace);
  14934. },
  14935. event: {
  14936. clickaway: function(event) {
  14937. var
  14938. clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
  14939. clickedContext = ($context.is(event.target))
  14940. ;
  14941. if(clickedInPusher) {
  14942. module.verbose('User clicked on dimmed page');
  14943. module.hide();
  14944. }
  14945. if(clickedContext) {
  14946. module.verbose('User clicked on dimmable context (scaled out page)');
  14947. module.hide();
  14948. }
  14949. },
  14950. touch: function(event) {
  14951. //event.stopPropagation();
  14952. },
  14953. containScroll: function(event) {
  14954. if(element.scrollTop <= 0) {
  14955. element.scrollTop = 1;
  14956. }
  14957. if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
  14958. element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
  14959. }
  14960. },
  14961. scroll: function(event) {
  14962. if( $(event.target).closest(selector.sidebar).length === 0 ) {
  14963. event.preventDefault();
  14964. }
  14965. }
  14966. },
  14967. bind: {
  14968. clickaway: function() {
  14969. module.verbose('Adding clickaway events to context', $context);
  14970. if(settings.closable) {
  14971. $context
  14972. .on('click' + elementNamespace, module.event.clickaway)
  14973. .on('touchend' + elementNamespace, module.event.clickaway)
  14974. ;
  14975. }
  14976. },
  14977. scrollLock: function() {
  14978. if(settings.scrollLock) {
  14979. module.debug('Disabling page scroll');
  14980. $window
  14981. .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
  14982. ;
  14983. }
  14984. module.verbose('Adding events to contain sidebar scroll');
  14985. $document
  14986. .on('touchmove' + elementNamespace, module.event.touch)
  14987. ;
  14988. $module
  14989. .on('scroll' + eventNamespace, module.event.containScroll)
  14990. ;
  14991. }
  14992. },
  14993. unbind: {
  14994. clickaway: function() {
  14995. module.verbose('Removing clickaway events from context', $context);
  14996. $context.off(elementNamespace);
  14997. },
  14998. scrollLock: function() {
  14999. module.verbose('Removing scroll lock from page');
  15000. $document.off(elementNamespace);
  15001. $window.off(elementNamespace);
  15002. $module.off('scroll' + eventNamespace);
  15003. }
  15004. },
  15005. add: {
  15006. inlineCSS: function() {
  15007. var
  15008. width = module.cache.width || $module.outerWidth(),
  15009. height = module.cache.height || $module.outerHeight(),
  15010. isRTL = module.is.rtl(),
  15011. direction = module.get.direction(),
  15012. distance = {
  15013. left : width,
  15014. right : -width,
  15015. top : height,
  15016. bottom : -height
  15017. },
  15018. style
  15019. ;
  15020. if(isRTL){
  15021. module.verbose('RTL detected, flipping widths');
  15022. distance.left = -width;
  15023. distance.right = width;
  15024. }
  15025. style = '<style>';
  15026. if(direction === 'left' || direction === 'right') {
  15027. module.debug('Adding CSS rules for animation distance', width);
  15028. style += ''
  15029. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  15030. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  15031. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15032. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15033. + ' }'
  15034. ;
  15035. }
  15036. else if(direction === 'top' || direction == 'bottom') {
  15037. style += ''
  15038. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  15039. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  15040. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15041. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15042. + ' }'
  15043. ;
  15044. }
  15045. /* IE is only browser not to create context with transforms */
  15046. /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
  15047. if( module.is.ie() ) {
  15048. if(direction === 'left' || direction === 'right') {
  15049. module.debug('Adding CSS rules for animation distance', width);
  15050. style += ''
  15051. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  15052. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15053. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15054. + ' }'
  15055. ;
  15056. }
  15057. else if(direction === 'top' || direction == 'bottom') {
  15058. style += ''
  15059. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  15060. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15061. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15062. + ' }'
  15063. ;
  15064. }
  15065. /* opposite sides visible forces content overlay */
  15066. style += ''
  15067. + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
  15068. + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
  15069. + ' -webkit-transform: translate3d(0px, 0, 0);'
  15070. + ' transform: translate3d(0px, 0, 0);'
  15071. + ' }'
  15072. ;
  15073. }
  15074. style += '</style>';
  15075. $style = $(style)
  15076. .appendTo($head)
  15077. ;
  15078. module.debug('Adding sizing css to head', $style);
  15079. }
  15080. },
  15081. refresh: function() {
  15082. module.verbose('Refreshing selector cache');
  15083. $context = $(settings.context);
  15084. $sidebars = $context.children(selector.sidebar);
  15085. $pusher = $context.children(selector.pusher);
  15086. $fixed = $context.children(selector.fixed);
  15087. module.clear.cache();
  15088. },
  15089. refreshSidebars: function() {
  15090. module.verbose('Refreshing other sidebars');
  15091. $sidebars = $context.children(selector.sidebar);
  15092. },
  15093. repaint: function() {
  15094. module.verbose('Forcing repaint event');
  15095. element.style.display = 'none';
  15096. var ignored = element.offsetHeight;
  15097. element.scrollTop = element.scrollTop;
  15098. element.style.display = '';
  15099. },
  15100. setup: {
  15101. cache: function() {
  15102. module.cache = {
  15103. width : $module.outerWidth(),
  15104. height : $module.outerHeight(),
  15105. rtl : ($module.css('direction') == 'rtl')
  15106. };
  15107. },
  15108. layout: function() {
  15109. if( $context.children(selector.pusher).length === 0 ) {
  15110. module.debug('Adding wrapper element for sidebar');
  15111. module.error(error.pusher);
  15112. $pusher = $('<div class="pusher" />');
  15113. $context
  15114. .children()
  15115. .not(selector.omitted)
  15116. .not($sidebars)
  15117. .wrapAll($pusher)
  15118. ;
  15119. module.refresh();
  15120. }
  15121. if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
  15122. module.debug('Moved sidebar to correct parent element');
  15123. module.error(error.movedSidebar, element);
  15124. $module.detach().prependTo($context);
  15125. module.refresh();
  15126. }
  15127. module.clear.cache();
  15128. module.set.pushable();
  15129. module.set.direction();
  15130. }
  15131. },
  15132. attachEvents: function(selector, event) {
  15133. var
  15134. $toggle = $(selector)
  15135. ;
  15136. event = $.isFunction(module[event])
  15137. ? module[event]
  15138. : module.toggle
  15139. ;
  15140. if($toggle.length > 0) {
  15141. module.debug('Attaching sidebar events to element', selector, event);
  15142. $toggle
  15143. .on('click' + eventNamespace, event)
  15144. ;
  15145. }
  15146. else {
  15147. module.error(error.notFound, selector);
  15148. }
  15149. },
  15150. show: function(callback) {
  15151. callback = $.isFunction(callback)
  15152. ? callback
  15153. : function(){}
  15154. ;
  15155. if(module.is.hidden()) {
  15156. module.refreshSidebars();
  15157. if(settings.overlay) {
  15158. module.error(error.overlay);
  15159. settings.transition = 'overlay';
  15160. }
  15161. module.refresh();
  15162. if(module.othersActive()) {
  15163. module.debug('Other sidebars currently visible');
  15164. if(settings.exclusive) {
  15165. // if not overlay queue animation after hide
  15166. if(settings.transition != 'overlay') {
  15167. module.hideOthers(module.show);
  15168. return;
  15169. }
  15170. else {
  15171. module.hideOthers();
  15172. }
  15173. }
  15174. else {
  15175. settings.transition = 'overlay';
  15176. }
  15177. }
  15178. module.pushPage(function() {
  15179. callback.call(element);
  15180. settings.onShow.call(element);
  15181. });
  15182. settings.onChange.call(element);
  15183. settings.onVisible.call(element);
  15184. }
  15185. else {
  15186. module.debug('Sidebar is already visible');
  15187. }
  15188. },
  15189. hide: function(callback) {
  15190. callback = $.isFunction(callback)
  15191. ? callback
  15192. : function(){}
  15193. ;
  15194. if(module.is.visible() || module.is.animating()) {
  15195. module.debug('Hiding sidebar', callback);
  15196. module.refreshSidebars();
  15197. module.pullPage(function() {
  15198. callback.call(element);
  15199. settings.onHidden.call(element);
  15200. });
  15201. settings.onChange.call(element);
  15202. settings.onHide.call(element);
  15203. }
  15204. },
  15205. othersAnimating: function() {
  15206. return ($sidebars.not($module).filter('.' + className.animating).length > 0);
  15207. },
  15208. othersVisible: function() {
  15209. return ($sidebars.not($module).filter('.' + className.visible).length > 0);
  15210. },
  15211. othersActive: function() {
  15212. return(module.othersVisible() || module.othersAnimating());
  15213. },
  15214. hideOthers: function(callback) {
  15215. var
  15216. $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
  15217. sidebarCount = $otherSidebars.length,
  15218. callbackCount = 0
  15219. ;
  15220. callback = callback || function(){};
  15221. $otherSidebars
  15222. .sidebar('hide', function() {
  15223. callbackCount++;
  15224. if(callbackCount == sidebarCount) {
  15225. callback();
  15226. }
  15227. })
  15228. ;
  15229. },
  15230. toggle: function() {
  15231. module.verbose('Determining toggled direction');
  15232. if(module.is.hidden()) {
  15233. module.show();
  15234. }
  15235. else {
  15236. module.hide();
  15237. }
  15238. },
  15239. pushPage: function(callback) {
  15240. var
  15241. transition = module.get.transition(),
  15242. $transition = (transition === 'overlay' || module.othersActive())
  15243. ? $module
  15244. : $pusher,
  15245. animate,
  15246. dim,
  15247. transitionEnd
  15248. ;
  15249. callback = $.isFunction(callback)
  15250. ? callback
  15251. : function(){}
  15252. ;
  15253. if(settings.transition == 'scale down') {
  15254. module.scrollToTop();
  15255. }
  15256. module.set.transition(transition);
  15257. module.repaint();
  15258. animate = function() {
  15259. module.bind.clickaway();
  15260. module.add.inlineCSS();
  15261. module.set.animating();
  15262. module.set.visible();
  15263. };
  15264. dim = function() {
  15265. module.set.dimmed();
  15266. };
  15267. transitionEnd = function(event) {
  15268. if( event.target == $transition[0] ) {
  15269. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  15270. module.remove.animating();
  15271. module.bind.scrollLock();
  15272. callback.call(element);
  15273. }
  15274. };
  15275. $transition.off(transitionEvent + elementNamespace);
  15276. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  15277. requestAnimationFrame(animate);
  15278. if(settings.dimPage && !module.othersVisible()) {
  15279. requestAnimationFrame(dim);
  15280. }
  15281. },
  15282. pullPage: function(callback) {
  15283. var
  15284. transition = module.get.transition(),
  15285. $transition = (transition == 'overlay' || module.othersActive())
  15286. ? $module
  15287. : $pusher,
  15288. animate,
  15289. transitionEnd
  15290. ;
  15291. callback = $.isFunction(callback)
  15292. ? callback
  15293. : function(){}
  15294. ;
  15295. module.verbose('Removing context push state', module.get.direction());
  15296. module.unbind.clickaway();
  15297. module.unbind.scrollLock();
  15298. animate = function() {
  15299. module.set.transition(transition);
  15300. module.set.animating();
  15301. module.remove.visible();
  15302. if(settings.dimPage && !module.othersVisible()) {
  15303. $pusher.removeClass(className.dimmed);
  15304. }
  15305. };
  15306. transitionEnd = function(event) {
  15307. if( event.target == $transition[0] ) {
  15308. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  15309. module.remove.animating();
  15310. module.remove.transition();
  15311. module.remove.inlineCSS();
  15312. if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
  15313. module.scrollBack();
  15314. }
  15315. callback.call(element);
  15316. }
  15317. };
  15318. $transition.off(transitionEvent + elementNamespace);
  15319. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  15320. requestAnimationFrame(animate);
  15321. },
  15322. scrollToTop: function() {
  15323. module.verbose('Scrolling to top of page to avoid animation issues');
  15324. currentScroll = $(window).scrollTop();
  15325. $module.scrollTop(0);
  15326. window.scrollTo(0, 0);
  15327. },
  15328. scrollBack: function() {
  15329. module.verbose('Scrolling back to original page position');
  15330. window.scrollTo(0, currentScroll);
  15331. },
  15332. clear: {
  15333. cache: function() {
  15334. module.verbose('Clearing cached dimensions');
  15335. module.cache = {};
  15336. }
  15337. },
  15338. set: {
  15339. // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
  15340. // (This is no longer necessary in latest iOS)
  15341. ios: function() {
  15342. $html.addClass(className.ios);
  15343. },
  15344. // container
  15345. pushed: function() {
  15346. $context.addClass(className.pushed);
  15347. },
  15348. pushable: function() {
  15349. $context.addClass(className.pushable);
  15350. },
  15351. // pusher
  15352. dimmed: function() {
  15353. $pusher.addClass(className.dimmed);
  15354. },
  15355. // sidebar
  15356. active: function() {
  15357. $module.addClass(className.active);
  15358. },
  15359. animating: function() {
  15360. $module.addClass(className.animating);
  15361. },
  15362. transition: function(transition) {
  15363. transition = transition || module.get.transition();
  15364. $module.addClass(transition);
  15365. },
  15366. direction: function(direction) {
  15367. direction = direction || module.get.direction();
  15368. $module.addClass(className[direction]);
  15369. },
  15370. visible: function() {
  15371. $module.addClass(className.visible);
  15372. },
  15373. overlay: function() {
  15374. $module.addClass(className.overlay);
  15375. }
  15376. },
  15377. remove: {
  15378. inlineCSS: function() {
  15379. module.debug('Removing inline css styles', $style);
  15380. if($style && $style.length > 0) {
  15381. $style.remove();
  15382. }
  15383. },
  15384. // ios scroll on html not document
  15385. ios: function() {
  15386. $html.removeClass(className.ios);
  15387. },
  15388. // context
  15389. pushed: function() {
  15390. $context.removeClass(className.pushed);
  15391. },
  15392. pushable: function() {
  15393. $context.removeClass(className.pushable);
  15394. },
  15395. // sidebar
  15396. active: function() {
  15397. $module.removeClass(className.active);
  15398. },
  15399. animating: function() {
  15400. $module.removeClass(className.animating);
  15401. },
  15402. transition: function(transition) {
  15403. transition = transition || module.get.transition();
  15404. $module.removeClass(transition);
  15405. },
  15406. direction: function(direction) {
  15407. direction = direction || module.get.direction();
  15408. $module.removeClass(className[direction]);
  15409. },
  15410. visible: function() {
  15411. $module.removeClass(className.visible);
  15412. },
  15413. overlay: function() {
  15414. $module.removeClass(className.overlay);
  15415. }
  15416. },
  15417. get: {
  15418. direction: function() {
  15419. if($module.hasClass(className.top)) {
  15420. return className.top;
  15421. }
  15422. else if($module.hasClass(className.right)) {
  15423. return className.right;
  15424. }
  15425. else if($module.hasClass(className.bottom)) {
  15426. return className.bottom;
  15427. }
  15428. return className.left;
  15429. },
  15430. transition: function() {
  15431. var
  15432. direction = module.get.direction(),
  15433. transition
  15434. ;
  15435. transition = ( module.is.mobile() )
  15436. ? (settings.mobileTransition == 'auto')
  15437. ? settings.defaultTransition.mobile[direction]
  15438. : settings.mobileTransition
  15439. : (settings.transition == 'auto')
  15440. ? settings.defaultTransition.computer[direction]
  15441. : settings.transition
  15442. ;
  15443. module.verbose('Determined transition', transition);
  15444. return transition;
  15445. },
  15446. transitionEvent: function() {
  15447. var
  15448. element = document.createElement('element'),
  15449. transitions = {
  15450. 'transition' :'transitionend',
  15451. 'OTransition' :'oTransitionEnd',
  15452. 'MozTransition' :'transitionend',
  15453. 'WebkitTransition' :'webkitTransitionEnd'
  15454. },
  15455. transition
  15456. ;
  15457. for(transition in transitions){
  15458. if( element.style[transition] !== undefined ){
  15459. return transitions[transition];
  15460. }
  15461. }
  15462. }
  15463. },
  15464. is: {
  15465. ie: function() {
  15466. var
  15467. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  15468. isIE = ('ActiveXObject' in window)
  15469. ;
  15470. return (isIE11 || isIE);
  15471. },
  15472. ios: function() {
  15473. var
  15474. userAgent = navigator.userAgent,
  15475. isIOS = userAgent.match(regExp.ios),
  15476. isMobileChrome = userAgent.match(regExp.mobileChrome)
  15477. ;
  15478. if(isIOS && !isMobileChrome) {
  15479. module.verbose('Browser was found to be iOS', userAgent);
  15480. return true;
  15481. }
  15482. else {
  15483. return false;
  15484. }
  15485. },
  15486. mobile: function() {
  15487. var
  15488. userAgent = navigator.userAgent,
  15489. isMobile = userAgent.match(regExp.mobile)
  15490. ;
  15491. if(isMobile) {
  15492. module.verbose('Browser was found to be mobile', userAgent);
  15493. return true;
  15494. }
  15495. else {
  15496. module.verbose('Browser is not mobile, using regular transition', userAgent);
  15497. return false;
  15498. }
  15499. },
  15500. hidden: function() {
  15501. return !module.is.visible();
  15502. },
  15503. visible: function() {
  15504. return $module.hasClass(className.visible);
  15505. },
  15506. // alias
  15507. open: function() {
  15508. return module.is.visible();
  15509. },
  15510. closed: function() {
  15511. return module.is.hidden();
  15512. },
  15513. vertical: function() {
  15514. return $module.hasClass(className.top);
  15515. },
  15516. animating: function() {
  15517. return $context.hasClass(className.animating);
  15518. },
  15519. rtl: function () {
  15520. if(module.cache.rtl === undefined) {
  15521. module.cache.rtl = ($module.css('direction') == 'rtl');
  15522. }
  15523. return module.cache.rtl;
  15524. }
  15525. },
  15526. setting: function(name, value) {
  15527. module.debug('Changing setting', name, value);
  15528. if( $.isPlainObject(name) ) {
  15529. $.extend(true, settings, name);
  15530. }
  15531. else if(value !== undefined) {
  15532. if($.isPlainObject(settings[name])) {
  15533. $.extend(true, settings[name], value);
  15534. }
  15535. else {
  15536. settings[name] = value;
  15537. }
  15538. }
  15539. else {
  15540. return settings[name];
  15541. }
  15542. },
  15543. internal: function(name, value) {
  15544. if( $.isPlainObject(name) ) {
  15545. $.extend(true, module, name);
  15546. }
  15547. else if(value !== undefined) {
  15548. module[name] = value;
  15549. }
  15550. else {
  15551. return module[name];
  15552. }
  15553. },
  15554. debug: function() {
  15555. if(!settings.silent && settings.debug) {
  15556. if(settings.performance) {
  15557. module.performance.log(arguments);
  15558. }
  15559. else {
  15560. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15561. module.debug.apply(console, arguments);
  15562. }
  15563. }
  15564. },
  15565. verbose: function() {
  15566. if(!settings.silent && settings.verbose && settings.debug) {
  15567. if(settings.performance) {
  15568. module.performance.log(arguments);
  15569. }
  15570. else {
  15571. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15572. module.verbose.apply(console, arguments);
  15573. }
  15574. }
  15575. },
  15576. error: function() {
  15577. if(!settings.silent) {
  15578. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  15579. module.error.apply(console, arguments);
  15580. }
  15581. },
  15582. performance: {
  15583. log: function(message) {
  15584. var
  15585. currentTime,
  15586. executionTime,
  15587. previousTime
  15588. ;
  15589. if(settings.performance) {
  15590. currentTime = new Date().getTime();
  15591. previousTime = time || currentTime;
  15592. executionTime = currentTime - previousTime;
  15593. time = currentTime;
  15594. performance.push({
  15595. 'Name' : message[0],
  15596. 'Arguments' : [].slice.call(message, 1) || '',
  15597. 'Element' : element,
  15598. 'Execution Time' : executionTime
  15599. });
  15600. }
  15601. clearTimeout(module.performance.timer);
  15602. module.performance.timer = setTimeout(module.performance.display, 500);
  15603. },
  15604. display: function() {
  15605. var
  15606. title = settings.name + ':',
  15607. totalTime = 0
  15608. ;
  15609. time = false;
  15610. clearTimeout(module.performance.timer);
  15611. $.each(performance, function(index, data) {
  15612. totalTime += data['Execution Time'];
  15613. });
  15614. title += ' ' + totalTime + 'ms';
  15615. if(moduleSelector) {
  15616. title += ' \'' + moduleSelector + '\'';
  15617. }
  15618. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  15619. console.groupCollapsed(title);
  15620. if(console.table) {
  15621. console.table(performance);
  15622. }
  15623. else {
  15624. $.each(performance, function(index, data) {
  15625. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  15626. });
  15627. }
  15628. console.groupEnd();
  15629. }
  15630. performance = [];
  15631. }
  15632. },
  15633. invoke: function(query, passedArguments, context) {
  15634. var
  15635. object = instance,
  15636. maxDepth,
  15637. found,
  15638. response
  15639. ;
  15640. passedArguments = passedArguments || queryArguments;
  15641. context = element || context;
  15642. if(typeof query == 'string' && object !== undefined) {
  15643. query = query.split(/[\. ]/);
  15644. maxDepth = query.length - 1;
  15645. $.each(query, function(depth, value) {
  15646. var camelCaseValue = (depth != maxDepth)
  15647. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  15648. : query
  15649. ;
  15650. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  15651. object = object[camelCaseValue];
  15652. }
  15653. else if( object[camelCaseValue] !== undefined ) {
  15654. found = object[camelCaseValue];
  15655. return false;
  15656. }
  15657. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  15658. object = object[value];
  15659. }
  15660. else if( object[value] !== undefined ) {
  15661. found = object[value];
  15662. return false;
  15663. }
  15664. else {
  15665. module.error(error.method, query);
  15666. return false;
  15667. }
  15668. });
  15669. }
  15670. if ( $.isFunction( found ) ) {
  15671. response = found.apply(context, passedArguments);
  15672. }
  15673. else if(found !== undefined) {
  15674. response = found;
  15675. }
  15676. if($.isArray(returnedValue)) {
  15677. returnedValue.push(response);
  15678. }
  15679. else if(returnedValue !== undefined) {
  15680. returnedValue = [returnedValue, response];
  15681. }
  15682. else if(response !== undefined) {
  15683. returnedValue = response;
  15684. }
  15685. return found;
  15686. }
  15687. }
  15688. ;
  15689. if(methodInvoked) {
  15690. if(instance === undefined) {
  15691. module.initialize();
  15692. }
  15693. module.invoke(query);
  15694. }
  15695. else {
  15696. if(instance !== undefined) {
  15697. module.invoke('destroy');
  15698. }
  15699. module.initialize();
  15700. }
  15701. });
  15702. return (returnedValue !== undefined)
  15703. ? returnedValue
  15704. : this
  15705. ;
  15706. };
  15707. $.fn.sidebar.settings = {
  15708. name : 'Sidebar',
  15709. namespace : 'sidebar',
  15710. silent : false,
  15711. debug : false,
  15712. verbose : false,
  15713. performance : true,
  15714. transition : 'auto',
  15715. mobileTransition : 'auto',
  15716. defaultTransition : {
  15717. computer: {
  15718. left : 'uncover',
  15719. right : 'uncover',
  15720. top : 'overlay',
  15721. bottom : 'overlay'
  15722. },
  15723. mobile: {
  15724. left : 'uncover',
  15725. right : 'uncover',
  15726. top : 'overlay',
  15727. bottom : 'overlay'
  15728. }
  15729. },
  15730. context : 'body',
  15731. exclusive : false,
  15732. closable : true,
  15733. dimPage : true,
  15734. scrollLock : false,
  15735. returnScroll : false,
  15736. delaySetup : false,
  15737. duration : 500,
  15738. onChange : function(){},
  15739. onShow : function(){},
  15740. onHide : function(){},
  15741. onHidden : function(){},
  15742. onVisible : function(){},
  15743. className : {
  15744. active : 'active',
  15745. animating : 'animating',
  15746. dimmed : 'dimmed',
  15747. ios : 'ios',
  15748. pushable : 'pushable',
  15749. pushed : 'pushed',
  15750. right : 'right',
  15751. top : 'top',
  15752. left : 'left',
  15753. bottom : 'bottom',
  15754. visible : 'visible'
  15755. },
  15756. selector: {
  15757. fixed : '.fixed',
  15758. omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
  15759. pusher : '.pusher',
  15760. sidebar : '.ui.sidebar'
  15761. },
  15762. regExp: {
  15763. ios : /(iPad|iPhone|iPod)/g,
  15764. mobileChrome : /(CriOS)/g,
  15765. 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
  15766. },
  15767. error : {
  15768. method : 'The method you called is not defined.',
  15769. pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
  15770. movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
  15771. overlay : 'The overlay setting is no longer supported, use animation: overlay',
  15772. notFound : 'There were no elements that matched the specified selector'
  15773. }
  15774. };
  15775. })( jQuery, window, document );
  15776. /*!
  15777. * # Semantic UI 2.3.3 - Sticky
  15778. * http://github.com/semantic-org/semantic-ui/
  15779. *
  15780. *
  15781. * Released under the MIT license
  15782. * http://opensource.org/licenses/MIT
  15783. *
  15784. */
  15785. ;(function ($, window, document, undefined) {
  15786. 'use strict';
  15787. window = (typeof window != 'undefined' && window.Math == Math)
  15788. ? window
  15789. : (typeof self != 'undefined' && self.Math == Math)
  15790. ? self
  15791. : Function('return this')()
  15792. ;
  15793. $.fn.sticky = function(parameters) {
  15794. var
  15795. $allModules = $(this),
  15796. moduleSelector = $allModules.selector || '',
  15797. time = new Date().getTime(),
  15798. performance = [],
  15799. query = arguments[0],
  15800. methodInvoked = (typeof query == 'string'),
  15801. queryArguments = [].slice.call(arguments, 1),
  15802. returnedValue
  15803. ;
  15804. $allModules
  15805. .each(function() {
  15806. var
  15807. settings = ( $.isPlainObject(parameters) )
  15808. ? $.extend(true, {}, $.fn.sticky.settings, parameters)
  15809. : $.extend({}, $.fn.sticky.settings),
  15810. className = settings.className,
  15811. namespace = settings.namespace,
  15812. error = settings.error,
  15813. eventNamespace = '.' + namespace,
  15814. moduleNamespace = 'module-' + namespace,
  15815. $module = $(this),
  15816. $window = $(window),
  15817. $scroll = $(settings.scrollContext),
  15818. $container,
  15819. $context,
  15820. selector = $module.selector || '',
  15821. instance = $module.data(moduleNamespace),
  15822. requestAnimationFrame = window.requestAnimationFrame
  15823. || window.mozRequestAnimationFrame
  15824. || window.webkitRequestAnimationFrame
  15825. || window.msRequestAnimationFrame
  15826. || function(callback) { setTimeout(callback, 0); },
  15827. element = this,
  15828. documentObserver,
  15829. observer,
  15830. module
  15831. ;
  15832. module = {
  15833. initialize: function() {
  15834. module.determineContainer();
  15835. module.determineContext();
  15836. module.verbose('Initializing sticky', settings, $container);
  15837. module.save.positions();
  15838. module.checkErrors();
  15839. module.bind.events();
  15840. if(settings.observeChanges) {
  15841. module.observeChanges();
  15842. }
  15843. module.instantiate();
  15844. },
  15845. instantiate: function() {
  15846. module.verbose('Storing instance of module', module);
  15847. instance = module;
  15848. $module
  15849. .data(moduleNamespace, module)
  15850. ;
  15851. },
  15852. destroy: function() {
  15853. module.verbose('Destroying previous instance');
  15854. module.reset();
  15855. if(documentObserver) {
  15856. documentObserver.disconnect();
  15857. }
  15858. if(observer) {
  15859. observer.disconnect();
  15860. }
  15861. $window
  15862. .off('load' + eventNamespace, module.event.load)
  15863. .off('resize' + eventNamespace, module.event.resize)
  15864. ;
  15865. $scroll
  15866. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  15867. ;
  15868. $module.removeData(moduleNamespace);
  15869. },
  15870. observeChanges: function() {
  15871. if('MutationObserver' in window) {
  15872. documentObserver = new MutationObserver(module.event.documentChanged);
  15873. observer = new MutationObserver(module.event.changed);
  15874. documentObserver.observe(document, {
  15875. childList : true,
  15876. subtree : true
  15877. });
  15878. observer.observe(element, {
  15879. childList : true,
  15880. subtree : true
  15881. });
  15882. observer.observe($context[0], {
  15883. childList : true,
  15884. subtree : true
  15885. });
  15886. module.debug('Setting up mutation observer', observer);
  15887. }
  15888. },
  15889. determineContainer: function() {
  15890. if(settings.container) {
  15891. $container = $(settings.container);
  15892. }
  15893. else {
  15894. $container = $module.offsetParent();
  15895. }
  15896. },
  15897. determineContext: function() {
  15898. if(settings.context) {
  15899. $context = $(settings.context);
  15900. }
  15901. else {
  15902. $context = $container;
  15903. }
  15904. if($context.length === 0) {
  15905. module.error(error.invalidContext, settings.context, $module);
  15906. return;
  15907. }
  15908. },
  15909. checkErrors: function() {
  15910. if( module.is.hidden() ) {
  15911. module.error(error.visible, $module);
  15912. }
  15913. if(module.cache.element.height > module.cache.context.height) {
  15914. module.reset();
  15915. module.error(error.elementSize, $module);
  15916. return;
  15917. }
  15918. },
  15919. bind: {
  15920. events: function() {
  15921. $window
  15922. .on('load' + eventNamespace, module.event.load)
  15923. .on('resize' + eventNamespace, module.event.resize)
  15924. ;
  15925. // pub/sub pattern
  15926. $scroll
  15927. .off('scroll' + eventNamespace)
  15928. .on('scroll' + eventNamespace, module.event.scroll)
  15929. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  15930. ;
  15931. }
  15932. },
  15933. event: {
  15934. changed: function(mutations) {
  15935. clearTimeout(module.timer);
  15936. module.timer = setTimeout(function() {
  15937. module.verbose('DOM tree modified, updating sticky menu', mutations);
  15938. module.refresh();
  15939. }, 100);
  15940. },
  15941. documentChanged: function(mutations) {
  15942. [].forEach.call(mutations, function(mutation) {
  15943. if(mutation.removedNodes) {
  15944. [].forEach.call(mutation.removedNodes, function(node) {
  15945. if(node == element || $(node).find(element).length > 0) {
  15946. module.debug('Element removed from DOM, tearing down events');
  15947. module.destroy();
  15948. }
  15949. });
  15950. }
  15951. });
  15952. },
  15953. load: function() {
  15954. module.verbose('Page contents finished loading');
  15955. requestAnimationFrame(module.refresh);
  15956. },
  15957. resize: function() {
  15958. module.verbose('Window resized');
  15959. requestAnimationFrame(module.refresh);
  15960. },
  15961. scroll: function() {
  15962. requestAnimationFrame(function() {
  15963. $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
  15964. });
  15965. },
  15966. scrollchange: function(event, scrollPosition) {
  15967. module.stick(scrollPosition);
  15968. settings.onScroll.call(element);
  15969. }
  15970. },
  15971. refresh: function(hardRefresh) {
  15972. module.reset();
  15973. if(!settings.context) {
  15974. module.determineContext();
  15975. }
  15976. if(hardRefresh) {
  15977. module.determineContainer();
  15978. }
  15979. module.save.positions();
  15980. module.stick();
  15981. settings.onReposition.call(element);
  15982. },
  15983. supports: {
  15984. sticky: function() {
  15985. var
  15986. $element = $('<div/>'),
  15987. element = $element[0]
  15988. ;
  15989. $element.addClass(className.supported);
  15990. return($element.css('position').match('sticky'));
  15991. }
  15992. },
  15993. save: {
  15994. lastScroll: function(scroll) {
  15995. module.lastScroll = scroll;
  15996. },
  15997. elementScroll: function(scroll) {
  15998. module.elementScroll = scroll;
  15999. },
  16000. positions: function() {
  16001. var
  16002. scrollContext = {
  16003. height : $scroll.height()
  16004. },
  16005. element = {
  16006. margin: {
  16007. top : parseInt($module.css('margin-top'), 10),
  16008. bottom : parseInt($module.css('margin-bottom'), 10),
  16009. },
  16010. offset : $module.offset(),
  16011. width : $module.outerWidth(),
  16012. height : $module.outerHeight()
  16013. },
  16014. context = {
  16015. offset : $context.offset(),
  16016. height : $context.outerHeight()
  16017. },
  16018. container = {
  16019. height: $container.outerHeight()
  16020. }
  16021. ;
  16022. if( !module.is.standardScroll() ) {
  16023. module.debug('Non-standard scroll. Removing scroll offset from element offset');
  16024. scrollContext.top = $scroll.scrollTop();
  16025. scrollContext.left = $scroll.scrollLeft();
  16026. element.offset.top += scrollContext.top;
  16027. context.offset.top += scrollContext.top;
  16028. element.offset.left += scrollContext.left;
  16029. context.offset.left += scrollContext.left;
  16030. }
  16031. module.cache = {
  16032. fits : ( (element.height + settings.offset) <= scrollContext.height),
  16033. sameHeight : (element.height == context.height),
  16034. scrollContext : {
  16035. height : scrollContext.height
  16036. },
  16037. element: {
  16038. margin : element.margin,
  16039. top : element.offset.top - element.margin.top,
  16040. left : element.offset.left,
  16041. width : element.width,
  16042. height : element.height,
  16043. bottom : element.offset.top + element.height
  16044. },
  16045. context: {
  16046. top : context.offset.top,
  16047. height : context.height,
  16048. bottom : context.offset.top + context.height
  16049. }
  16050. };
  16051. module.set.containerSize();
  16052. module.stick();
  16053. module.debug('Caching element positions', module.cache);
  16054. }
  16055. },
  16056. get: {
  16057. direction: function(scroll) {
  16058. var
  16059. direction = 'down'
  16060. ;
  16061. scroll = scroll || $scroll.scrollTop();
  16062. if(module.lastScroll !== undefined) {
  16063. if(module.lastScroll < scroll) {
  16064. direction = 'down';
  16065. }
  16066. else if(module.lastScroll > scroll) {
  16067. direction = 'up';
  16068. }
  16069. }
  16070. return direction;
  16071. },
  16072. scrollChange: function(scroll) {
  16073. scroll = scroll || $scroll.scrollTop();
  16074. return (module.lastScroll)
  16075. ? (scroll - module.lastScroll)
  16076. : 0
  16077. ;
  16078. },
  16079. currentElementScroll: function() {
  16080. if(module.elementScroll) {
  16081. return module.elementScroll;
  16082. }
  16083. return ( module.is.top() )
  16084. ? Math.abs(parseInt($module.css('top'), 10)) || 0
  16085. : Math.abs(parseInt($module.css('bottom'), 10)) || 0
  16086. ;
  16087. },
  16088. elementScroll: function(scroll) {
  16089. scroll = scroll || $scroll.scrollTop();
  16090. var
  16091. element = module.cache.element,
  16092. scrollContext = module.cache.scrollContext,
  16093. delta = module.get.scrollChange(scroll),
  16094. maxScroll = (element.height - scrollContext.height + settings.offset),
  16095. elementScroll = module.get.currentElementScroll(),
  16096. possibleScroll = (elementScroll + delta)
  16097. ;
  16098. if(module.cache.fits || possibleScroll < 0) {
  16099. elementScroll = 0;
  16100. }
  16101. else if(possibleScroll > maxScroll ) {
  16102. elementScroll = maxScroll;
  16103. }
  16104. else {
  16105. elementScroll = possibleScroll;
  16106. }
  16107. return elementScroll;
  16108. }
  16109. },
  16110. remove: {
  16111. lastScroll: function() {
  16112. delete module.lastScroll;
  16113. },
  16114. elementScroll: function(scroll) {
  16115. delete module.elementScroll;
  16116. },
  16117. minimumSize: function() {
  16118. $container
  16119. .css('min-height', '')
  16120. ;
  16121. },
  16122. offset: function() {
  16123. $module.css('margin-top', '');
  16124. }
  16125. },
  16126. set: {
  16127. offset: function() {
  16128. module.verbose('Setting offset on element', settings.offset);
  16129. $module
  16130. .css('margin-top', settings.offset)
  16131. ;
  16132. },
  16133. containerSize: function() {
  16134. var
  16135. tagName = $container.get(0).tagName
  16136. ;
  16137. if(tagName === 'HTML' || tagName == 'body') {
  16138. // this can trigger for too many reasons
  16139. //module.error(error.container, tagName, $module);
  16140. module.determineContainer();
  16141. }
  16142. else {
  16143. if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
  16144. module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
  16145. $container.css({
  16146. height: module.cache.context.height
  16147. });
  16148. }
  16149. }
  16150. },
  16151. minimumSize: function() {
  16152. var
  16153. element = module.cache.element
  16154. ;
  16155. $container
  16156. .css('min-height', element.height)
  16157. ;
  16158. },
  16159. scroll: function(scroll) {
  16160. module.debug('Setting scroll on element', scroll);
  16161. if(module.elementScroll == scroll) {
  16162. return;
  16163. }
  16164. if( module.is.top() ) {
  16165. $module
  16166. .css('bottom', '')
  16167. .css('top', -scroll)
  16168. ;
  16169. }
  16170. if( module.is.bottom() ) {
  16171. $module
  16172. .css('top', '')
  16173. .css('bottom', scroll)
  16174. ;
  16175. }
  16176. },
  16177. size: function() {
  16178. if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
  16179. element.style.setProperty('width', module.cache.element.width + 'px', 'important');
  16180. element.style.setProperty('height', module.cache.element.height + 'px', 'important');
  16181. }
  16182. }
  16183. },
  16184. is: {
  16185. standardScroll: function() {
  16186. return ($scroll[0] == window);
  16187. },
  16188. top: function() {
  16189. return $module.hasClass(className.top);
  16190. },
  16191. bottom: function() {
  16192. return $module.hasClass(className.bottom);
  16193. },
  16194. initialPosition: function() {
  16195. return (!module.is.fixed() && !module.is.bound());
  16196. },
  16197. hidden: function() {
  16198. return (!$module.is(':visible'));
  16199. },
  16200. bound: function() {
  16201. return $module.hasClass(className.bound);
  16202. },
  16203. fixed: function() {
  16204. return $module.hasClass(className.fixed);
  16205. }
  16206. },
  16207. stick: function(scroll) {
  16208. var
  16209. cachedPosition = scroll || $scroll.scrollTop(),
  16210. cache = module.cache,
  16211. fits = cache.fits,
  16212. sameHeight = cache.sameHeight,
  16213. element = cache.element,
  16214. scrollContext = cache.scrollContext,
  16215. context = cache.context,
  16216. offset = (module.is.bottom() && settings.pushing)
  16217. ? settings.bottomOffset
  16218. : settings.offset,
  16219. scroll = {
  16220. top : cachedPosition + offset,
  16221. bottom : cachedPosition + offset + scrollContext.height
  16222. },
  16223. direction = module.get.direction(scroll.top),
  16224. elementScroll = (fits)
  16225. ? 0
  16226. : module.get.elementScroll(scroll.top),
  16227. // shorthand
  16228. doesntFit = !fits,
  16229. elementVisible = (element.height !== 0)
  16230. ;
  16231. if(elementVisible && !sameHeight) {
  16232. if( module.is.initialPosition() ) {
  16233. if(scroll.top >= context.bottom) {
  16234. module.debug('Initial element position is bottom of container');
  16235. module.bindBottom();
  16236. }
  16237. else if(scroll.top > element.top) {
  16238. if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  16239. module.debug('Initial element position is bottom of container');
  16240. module.bindBottom();
  16241. }
  16242. else {
  16243. module.debug('Initial element position is fixed');
  16244. module.fixTop();
  16245. }
  16246. }
  16247. }
  16248. else if( module.is.fixed() ) {
  16249. // currently fixed top
  16250. if( module.is.top() ) {
  16251. if( scroll.top <= element.top ) {
  16252. module.debug('Fixed element reached top of container');
  16253. module.setInitialPosition();
  16254. }
  16255. else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  16256. module.debug('Fixed element reached bottom of container');
  16257. module.bindBottom();
  16258. }
  16259. // scroll element if larger than screen
  16260. else if(doesntFit) {
  16261. module.set.scroll(elementScroll);
  16262. module.save.lastScroll(scroll.top);
  16263. module.save.elementScroll(elementScroll);
  16264. }
  16265. }
  16266. // currently fixed bottom
  16267. else if(module.is.bottom() ) {
  16268. // top edge
  16269. if( (scroll.bottom - element.height) <= element.top) {
  16270. module.debug('Bottom fixed rail has reached top of container');
  16271. module.setInitialPosition();
  16272. }
  16273. // bottom edge
  16274. else if(scroll.bottom >= context.bottom) {
  16275. module.debug('Bottom fixed rail has reached bottom of container');
  16276. module.bindBottom();
  16277. }
  16278. // scroll element if larger than screen
  16279. else if(doesntFit) {
  16280. module.set.scroll(elementScroll);
  16281. module.save.lastScroll(scroll.top);
  16282. module.save.elementScroll(elementScroll);
  16283. }
  16284. }
  16285. }
  16286. else if( module.is.bottom() ) {
  16287. if( scroll.top <= element.top ) {
  16288. module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
  16289. module.setInitialPosition();
  16290. }
  16291. else {
  16292. if(settings.pushing) {
  16293. if(module.is.bound() && scroll.bottom <= context.bottom ) {
  16294. module.debug('Fixing bottom attached element to bottom of browser.');
  16295. module.fixBottom();
  16296. }
  16297. }
  16298. else {
  16299. if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
  16300. module.debug('Fixing bottom attached element to top of browser.');
  16301. module.fixTop();
  16302. }
  16303. }
  16304. }
  16305. }
  16306. }
  16307. },
  16308. bindTop: function() {
  16309. module.debug('Binding element to top of parent container');
  16310. module.remove.offset();
  16311. $module
  16312. .css({
  16313. left : '',
  16314. top : '',
  16315. marginBottom : ''
  16316. })
  16317. .removeClass(className.fixed)
  16318. .removeClass(className.bottom)
  16319. .addClass(className.bound)
  16320. .addClass(className.top)
  16321. ;
  16322. settings.onTop.call(element);
  16323. settings.onUnstick.call(element);
  16324. },
  16325. bindBottom: function() {
  16326. module.debug('Binding element to bottom of parent container');
  16327. module.remove.offset();
  16328. $module
  16329. .css({
  16330. left : '',
  16331. top : ''
  16332. })
  16333. .removeClass(className.fixed)
  16334. .removeClass(className.top)
  16335. .addClass(className.bound)
  16336. .addClass(className.bottom)
  16337. ;
  16338. settings.onBottom.call(element);
  16339. settings.onUnstick.call(element);
  16340. },
  16341. setInitialPosition: function() {
  16342. module.debug('Returning to initial position');
  16343. module.unfix();
  16344. module.unbind();
  16345. },
  16346. fixTop: function() {
  16347. module.debug('Fixing element to top of page');
  16348. if(settings.setSize) {
  16349. module.set.size();
  16350. }
  16351. module.set.minimumSize();
  16352. module.set.offset();
  16353. $module
  16354. .css({
  16355. left : module.cache.element.left,
  16356. bottom : '',
  16357. marginBottom : ''
  16358. })
  16359. .removeClass(className.bound)
  16360. .removeClass(className.bottom)
  16361. .addClass(className.fixed)
  16362. .addClass(className.top)
  16363. ;
  16364. settings.onStick.call(element);
  16365. },
  16366. fixBottom: function() {
  16367. module.debug('Sticking element to bottom of page');
  16368. if(settings.setSize) {
  16369. module.set.size();
  16370. }
  16371. module.set.minimumSize();
  16372. module.set.offset();
  16373. $module
  16374. .css({
  16375. left : module.cache.element.left,
  16376. bottom : '',
  16377. marginBottom : ''
  16378. })
  16379. .removeClass(className.bound)
  16380. .removeClass(className.top)
  16381. .addClass(className.fixed)
  16382. .addClass(className.bottom)
  16383. ;
  16384. settings.onStick.call(element);
  16385. },
  16386. unbind: function() {
  16387. if( module.is.bound() ) {
  16388. module.debug('Removing container bound position on element');
  16389. module.remove.offset();
  16390. $module
  16391. .removeClass(className.bound)
  16392. .removeClass(className.top)
  16393. .removeClass(className.bottom)
  16394. ;
  16395. }
  16396. },
  16397. unfix: function() {
  16398. if( module.is.fixed() ) {
  16399. module.debug('Removing fixed position on element');
  16400. module.remove.minimumSize();
  16401. module.remove.offset();
  16402. $module
  16403. .removeClass(className.fixed)
  16404. .removeClass(className.top)
  16405. .removeClass(className.bottom)
  16406. ;
  16407. settings.onUnstick.call(element);
  16408. }
  16409. },
  16410. reset: function() {
  16411. module.debug('Resetting elements position');
  16412. module.unbind();
  16413. module.unfix();
  16414. module.resetCSS();
  16415. module.remove.offset();
  16416. module.remove.lastScroll();
  16417. },
  16418. resetCSS: function() {
  16419. $module
  16420. .css({
  16421. width : '',
  16422. height : ''
  16423. })
  16424. ;
  16425. $container
  16426. .css({
  16427. height: ''
  16428. })
  16429. ;
  16430. },
  16431. setting: function(name, value) {
  16432. if( $.isPlainObject(name) ) {
  16433. $.extend(true, settings, name);
  16434. }
  16435. else if(value !== undefined) {
  16436. settings[name] = value;
  16437. }
  16438. else {
  16439. return settings[name];
  16440. }
  16441. },
  16442. internal: function(name, value) {
  16443. if( $.isPlainObject(name) ) {
  16444. $.extend(true, module, name);
  16445. }
  16446. else if(value !== undefined) {
  16447. module[name] = value;
  16448. }
  16449. else {
  16450. return module[name];
  16451. }
  16452. },
  16453. debug: function() {
  16454. if(!settings.silent && settings.debug) {
  16455. if(settings.performance) {
  16456. module.performance.log(arguments);
  16457. }
  16458. else {
  16459. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16460. module.debug.apply(console, arguments);
  16461. }
  16462. }
  16463. },
  16464. verbose: function() {
  16465. if(!settings.silent && settings.verbose && settings.debug) {
  16466. if(settings.performance) {
  16467. module.performance.log(arguments);
  16468. }
  16469. else {
  16470. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16471. module.verbose.apply(console, arguments);
  16472. }
  16473. }
  16474. },
  16475. error: function() {
  16476. if(!settings.silent) {
  16477. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  16478. module.error.apply(console, arguments);
  16479. }
  16480. },
  16481. performance: {
  16482. log: function(message) {
  16483. var
  16484. currentTime,
  16485. executionTime,
  16486. previousTime
  16487. ;
  16488. if(settings.performance) {
  16489. currentTime = new Date().getTime();
  16490. previousTime = time || currentTime;
  16491. executionTime = currentTime - previousTime;
  16492. time = currentTime;
  16493. performance.push({
  16494. 'Name' : message[0],
  16495. 'Arguments' : [].slice.call(message, 1) || '',
  16496. 'Element' : element,
  16497. 'Execution Time' : executionTime
  16498. });
  16499. }
  16500. clearTimeout(module.performance.timer);
  16501. module.performance.timer = setTimeout(module.performance.display, 0);
  16502. },
  16503. display: function() {
  16504. var
  16505. title = settings.name + ':',
  16506. totalTime = 0
  16507. ;
  16508. time = false;
  16509. clearTimeout(module.performance.timer);
  16510. $.each(performance, function(index, data) {
  16511. totalTime += data['Execution Time'];
  16512. });
  16513. title += ' ' + totalTime + 'ms';
  16514. if(moduleSelector) {
  16515. title += ' \'' + moduleSelector + '\'';
  16516. }
  16517. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  16518. console.groupCollapsed(title);
  16519. if(console.table) {
  16520. console.table(performance);
  16521. }
  16522. else {
  16523. $.each(performance, function(index, data) {
  16524. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  16525. });
  16526. }
  16527. console.groupEnd();
  16528. }
  16529. performance = [];
  16530. }
  16531. },
  16532. invoke: function(query, passedArguments, context) {
  16533. var
  16534. object = instance,
  16535. maxDepth,
  16536. found,
  16537. response
  16538. ;
  16539. passedArguments = passedArguments || queryArguments;
  16540. context = element || context;
  16541. if(typeof query == 'string' && object !== undefined) {
  16542. query = query.split(/[\. ]/);
  16543. maxDepth = query.length - 1;
  16544. $.each(query, function(depth, value) {
  16545. var camelCaseValue = (depth != maxDepth)
  16546. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  16547. : query
  16548. ;
  16549. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  16550. object = object[camelCaseValue];
  16551. }
  16552. else if( object[camelCaseValue] !== undefined ) {
  16553. found = object[camelCaseValue];
  16554. return false;
  16555. }
  16556. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  16557. object = object[value];
  16558. }
  16559. else if( object[value] !== undefined ) {
  16560. found = object[value];
  16561. return false;
  16562. }
  16563. else {
  16564. return false;
  16565. }
  16566. });
  16567. }
  16568. if ( $.isFunction( found ) ) {
  16569. response = found.apply(context, passedArguments);
  16570. }
  16571. else if(found !== undefined) {
  16572. response = found;
  16573. }
  16574. if($.isArray(returnedValue)) {
  16575. returnedValue.push(response);
  16576. }
  16577. else if(returnedValue !== undefined) {
  16578. returnedValue = [returnedValue, response];
  16579. }
  16580. else if(response !== undefined) {
  16581. returnedValue = response;
  16582. }
  16583. return found;
  16584. }
  16585. };
  16586. if(methodInvoked) {
  16587. if(instance === undefined) {
  16588. module.initialize();
  16589. }
  16590. module.invoke(query);
  16591. }
  16592. else {
  16593. if(instance !== undefined) {
  16594. instance.invoke('destroy');
  16595. }
  16596. module.initialize();
  16597. }
  16598. })
  16599. ;
  16600. return (returnedValue !== undefined)
  16601. ? returnedValue
  16602. : this
  16603. ;
  16604. };
  16605. $.fn.sticky.settings = {
  16606. name : 'Sticky',
  16607. namespace : 'sticky',
  16608. silent : false,
  16609. debug : false,
  16610. verbose : true,
  16611. performance : true,
  16612. // whether to stick in the opposite direction on scroll up
  16613. pushing : false,
  16614. context : false,
  16615. container : false,
  16616. // Context to watch scroll events
  16617. scrollContext : window,
  16618. // Offset to adjust scroll
  16619. offset : 0,
  16620. // Offset to adjust scroll when attached to bottom of screen
  16621. bottomOffset : 0,
  16622. // will only set container height if difference between context and container is larger than this number
  16623. jitter : 5,
  16624. // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
  16625. setSize : true,
  16626. // Whether to automatically observe changes with Mutation Observers
  16627. observeChanges : false,
  16628. // Called when position is recalculated
  16629. onReposition : function(){},
  16630. // Called on each scroll
  16631. onScroll : function(){},
  16632. // Called when element is stuck to viewport
  16633. onStick : function(){},
  16634. // Called when element is unstuck from viewport
  16635. onUnstick : function(){},
  16636. // Called when element reaches top of context
  16637. onTop : function(){},
  16638. // Called when element reaches bottom of context
  16639. onBottom : function(){},
  16640. error : {
  16641. container : 'Sticky element must be inside a relative container',
  16642. visible : 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to surpress this warning in production.',
  16643. method : 'The method you called is not defined.',
  16644. invalidContext : 'Context specified does not exist',
  16645. elementSize : 'Sticky element is larger than its container, cannot create sticky.'
  16646. },
  16647. className : {
  16648. bound : 'bound',
  16649. fixed : 'fixed',
  16650. supported : 'native',
  16651. top : 'top',
  16652. bottom : 'bottom'
  16653. }
  16654. };
  16655. })( jQuery, window, document );
  16656. /*!
  16657. * # Semantic UI 2.3.3 - Tab
  16658. * http://github.com/semantic-org/semantic-ui/
  16659. *
  16660. *
  16661. * Released under the MIT license
  16662. * http://opensource.org/licenses/MIT
  16663. *
  16664. */
  16665. ;(function ($, window, document, undefined) {
  16666. 'use strict';
  16667. window = (typeof window != 'undefined' && window.Math == Math)
  16668. ? window
  16669. : (typeof self != 'undefined' && self.Math == Math)
  16670. ? self
  16671. : Function('return this')()
  16672. ;
  16673. $.fn.tab = function(parameters) {
  16674. var
  16675. // use window context if none specified
  16676. $allModules = $.isFunction(this)
  16677. ? $(window)
  16678. : $(this),
  16679. moduleSelector = $allModules.selector || '',
  16680. time = new Date().getTime(),
  16681. performance = [],
  16682. query = arguments[0],
  16683. methodInvoked = (typeof query == 'string'),
  16684. queryArguments = [].slice.call(arguments, 1),
  16685. initializedHistory = false,
  16686. returnedValue
  16687. ;
  16688. $allModules
  16689. .each(function() {
  16690. var
  16691. settings = ( $.isPlainObject(parameters) )
  16692. ? $.extend(true, {}, $.fn.tab.settings, parameters)
  16693. : $.extend({}, $.fn.tab.settings),
  16694. className = settings.className,
  16695. metadata = settings.metadata,
  16696. selector = settings.selector,
  16697. error = settings.error,
  16698. eventNamespace = '.' + settings.namespace,
  16699. moduleNamespace = 'module-' + settings.namespace,
  16700. $module = $(this),
  16701. $context,
  16702. $tabs,
  16703. cache = {},
  16704. firstLoad = true,
  16705. recursionDepth = 0,
  16706. element = this,
  16707. instance = $module.data(moduleNamespace),
  16708. activeTabPath,
  16709. parameterArray,
  16710. module,
  16711. historyEvent
  16712. ;
  16713. module = {
  16714. initialize: function() {
  16715. module.debug('Initializing tab menu item', $module);
  16716. module.fix.callbacks();
  16717. module.determineTabs();
  16718. module.debug('Determining tabs', settings.context, $tabs);
  16719. // set up automatic routing
  16720. if(settings.auto) {
  16721. module.set.auto();
  16722. }
  16723. module.bind.events();
  16724. if(settings.history && !initializedHistory) {
  16725. module.initializeHistory();
  16726. initializedHistory = true;
  16727. }
  16728. module.instantiate();
  16729. },
  16730. instantiate: function () {
  16731. module.verbose('Storing instance of module', module);
  16732. instance = module;
  16733. $module
  16734. .data(moduleNamespace, module)
  16735. ;
  16736. },
  16737. destroy: function() {
  16738. module.debug('Destroying tabs', $module);
  16739. $module
  16740. .removeData(moduleNamespace)
  16741. .off(eventNamespace)
  16742. ;
  16743. },
  16744. bind: {
  16745. events: function() {
  16746. // if using $.tab don't add events
  16747. if( !$.isWindow( element ) ) {
  16748. module.debug('Attaching tab activation events to element', $module);
  16749. $module
  16750. .on('click' + eventNamespace, module.event.click)
  16751. ;
  16752. }
  16753. }
  16754. },
  16755. determineTabs: function() {
  16756. var
  16757. $reference
  16758. ;
  16759. // determine tab context
  16760. if(settings.context === 'parent') {
  16761. if($module.closest(selector.ui).length > 0) {
  16762. $reference = $module.closest(selector.ui);
  16763. module.verbose('Using closest UI element as parent', $reference);
  16764. }
  16765. else {
  16766. $reference = $module;
  16767. }
  16768. $context = $reference.parent();
  16769. module.verbose('Determined parent element for creating context', $context);
  16770. }
  16771. else if(settings.context) {
  16772. $context = $(settings.context);
  16773. module.verbose('Using selector for tab context', settings.context, $context);
  16774. }
  16775. else {
  16776. $context = $('body');
  16777. }
  16778. // find tabs
  16779. if(settings.childrenOnly) {
  16780. $tabs = $context.children(selector.tabs);
  16781. module.debug('Searching tab context children for tabs', $context, $tabs);
  16782. }
  16783. else {
  16784. $tabs = $context.find(selector.tabs);
  16785. module.debug('Searching tab context for tabs', $context, $tabs);
  16786. }
  16787. },
  16788. fix: {
  16789. callbacks: function() {
  16790. if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
  16791. if(parameters.onTabLoad) {
  16792. parameters.onLoad = parameters.onTabLoad;
  16793. delete parameters.onTabLoad;
  16794. module.error(error.legacyLoad, parameters.onLoad);
  16795. }
  16796. if(parameters.onTabInit) {
  16797. parameters.onFirstLoad = parameters.onTabInit;
  16798. delete parameters.onTabInit;
  16799. module.error(error.legacyInit, parameters.onFirstLoad);
  16800. }
  16801. settings = $.extend(true, {}, $.fn.tab.settings, parameters);
  16802. }
  16803. }
  16804. },
  16805. initializeHistory: function() {
  16806. module.debug('Initializing page state');
  16807. if( $.address === undefined ) {
  16808. module.error(error.state);
  16809. return false;
  16810. }
  16811. else {
  16812. if(settings.historyType == 'state') {
  16813. module.debug('Using HTML5 to manage state');
  16814. if(settings.path !== false) {
  16815. $.address
  16816. .history(true)
  16817. .state(settings.path)
  16818. ;
  16819. }
  16820. else {
  16821. module.error(error.path);
  16822. return false;
  16823. }
  16824. }
  16825. $.address
  16826. .bind('change', module.event.history.change)
  16827. ;
  16828. }
  16829. },
  16830. event: {
  16831. click: function(event) {
  16832. var
  16833. tabPath = $(this).data(metadata.tab)
  16834. ;
  16835. if(tabPath !== undefined) {
  16836. if(settings.history) {
  16837. module.verbose('Updating page state', event);
  16838. $.address.value(tabPath);
  16839. }
  16840. else {
  16841. module.verbose('Changing tab', event);
  16842. module.changeTab(tabPath);
  16843. }
  16844. event.preventDefault();
  16845. }
  16846. else {
  16847. module.debug('No tab specified');
  16848. }
  16849. },
  16850. history: {
  16851. change: function(event) {
  16852. var
  16853. tabPath = event.pathNames.join('/') || module.get.initialPath(),
  16854. pageTitle = settings.templates.determineTitle(tabPath) || false
  16855. ;
  16856. module.performance.display();
  16857. module.debug('History change event', tabPath, event);
  16858. historyEvent = event;
  16859. if(tabPath !== undefined) {
  16860. module.changeTab(tabPath);
  16861. }
  16862. if(pageTitle) {
  16863. $.address.title(pageTitle);
  16864. }
  16865. }
  16866. }
  16867. },
  16868. refresh: function() {
  16869. if(activeTabPath) {
  16870. module.debug('Refreshing tab', activeTabPath);
  16871. module.changeTab(activeTabPath);
  16872. }
  16873. },
  16874. cache: {
  16875. read: function(cacheKey) {
  16876. return (cacheKey !== undefined)
  16877. ? cache[cacheKey]
  16878. : false
  16879. ;
  16880. },
  16881. add: function(cacheKey, content) {
  16882. cacheKey = cacheKey || activeTabPath;
  16883. module.debug('Adding cached content for', cacheKey);
  16884. cache[cacheKey] = content;
  16885. },
  16886. remove: function(cacheKey) {
  16887. cacheKey = cacheKey || activeTabPath;
  16888. module.debug('Removing cached content for', cacheKey);
  16889. delete cache[cacheKey];
  16890. }
  16891. },
  16892. set: {
  16893. auto: function() {
  16894. var
  16895. url = (typeof settings.path == 'string')
  16896. ? settings.path.replace(/\/$/, '') + '/{$tab}'
  16897. : '/{$tab}'
  16898. ;
  16899. module.verbose('Setting up automatic tab retrieval from server', url);
  16900. if($.isPlainObject(settings.apiSettings)) {
  16901. settings.apiSettings.url = url;
  16902. }
  16903. else {
  16904. settings.apiSettings = {
  16905. url: url
  16906. };
  16907. }
  16908. },
  16909. loading: function(tabPath) {
  16910. var
  16911. $tab = module.get.tabElement(tabPath),
  16912. isLoading = $tab.hasClass(className.loading)
  16913. ;
  16914. if(!isLoading) {
  16915. module.verbose('Setting loading state for', $tab);
  16916. $tab
  16917. .addClass(className.loading)
  16918. .siblings($tabs)
  16919. .removeClass(className.active + ' ' + className.loading)
  16920. ;
  16921. if($tab.length > 0) {
  16922. settings.onRequest.call($tab[0], tabPath);
  16923. }
  16924. }
  16925. },
  16926. state: function(state) {
  16927. $.address.value(state);
  16928. }
  16929. },
  16930. changeTab: function(tabPath) {
  16931. var
  16932. pushStateAvailable = (window.history && window.history.pushState),
  16933. shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
  16934. remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
  16935. // only add default path if not remote content
  16936. pathArray = (remoteContent && !shouldIgnoreLoad)
  16937. ? module.utilities.pathToArray(tabPath)
  16938. : module.get.defaultPathArray(tabPath)
  16939. ;
  16940. tabPath = module.utilities.arrayToPath(pathArray);
  16941. $.each(pathArray, function(index, tab) {
  16942. var
  16943. currentPathArray = pathArray.slice(0, index + 1),
  16944. currentPath = module.utilities.arrayToPath(currentPathArray),
  16945. isTab = module.is.tab(currentPath),
  16946. isLastIndex = (index + 1 == pathArray.length),
  16947. $tab = module.get.tabElement(currentPath),
  16948. $anchor,
  16949. nextPathArray,
  16950. nextPath,
  16951. isLastTab
  16952. ;
  16953. module.verbose('Looking for tab', tab);
  16954. if(isTab) {
  16955. module.verbose('Tab was found', tab);
  16956. // scope up
  16957. activeTabPath = currentPath;
  16958. parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
  16959. if(isLastIndex) {
  16960. isLastTab = true;
  16961. }
  16962. else {
  16963. nextPathArray = pathArray.slice(0, index + 2);
  16964. nextPath = module.utilities.arrayToPath(nextPathArray);
  16965. isLastTab = ( !module.is.tab(nextPath) );
  16966. if(isLastTab) {
  16967. module.verbose('Tab parameters found', nextPathArray);
  16968. }
  16969. }
  16970. if(isLastTab && remoteContent) {
  16971. if(!shouldIgnoreLoad) {
  16972. module.activate.navigation(currentPath);
  16973. module.fetch.content(currentPath, tabPath);
  16974. }
  16975. else {
  16976. module.debug('Ignoring remote content on first tab load', currentPath);
  16977. firstLoad = false;
  16978. module.cache.add(tabPath, $tab.html());
  16979. module.activate.all(currentPath);
  16980. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16981. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16982. }
  16983. return false;
  16984. }
  16985. else {
  16986. module.debug('Opened local tab', currentPath);
  16987. module.activate.all(currentPath);
  16988. if( !module.cache.read(currentPath) ) {
  16989. module.cache.add(currentPath, true);
  16990. module.debug('First time tab loaded calling tab init');
  16991. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16992. }
  16993. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16994. }
  16995. }
  16996. else if(tabPath.search('/') == -1 && tabPath !== '') {
  16997. // look for in page anchor
  16998. $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
  16999. currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
  17000. $tab = module.get.tabElement(currentPath);
  17001. // if anchor exists use parent tab
  17002. if($anchor && $anchor.length > 0 && currentPath) {
  17003. module.debug('Anchor link used, opening parent tab', $tab, $anchor);
  17004. if( !$tab.hasClass(className.active) ) {
  17005. setTimeout(function() {
  17006. module.scrollTo($anchor);
  17007. }, 0);
  17008. }
  17009. module.activate.all(currentPath);
  17010. if( !module.cache.read(currentPath) ) {
  17011. module.cache.add(currentPath, true);
  17012. module.debug('First time tab loaded calling tab init');
  17013. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  17014. }
  17015. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  17016. return false;
  17017. }
  17018. }
  17019. else {
  17020. module.error(error.missingTab, $module, $context, currentPath);
  17021. return false;
  17022. }
  17023. });
  17024. },
  17025. scrollTo: function($element) {
  17026. var
  17027. scrollOffset = ($element && $element.length > 0)
  17028. ? $element.offset().top
  17029. : false
  17030. ;
  17031. if(scrollOffset !== false) {
  17032. module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
  17033. $(document).scrollTop(scrollOffset);
  17034. }
  17035. },
  17036. update: {
  17037. content: function(tabPath, html, evaluateScripts) {
  17038. var
  17039. $tab = module.get.tabElement(tabPath),
  17040. tab = $tab[0]
  17041. ;
  17042. evaluateScripts = (evaluateScripts !== undefined)
  17043. ? evaluateScripts
  17044. : settings.evaluateScripts
  17045. ;
  17046. if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') {
  17047. $tab
  17048. .empty()
  17049. .append($(html).clone(true))
  17050. ;
  17051. }
  17052. else {
  17053. if(evaluateScripts) {
  17054. module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
  17055. $tab.html(html);
  17056. }
  17057. else {
  17058. module.debug('Updating HTML', tabPath, html);
  17059. tab.innerHTML = html;
  17060. }
  17061. }
  17062. }
  17063. },
  17064. fetch: {
  17065. content: function(tabPath, fullTabPath) {
  17066. var
  17067. $tab = module.get.tabElement(tabPath),
  17068. apiSettings = {
  17069. dataType : 'html',
  17070. encodeParameters : false,
  17071. on : 'now',
  17072. cache : settings.alwaysRefresh,
  17073. headers : {
  17074. 'X-Remote': true
  17075. },
  17076. onSuccess : function(response) {
  17077. if(settings.cacheType == 'response') {
  17078. module.cache.add(fullTabPath, response);
  17079. }
  17080. module.update.content(tabPath, response);
  17081. if(tabPath == activeTabPath) {
  17082. module.debug('Content loaded', tabPath);
  17083. module.activate.tab(tabPath);
  17084. }
  17085. else {
  17086. module.debug('Content loaded in background', tabPath);
  17087. }
  17088. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17089. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17090. if(settings.loadOnce) {
  17091. module.cache.add(fullTabPath, true);
  17092. }
  17093. else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) {
  17094. setTimeout(function() {
  17095. var
  17096. $clone = $tab.children().clone(true)
  17097. ;
  17098. $clone = $clone.not('script');
  17099. module.cache.add(fullTabPath, $clone);
  17100. }, 0);
  17101. }
  17102. else {
  17103. module.cache.add(fullTabPath, $tab.html());
  17104. }
  17105. },
  17106. urlData: {
  17107. tab: fullTabPath
  17108. }
  17109. },
  17110. request = $tab.api('get request') || false,
  17111. existingRequest = ( request && request.state() === 'pending' ),
  17112. requestSettings,
  17113. cachedContent
  17114. ;
  17115. fullTabPath = fullTabPath || tabPath;
  17116. cachedContent = module.cache.read(fullTabPath);
  17117. if(settings.cache && cachedContent) {
  17118. module.activate.tab(tabPath);
  17119. module.debug('Adding cached content', fullTabPath);
  17120. if(!settings.loadOnce) {
  17121. if(settings.evaluateScripts == 'once') {
  17122. module.update.content(tabPath, cachedContent, false);
  17123. }
  17124. else {
  17125. module.update.content(tabPath, cachedContent);
  17126. }
  17127. }
  17128. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17129. }
  17130. else if(existingRequest) {
  17131. module.set.loading(tabPath);
  17132. module.debug('Content is already loading', fullTabPath);
  17133. }
  17134. else if($.api !== undefined) {
  17135. requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
  17136. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  17137. module.set.loading(tabPath);
  17138. $tab.api(requestSettings);
  17139. }
  17140. else {
  17141. module.error(error.api);
  17142. }
  17143. }
  17144. },
  17145. activate: {
  17146. all: function(tabPath) {
  17147. module.activate.tab(tabPath);
  17148. module.activate.navigation(tabPath);
  17149. },
  17150. tab: function(tabPath) {
  17151. var
  17152. $tab = module.get.tabElement(tabPath),
  17153. $deactiveTabs = (settings.deactivate == 'siblings')
  17154. ? $tab.siblings($tabs)
  17155. : $tabs.not($tab),
  17156. isActive = $tab.hasClass(className.active)
  17157. ;
  17158. module.verbose('Showing tab content for', $tab);
  17159. if(!isActive) {
  17160. $tab
  17161. .addClass(className.active)
  17162. ;
  17163. $deactiveTabs
  17164. .removeClass(className.active + ' ' + className.loading)
  17165. ;
  17166. if($tab.length > 0) {
  17167. settings.onVisible.call($tab[0], tabPath);
  17168. }
  17169. }
  17170. },
  17171. navigation: function(tabPath) {
  17172. var
  17173. $navigation = module.get.navElement(tabPath),
  17174. $deactiveNavigation = (settings.deactivate == 'siblings')
  17175. ? $navigation.siblings($allModules)
  17176. : $allModules.not($navigation),
  17177. isActive = $navigation.hasClass(className.active)
  17178. ;
  17179. module.verbose('Activating tab navigation for', $navigation, tabPath);
  17180. if(!isActive) {
  17181. $navigation
  17182. .addClass(className.active)
  17183. ;
  17184. $deactiveNavigation
  17185. .removeClass(className.active + ' ' + className.loading)
  17186. ;
  17187. }
  17188. }
  17189. },
  17190. deactivate: {
  17191. all: function() {
  17192. module.deactivate.navigation();
  17193. module.deactivate.tabs();
  17194. },
  17195. navigation: function() {
  17196. $allModules
  17197. .removeClass(className.active)
  17198. ;
  17199. },
  17200. tabs: function() {
  17201. $tabs
  17202. .removeClass(className.active + ' ' + className.loading)
  17203. ;
  17204. }
  17205. },
  17206. is: {
  17207. tab: function(tabName) {
  17208. return (tabName !== undefined)
  17209. ? ( module.get.tabElement(tabName).length > 0 )
  17210. : false
  17211. ;
  17212. }
  17213. },
  17214. get: {
  17215. initialPath: function() {
  17216. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  17217. },
  17218. path: function() {
  17219. return $.address.value();
  17220. },
  17221. // adds default tabs to tab path
  17222. defaultPathArray: function(tabPath) {
  17223. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  17224. },
  17225. defaultPath: function(tabPath) {
  17226. var
  17227. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0),
  17228. defaultTab = $defaultNav.data(metadata.tab) || false
  17229. ;
  17230. if( defaultTab ) {
  17231. module.debug('Found default tab', defaultTab);
  17232. if(recursionDepth < settings.maxDepth) {
  17233. recursionDepth++;
  17234. return module.get.defaultPath(defaultTab);
  17235. }
  17236. module.error(error.recursion);
  17237. }
  17238. else {
  17239. module.debug('No default tabs found for', tabPath, $tabs);
  17240. }
  17241. recursionDepth = 0;
  17242. return tabPath;
  17243. },
  17244. navElement: function(tabPath) {
  17245. tabPath = tabPath || activeTabPath;
  17246. return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  17247. },
  17248. tabElement: function(tabPath) {
  17249. var
  17250. $fullPathTab,
  17251. $simplePathTab,
  17252. tabPathArray,
  17253. lastTab
  17254. ;
  17255. tabPath = tabPath || activeTabPath;
  17256. tabPathArray = module.utilities.pathToArray(tabPath);
  17257. lastTab = module.utilities.last(tabPathArray);
  17258. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  17259. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]');
  17260. return ($fullPathTab.length > 0)
  17261. ? $fullPathTab
  17262. : $simplePathTab
  17263. ;
  17264. },
  17265. tab: function() {
  17266. return activeTabPath;
  17267. }
  17268. },
  17269. utilities: {
  17270. filterArray: function(keepArray, removeArray) {
  17271. return $.grep(keepArray, function(keepValue) {
  17272. return ( $.inArray(keepValue, removeArray) == -1);
  17273. });
  17274. },
  17275. last: function(array) {
  17276. return $.isArray(array)
  17277. ? array[ array.length - 1]
  17278. : false
  17279. ;
  17280. },
  17281. pathToArray: function(pathName) {
  17282. if(pathName === undefined) {
  17283. pathName = activeTabPath;
  17284. }
  17285. return typeof pathName == 'string'
  17286. ? pathName.split('/')
  17287. : [pathName]
  17288. ;
  17289. },
  17290. arrayToPath: function(pathArray) {
  17291. return $.isArray(pathArray)
  17292. ? pathArray.join('/')
  17293. : false
  17294. ;
  17295. }
  17296. },
  17297. setting: function(name, value) {
  17298. module.debug('Changing setting', name, value);
  17299. if( $.isPlainObject(name) ) {
  17300. $.extend(true, settings, name);
  17301. }
  17302. else if(value !== undefined) {
  17303. if($.isPlainObject(settings[name])) {
  17304. $.extend(true, settings[name], value);
  17305. }
  17306. else {
  17307. settings[name] = value;
  17308. }
  17309. }
  17310. else {
  17311. return settings[name];
  17312. }
  17313. },
  17314. internal: function(name, value) {
  17315. if( $.isPlainObject(name) ) {
  17316. $.extend(true, module, name);
  17317. }
  17318. else if(value !== undefined) {
  17319. module[name] = value;
  17320. }
  17321. else {
  17322. return module[name];
  17323. }
  17324. },
  17325. debug: function() {
  17326. if(!settings.silent && settings.debug) {
  17327. if(settings.performance) {
  17328. module.performance.log(arguments);
  17329. }
  17330. else {
  17331. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17332. module.debug.apply(console, arguments);
  17333. }
  17334. }
  17335. },
  17336. verbose: function() {
  17337. if(!settings.silent && settings.verbose && settings.debug) {
  17338. if(settings.performance) {
  17339. module.performance.log(arguments);
  17340. }
  17341. else {
  17342. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17343. module.verbose.apply(console, arguments);
  17344. }
  17345. }
  17346. },
  17347. error: function() {
  17348. if(!settings.silent) {
  17349. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  17350. module.error.apply(console, arguments);
  17351. }
  17352. },
  17353. performance: {
  17354. log: function(message) {
  17355. var
  17356. currentTime,
  17357. executionTime,
  17358. previousTime
  17359. ;
  17360. if(settings.performance) {
  17361. currentTime = new Date().getTime();
  17362. previousTime = time || currentTime;
  17363. executionTime = currentTime - previousTime;
  17364. time = currentTime;
  17365. performance.push({
  17366. 'Name' : message[0],
  17367. 'Arguments' : [].slice.call(message, 1) || '',
  17368. 'Element' : element,
  17369. 'Execution Time' : executionTime
  17370. });
  17371. }
  17372. clearTimeout(module.performance.timer);
  17373. module.performance.timer = setTimeout(module.performance.display, 500);
  17374. },
  17375. display: function() {
  17376. var
  17377. title = settings.name + ':',
  17378. totalTime = 0
  17379. ;
  17380. time = false;
  17381. clearTimeout(module.performance.timer);
  17382. $.each(performance, function(index, data) {
  17383. totalTime += data['Execution Time'];
  17384. });
  17385. title += ' ' + totalTime + 'ms';
  17386. if(moduleSelector) {
  17387. title += ' \'' + moduleSelector + '\'';
  17388. }
  17389. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  17390. console.groupCollapsed(title);
  17391. if(console.table) {
  17392. console.table(performance);
  17393. }
  17394. else {
  17395. $.each(performance, function(index, data) {
  17396. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  17397. });
  17398. }
  17399. console.groupEnd();
  17400. }
  17401. performance = [];
  17402. }
  17403. },
  17404. invoke: function(query, passedArguments, context) {
  17405. var
  17406. object = instance,
  17407. maxDepth,
  17408. found,
  17409. response
  17410. ;
  17411. passedArguments = passedArguments || queryArguments;
  17412. context = element || context;
  17413. if(typeof query == 'string' && object !== undefined) {
  17414. query = query.split(/[\. ]/);
  17415. maxDepth = query.length - 1;
  17416. $.each(query, function(depth, value) {
  17417. var camelCaseValue = (depth != maxDepth)
  17418. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  17419. : query
  17420. ;
  17421. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  17422. object = object[camelCaseValue];
  17423. }
  17424. else if( object[camelCaseValue] !== undefined ) {
  17425. found = object[camelCaseValue];
  17426. return false;
  17427. }
  17428. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  17429. object = object[value];
  17430. }
  17431. else if( object[value] !== undefined ) {
  17432. found = object[value];
  17433. return false;
  17434. }
  17435. else {
  17436. module.error(error.method, query);
  17437. return false;
  17438. }
  17439. });
  17440. }
  17441. if ( $.isFunction( found ) ) {
  17442. response = found.apply(context, passedArguments);
  17443. }
  17444. else if(found !== undefined) {
  17445. response = found;
  17446. }
  17447. if($.isArray(returnedValue)) {
  17448. returnedValue.push(response);
  17449. }
  17450. else if(returnedValue !== undefined) {
  17451. returnedValue = [returnedValue, response];
  17452. }
  17453. else if(response !== undefined) {
  17454. returnedValue = response;
  17455. }
  17456. return found;
  17457. }
  17458. };
  17459. if(methodInvoked) {
  17460. if(instance === undefined) {
  17461. module.initialize();
  17462. }
  17463. module.invoke(query);
  17464. }
  17465. else {
  17466. if(instance !== undefined) {
  17467. instance.invoke('destroy');
  17468. }
  17469. module.initialize();
  17470. }
  17471. })
  17472. ;
  17473. return (returnedValue !== undefined)
  17474. ? returnedValue
  17475. : this
  17476. ;
  17477. };
  17478. // shortcut for tabbed content with no defined navigation
  17479. $.tab = function() {
  17480. $(window).tab.apply(this, arguments);
  17481. };
  17482. $.fn.tab.settings = {
  17483. name : 'Tab',
  17484. namespace : 'tab',
  17485. silent : false,
  17486. debug : false,
  17487. verbose : false,
  17488. performance : true,
  17489. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  17490. history : false, // use browser history
  17491. historyType : 'hash', // #/ or html5 state
  17492. path : false, // base path of url
  17493. context : false, // specify a context that tabs must appear inside
  17494. childrenOnly : false, // use only tabs that are children of context
  17495. maxDepth : 25, // max depth a tab can be nested
  17496. deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together
  17497. alwaysRefresh : false, // load tab content new every tab click
  17498. cache : true, // cache the content requests to pull locally
  17499. loadOnce : false, // Whether tab data should only be loaded once when using remote content
  17500. cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute
  17501. ignoreFirstLoad : false, // don't load remote content on first load
  17502. apiSettings : false, // settings for api call
  17503. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  17504. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  17505. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  17506. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  17507. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  17508. templates : {
  17509. determineTitle: function(tabArray) {} // returns page title for path
  17510. },
  17511. error: {
  17512. api : 'You attempted to load content without API module',
  17513. method : 'The method you called is not defined',
  17514. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  17515. noContent : 'The tab you specified is missing a content url.',
  17516. path : 'History enabled, but no path was specified',
  17517. recursion : 'Max recursive depth reached',
  17518. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  17519. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  17520. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  17521. },
  17522. metadata : {
  17523. tab : 'tab',
  17524. loaded : 'loaded',
  17525. promise: 'promise'
  17526. },
  17527. className : {
  17528. loading : 'loading',
  17529. active : 'active'
  17530. },
  17531. selector : {
  17532. tabs : '.ui.tab',
  17533. ui : '.ui'
  17534. }
  17535. };
  17536. })( jQuery, window, document );
  17537. /*!
  17538. * # Semantic UI 2.3.3 - Transition
  17539. * http://github.com/semantic-org/semantic-ui/
  17540. *
  17541. *
  17542. * Released under the MIT license
  17543. * http://opensource.org/licenses/MIT
  17544. *
  17545. */
  17546. ;(function ($, window, document, undefined) {
  17547. 'use strict';
  17548. window = (typeof window != 'undefined' && window.Math == Math)
  17549. ? window
  17550. : (typeof self != 'undefined' && self.Math == Math)
  17551. ? self
  17552. : Function('return this')()
  17553. ;
  17554. $.fn.transition = function() {
  17555. var
  17556. $allModules = $(this),
  17557. moduleSelector = $allModules.selector || '',
  17558. time = new Date().getTime(),
  17559. performance = [],
  17560. moduleArguments = arguments,
  17561. query = moduleArguments[0],
  17562. queryArguments = [].slice.call(arguments, 1),
  17563. methodInvoked = (typeof query === 'string'),
  17564. requestAnimationFrame = window.requestAnimationFrame
  17565. || window.mozRequestAnimationFrame
  17566. || window.webkitRequestAnimationFrame
  17567. || window.msRequestAnimationFrame
  17568. || function(callback) { setTimeout(callback, 0); },
  17569. returnedValue
  17570. ;
  17571. $allModules
  17572. .each(function(index) {
  17573. var
  17574. $module = $(this),
  17575. element = this,
  17576. // set at run time
  17577. settings,
  17578. instance,
  17579. error,
  17580. className,
  17581. metadata,
  17582. animationEnd,
  17583. animationName,
  17584. namespace,
  17585. moduleNamespace,
  17586. eventNamespace,
  17587. module
  17588. ;
  17589. module = {
  17590. initialize: function() {
  17591. // get full settings
  17592. settings = module.get.settings.apply(element, moduleArguments);
  17593. // shorthand
  17594. className = settings.className;
  17595. error = settings.error;
  17596. metadata = settings.metadata;
  17597. // define namespace
  17598. eventNamespace = '.' + settings.namespace;
  17599. moduleNamespace = 'module-' + settings.namespace;
  17600. instance = $module.data(moduleNamespace) || module;
  17601. // get vendor specific events
  17602. animationEnd = module.get.animationEndEvent();
  17603. if(methodInvoked) {
  17604. methodInvoked = module.invoke(query);
  17605. }
  17606. // method not invoked, lets run an animation
  17607. if(methodInvoked === false) {
  17608. module.verbose('Converted arguments into settings object', settings);
  17609. if(settings.interval) {
  17610. module.delay(settings.animate);
  17611. }
  17612. else {
  17613. module.animate();
  17614. }
  17615. module.instantiate();
  17616. }
  17617. },
  17618. instantiate: function() {
  17619. module.verbose('Storing instance of module', module);
  17620. instance = module;
  17621. $module
  17622. .data(moduleNamespace, instance)
  17623. ;
  17624. },
  17625. destroy: function() {
  17626. module.verbose('Destroying previous module for', element);
  17627. $module
  17628. .removeData(moduleNamespace)
  17629. ;
  17630. },
  17631. refresh: function() {
  17632. module.verbose('Refreshing display type on next animation');
  17633. delete module.displayType;
  17634. },
  17635. forceRepaint: function() {
  17636. module.verbose('Forcing element repaint');
  17637. var
  17638. $parentElement = $module.parent(),
  17639. $nextElement = $module.next()
  17640. ;
  17641. if($nextElement.length === 0) {
  17642. $module.detach().appendTo($parentElement);
  17643. }
  17644. else {
  17645. $module.detach().insertBefore($nextElement);
  17646. }
  17647. },
  17648. repaint: function() {
  17649. module.verbose('Repainting element');
  17650. var
  17651. fakeAssignment = element.offsetWidth
  17652. ;
  17653. },
  17654. delay: function(interval) {
  17655. var
  17656. direction = module.get.animationDirection(),
  17657. shouldReverse,
  17658. delay
  17659. ;
  17660. if(!direction) {
  17661. direction = module.can.transition()
  17662. ? module.get.direction()
  17663. : 'static'
  17664. ;
  17665. }
  17666. interval = (interval !== undefined)
  17667. ? interval
  17668. : settings.interval
  17669. ;
  17670. shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
  17671. delay = (shouldReverse || settings.reverse == true)
  17672. ? ($allModules.length - index) * settings.interval
  17673. : index * settings.interval
  17674. ;
  17675. module.debug('Delaying animation by', delay);
  17676. setTimeout(module.animate, delay);
  17677. },
  17678. animate: function(overrideSettings) {
  17679. settings = overrideSettings || settings;
  17680. if(!module.is.supported()) {
  17681. module.error(error.support);
  17682. return false;
  17683. }
  17684. module.debug('Preparing animation', settings.animation);
  17685. if(module.is.animating()) {
  17686. if(settings.queue) {
  17687. if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
  17688. module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
  17689. }
  17690. else {
  17691. module.queue(settings.animation);
  17692. }
  17693. return false;
  17694. }
  17695. else if(!settings.allowRepeats && module.is.occurring()) {
  17696. module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
  17697. return false;
  17698. }
  17699. else {
  17700. module.debug('New animation started, completing previous early', settings.animation);
  17701. instance.complete();
  17702. }
  17703. }
  17704. if( module.can.animate() ) {
  17705. module.set.animating(settings.animation);
  17706. }
  17707. else {
  17708. module.error(error.noAnimation, settings.animation, element);
  17709. }
  17710. },
  17711. reset: function() {
  17712. module.debug('Resetting animation to beginning conditions');
  17713. module.remove.animationCallbacks();
  17714. module.restore.conditions();
  17715. module.remove.animating();
  17716. },
  17717. queue: function(animation) {
  17718. module.debug('Queueing animation of', animation);
  17719. module.queuing = true;
  17720. $module
  17721. .one(animationEnd + '.queue' + eventNamespace, function() {
  17722. module.queuing = false;
  17723. module.repaint();
  17724. module.animate.apply(this, settings);
  17725. })
  17726. ;
  17727. },
  17728. complete: function (event) {
  17729. module.debug('Animation complete', settings.animation);
  17730. module.remove.completeCallback();
  17731. module.remove.failSafe();
  17732. if(!module.is.looping()) {
  17733. if( module.is.outward() ) {
  17734. module.verbose('Animation is outward, hiding element');
  17735. module.restore.conditions();
  17736. module.hide();
  17737. }
  17738. else if( module.is.inward() ) {
  17739. module.verbose('Animation is outward, showing element');
  17740. module.restore.conditions();
  17741. module.show();
  17742. }
  17743. else {
  17744. module.verbose('Static animation completed');
  17745. module.restore.conditions();
  17746. settings.onComplete.call(element);
  17747. }
  17748. }
  17749. },
  17750. force: {
  17751. visible: function() {
  17752. var
  17753. style = $module.attr('style'),
  17754. userStyle = module.get.userStyle(),
  17755. displayType = module.get.displayType(),
  17756. overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
  17757. currentDisplay = $module.css('display'),
  17758. emptyStyle = (style === undefined || style === '')
  17759. ;
  17760. if(currentDisplay !== displayType) {
  17761. module.verbose('Overriding default display to show element', displayType);
  17762. $module
  17763. .attr('style', overrideStyle)
  17764. ;
  17765. }
  17766. else if(emptyStyle) {
  17767. $module.removeAttr('style');
  17768. }
  17769. },
  17770. hidden: function() {
  17771. var
  17772. style = $module.attr('style'),
  17773. currentDisplay = $module.css('display'),
  17774. emptyStyle = (style === undefined || style === '')
  17775. ;
  17776. if(currentDisplay !== 'none' && !module.is.hidden()) {
  17777. module.verbose('Overriding default display to hide element');
  17778. $module
  17779. .css('display', 'none')
  17780. ;
  17781. }
  17782. else if(emptyStyle) {
  17783. $module
  17784. .removeAttr('style')
  17785. ;
  17786. }
  17787. }
  17788. },
  17789. has: {
  17790. direction: function(animation) {
  17791. var
  17792. hasDirection = false
  17793. ;
  17794. animation = animation || settings.animation;
  17795. if(typeof animation === 'string') {
  17796. animation = animation.split(' ');
  17797. $.each(animation, function(index, word){
  17798. if(word === className.inward || word === className.outward) {
  17799. hasDirection = true;
  17800. }
  17801. });
  17802. }
  17803. return hasDirection;
  17804. },
  17805. inlineDisplay: function() {
  17806. var
  17807. style = $module.attr('style') || ''
  17808. ;
  17809. return $.isArray(style.match(/display.*?;/, ''));
  17810. }
  17811. },
  17812. set: {
  17813. animating: function(animation) {
  17814. var
  17815. animationClass,
  17816. direction
  17817. ;
  17818. // remove previous callbacks
  17819. module.remove.completeCallback();
  17820. // determine exact animation
  17821. animation = animation || settings.animation;
  17822. animationClass = module.get.animationClass(animation);
  17823. // save animation class in cache to restore class names
  17824. module.save.animation(animationClass);
  17825. // override display if necessary so animation appears visibly
  17826. module.force.visible();
  17827. module.remove.hidden();
  17828. module.remove.direction();
  17829. module.start.animation(animationClass);
  17830. },
  17831. duration: function(animationName, duration) {
  17832. duration = duration || settings.duration;
  17833. duration = (typeof duration == 'number')
  17834. ? duration + 'ms'
  17835. : duration
  17836. ;
  17837. if(duration || duration === 0) {
  17838. module.verbose('Setting animation duration', duration);
  17839. $module
  17840. .css({
  17841. 'animation-duration': duration
  17842. })
  17843. ;
  17844. }
  17845. },
  17846. direction: function(direction) {
  17847. direction = direction || module.get.direction();
  17848. if(direction == className.inward) {
  17849. module.set.inward();
  17850. }
  17851. else {
  17852. module.set.outward();
  17853. }
  17854. },
  17855. looping: function() {
  17856. module.debug('Transition set to loop');
  17857. $module
  17858. .addClass(className.looping)
  17859. ;
  17860. },
  17861. hidden: function() {
  17862. $module
  17863. .addClass(className.transition)
  17864. .addClass(className.hidden)
  17865. ;
  17866. },
  17867. inward: function() {
  17868. module.debug('Setting direction to inward');
  17869. $module
  17870. .removeClass(className.outward)
  17871. .addClass(className.inward)
  17872. ;
  17873. },
  17874. outward: function() {
  17875. module.debug('Setting direction to outward');
  17876. $module
  17877. .removeClass(className.inward)
  17878. .addClass(className.outward)
  17879. ;
  17880. },
  17881. visible: function() {
  17882. $module
  17883. .addClass(className.transition)
  17884. .addClass(className.visible)
  17885. ;
  17886. }
  17887. },
  17888. start: {
  17889. animation: function(animationClass) {
  17890. animationClass = animationClass || module.get.animationClass();
  17891. module.debug('Starting tween', animationClass);
  17892. $module
  17893. .addClass(animationClass)
  17894. .one(animationEnd + '.complete' + eventNamespace, module.complete)
  17895. ;
  17896. if(settings.useFailSafe) {
  17897. module.add.failSafe();
  17898. }
  17899. module.set.duration(settings.duration);
  17900. settings.onStart.call(element);
  17901. }
  17902. },
  17903. save: {
  17904. animation: function(animation) {
  17905. if(!module.cache) {
  17906. module.cache = {};
  17907. }
  17908. module.cache.animation = animation;
  17909. },
  17910. displayType: function(displayType) {
  17911. if(displayType !== 'none') {
  17912. $module.data(metadata.displayType, displayType);
  17913. }
  17914. },
  17915. transitionExists: function(animation, exists) {
  17916. $.fn.transition.exists[animation] = exists;
  17917. module.verbose('Saving existence of transition', animation, exists);
  17918. }
  17919. },
  17920. restore: {
  17921. conditions: function() {
  17922. var
  17923. animation = module.get.currentAnimation()
  17924. ;
  17925. if(animation) {
  17926. $module
  17927. .removeClass(animation)
  17928. ;
  17929. module.verbose('Removing animation class', module.cache);
  17930. }
  17931. module.remove.duration();
  17932. }
  17933. },
  17934. add: {
  17935. failSafe: function() {
  17936. var
  17937. duration = module.get.duration()
  17938. ;
  17939. module.timer = setTimeout(function() {
  17940. $module.triggerHandler(animationEnd);
  17941. }, duration + settings.failSafeDelay);
  17942. module.verbose('Adding fail safe timer', module.timer);
  17943. }
  17944. },
  17945. remove: {
  17946. animating: function() {
  17947. $module.removeClass(className.animating);
  17948. },
  17949. animationCallbacks: function() {
  17950. module.remove.queueCallback();
  17951. module.remove.completeCallback();
  17952. },
  17953. queueCallback: function() {
  17954. $module.off('.queue' + eventNamespace);
  17955. },
  17956. completeCallback: function() {
  17957. $module.off('.complete' + eventNamespace);
  17958. },
  17959. display: function() {
  17960. $module.css('display', '');
  17961. },
  17962. direction: function() {
  17963. $module
  17964. .removeClass(className.inward)
  17965. .removeClass(className.outward)
  17966. ;
  17967. },
  17968. duration: function() {
  17969. $module
  17970. .css('animation-duration', '')
  17971. ;
  17972. },
  17973. failSafe: function() {
  17974. module.verbose('Removing fail safe timer', module.timer);
  17975. if(module.timer) {
  17976. clearTimeout(module.timer);
  17977. }
  17978. },
  17979. hidden: function() {
  17980. $module.removeClass(className.hidden);
  17981. },
  17982. visible: function() {
  17983. $module.removeClass(className.visible);
  17984. },
  17985. looping: function() {
  17986. module.debug('Transitions are no longer looping');
  17987. if( module.is.looping() ) {
  17988. module.reset();
  17989. $module
  17990. .removeClass(className.looping)
  17991. ;
  17992. }
  17993. },
  17994. transition: function() {
  17995. $module
  17996. .removeClass(className.visible)
  17997. .removeClass(className.hidden)
  17998. ;
  17999. }
  18000. },
  18001. get: {
  18002. settings: function(animation, duration, onComplete) {
  18003. // single settings object
  18004. if(typeof animation == 'object') {
  18005. return $.extend(true, {}, $.fn.transition.settings, animation);
  18006. }
  18007. // all arguments provided
  18008. else if(typeof onComplete == 'function') {
  18009. return $.extend({}, $.fn.transition.settings, {
  18010. animation : animation,
  18011. onComplete : onComplete,
  18012. duration : duration
  18013. });
  18014. }
  18015. // only duration provided
  18016. else if(typeof duration == 'string' || typeof duration == 'number') {
  18017. return $.extend({}, $.fn.transition.settings, {
  18018. animation : animation,
  18019. duration : duration
  18020. });
  18021. }
  18022. // duration is actually settings object
  18023. else if(typeof duration == 'object') {
  18024. return $.extend({}, $.fn.transition.settings, duration, {
  18025. animation : animation
  18026. });
  18027. }
  18028. // duration is actually callback
  18029. else if(typeof duration == 'function') {
  18030. return $.extend({}, $.fn.transition.settings, {
  18031. animation : animation,
  18032. onComplete : duration
  18033. });
  18034. }
  18035. // only animation provided
  18036. else {
  18037. return $.extend({}, $.fn.transition.settings, {
  18038. animation : animation
  18039. });
  18040. }
  18041. },
  18042. animationClass: function(animation) {
  18043. var
  18044. animationClass = animation || settings.animation,
  18045. directionClass = (module.can.transition() && !module.has.direction())
  18046. ? module.get.direction() + ' '
  18047. : ''
  18048. ;
  18049. return className.animating + ' '
  18050. + className.transition + ' '
  18051. + directionClass
  18052. + animationClass
  18053. ;
  18054. },
  18055. currentAnimation: function() {
  18056. return (module.cache && module.cache.animation !== undefined)
  18057. ? module.cache.animation
  18058. : false
  18059. ;
  18060. },
  18061. currentDirection: function() {
  18062. return module.is.inward()
  18063. ? className.inward
  18064. : className.outward
  18065. ;
  18066. },
  18067. direction: function() {
  18068. return module.is.hidden() || !module.is.visible()
  18069. ? className.inward
  18070. : className.outward
  18071. ;
  18072. },
  18073. animationDirection: function(animation) {
  18074. var
  18075. direction
  18076. ;
  18077. animation = animation || settings.animation;
  18078. if(typeof animation === 'string') {
  18079. animation = animation.split(' ');
  18080. // search animation name for out/in class
  18081. $.each(animation, function(index, word){
  18082. if(word === className.inward) {
  18083. direction = className.inward;
  18084. }
  18085. else if(word === className.outward) {
  18086. direction = className.outward;
  18087. }
  18088. });
  18089. }
  18090. // return found direction
  18091. if(direction) {
  18092. return direction;
  18093. }
  18094. return false;
  18095. },
  18096. duration: function(duration) {
  18097. duration = duration || settings.duration;
  18098. if(duration === false) {
  18099. duration = $module.css('animation-duration') || 0;
  18100. }
  18101. return (typeof duration === 'string')
  18102. ? (duration.indexOf('ms') > -1)
  18103. ? parseFloat(duration)
  18104. : parseFloat(duration) * 1000
  18105. : duration
  18106. ;
  18107. },
  18108. displayType: function(shouldDetermine) {
  18109. shouldDetermine = (shouldDetermine !== undefined)
  18110. ? shouldDetermine
  18111. : true
  18112. ;
  18113. if(settings.displayType) {
  18114. return settings.displayType;
  18115. }
  18116. if(shouldDetermine && $module.data(metadata.displayType) === undefined) {
  18117. // create fake element to determine display state
  18118. module.can.transition(true);
  18119. }
  18120. return $module.data(metadata.displayType);
  18121. },
  18122. userStyle: function(style) {
  18123. style = style || $module.attr('style') || '';
  18124. return style.replace(/display.*?;/, '');
  18125. },
  18126. transitionExists: function(animation) {
  18127. return $.fn.transition.exists[animation];
  18128. },
  18129. animationStartEvent: function() {
  18130. var
  18131. element = document.createElement('div'),
  18132. animations = {
  18133. 'animation' :'animationstart',
  18134. 'OAnimation' :'oAnimationStart',
  18135. 'MozAnimation' :'mozAnimationStart',
  18136. 'WebkitAnimation' :'webkitAnimationStart'
  18137. },
  18138. animation
  18139. ;
  18140. for(animation in animations){
  18141. if( element.style[animation] !== undefined ){
  18142. return animations[animation];
  18143. }
  18144. }
  18145. return false;
  18146. },
  18147. animationEndEvent: function() {
  18148. var
  18149. element = document.createElement('div'),
  18150. animations = {
  18151. 'animation' :'animationend',
  18152. 'OAnimation' :'oAnimationEnd',
  18153. 'MozAnimation' :'mozAnimationEnd',
  18154. 'WebkitAnimation' :'webkitAnimationEnd'
  18155. },
  18156. animation
  18157. ;
  18158. for(animation in animations){
  18159. if( element.style[animation] !== undefined ){
  18160. return animations[animation];
  18161. }
  18162. }
  18163. return false;
  18164. }
  18165. },
  18166. can: {
  18167. transition: function(forced) {
  18168. var
  18169. animation = settings.animation,
  18170. transitionExists = module.get.transitionExists(animation),
  18171. displayType = module.get.displayType(false),
  18172. elementClass,
  18173. tagName,
  18174. $clone,
  18175. currentAnimation,
  18176. inAnimation,
  18177. directionExists
  18178. ;
  18179. if( transitionExists === undefined || forced) {
  18180. module.verbose('Determining whether animation exists');
  18181. elementClass = $module.attr('class');
  18182. tagName = $module.prop('tagName');
  18183. $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
  18184. currentAnimation = $clone
  18185. .addClass(animation)
  18186. .removeClass(className.inward)
  18187. .removeClass(className.outward)
  18188. .addClass(className.animating)
  18189. .addClass(className.transition)
  18190. .css('animationName')
  18191. ;
  18192. inAnimation = $clone
  18193. .addClass(className.inward)
  18194. .css('animationName')
  18195. ;
  18196. if(!displayType) {
  18197. displayType = $clone
  18198. .attr('class', elementClass)
  18199. .removeAttr('style')
  18200. .removeClass(className.hidden)
  18201. .removeClass(className.visible)
  18202. .show()
  18203. .css('display')
  18204. ;
  18205. module.verbose('Determining final display state', displayType);
  18206. module.save.displayType(displayType);
  18207. }
  18208. $clone.remove();
  18209. if(currentAnimation != inAnimation) {
  18210. module.debug('Direction exists for animation', animation);
  18211. directionExists = true;
  18212. }
  18213. else if(currentAnimation == 'none' || !currentAnimation) {
  18214. module.debug('No animation defined in css', animation);
  18215. return;
  18216. }
  18217. else {
  18218. module.debug('Static animation found', animation, displayType);
  18219. directionExists = false;
  18220. }
  18221. module.save.transitionExists(animation, directionExists);
  18222. }
  18223. return (transitionExists !== undefined)
  18224. ? transitionExists
  18225. : directionExists
  18226. ;
  18227. },
  18228. animate: function() {
  18229. // can transition does not return a value if animation does not exist
  18230. return (module.can.transition() !== undefined);
  18231. }
  18232. },
  18233. is: {
  18234. animating: function() {
  18235. return $module.hasClass(className.animating);
  18236. },
  18237. inward: function() {
  18238. return $module.hasClass(className.inward);
  18239. },
  18240. outward: function() {
  18241. return $module.hasClass(className.outward);
  18242. },
  18243. looping: function() {
  18244. return $module.hasClass(className.looping);
  18245. },
  18246. occurring: function(animation) {
  18247. animation = animation || settings.animation;
  18248. animation = '.' + animation.replace(' ', '.');
  18249. return ( $module.filter(animation).length > 0 );
  18250. },
  18251. visible: function() {
  18252. return $module.is(':visible');
  18253. },
  18254. hidden: function() {
  18255. return $module.css('visibility') === 'hidden';
  18256. },
  18257. supported: function() {
  18258. return(animationEnd !== false);
  18259. }
  18260. },
  18261. hide: function() {
  18262. module.verbose('Hiding element');
  18263. if( module.is.animating() ) {
  18264. module.reset();
  18265. }
  18266. element.blur(); // IE will trigger focus change if element is not blurred before hiding
  18267. module.remove.display();
  18268. module.remove.visible();
  18269. module.set.hidden();
  18270. module.force.hidden();
  18271. settings.onHide.call(element);
  18272. settings.onComplete.call(element);
  18273. // module.repaint();
  18274. },
  18275. show: function(display) {
  18276. module.verbose('Showing element', display);
  18277. module.remove.hidden();
  18278. module.set.visible();
  18279. module.force.visible();
  18280. settings.onShow.call(element);
  18281. settings.onComplete.call(element);
  18282. // module.repaint();
  18283. },
  18284. toggle: function() {
  18285. if( module.is.visible() ) {
  18286. module.hide();
  18287. }
  18288. else {
  18289. module.show();
  18290. }
  18291. },
  18292. stop: function() {
  18293. module.debug('Stopping current animation');
  18294. $module.triggerHandler(animationEnd);
  18295. },
  18296. stopAll: function() {
  18297. module.debug('Stopping all animation');
  18298. module.remove.queueCallback();
  18299. $module.triggerHandler(animationEnd);
  18300. },
  18301. clear: {
  18302. queue: function() {
  18303. module.debug('Clearing animation queue');
  18304. module.remove.queueCallback();
  18305. }
  18306. },
  18307. enable: function() {
  18308. module.verbose('Starting animation');
  18309. $module.removeClass(className.disabled);
  18310. },
  18311. disable: function() {
  18312. module.debug('Stopping animation');
  18313. $module.addClass(className.disabled);
  18314. },
  18315. setting: function(name, value) {
  18316. module.debug('Changing setting', name, value);
  18317. if( $.isPlainObject(name) ) {
  18318. $.extend(true, settings, name);
  18319. }
  18320. else if(value !== undefined) {
  18321. if($.isPlainObject(settings[name])) {
  18322. $.extend(true, settings[name], value);
  18323. }
  18324. else {
  18325. settings[name] = value;
  18326. }
  18327. }
  18328. else {
  18329. return settings[name];
  18330. }
  18331. },
  18332. internal: function(name, value) {
  18333. if( $.isPlainObject(name) ) {
  18334. $.extend(true, module, name);
  18335. }
  18336. else if(value !== undefined) {
  18337. module[name] = value;
  18338. }
  18339. else {
  18340. return module[name];
  18341. }
  18342. },
  18343. debug: function() {
  18344. if(!settings.silent && settings.debug) {
  18345. if(settings.performance) {
  18346. module.performance.log(arguments);
  18347. }
  18348. else {
  18349. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18350. module.debug.apply(console, arguments);
  18351. }
  18352. }
  18353. },
  18354. verbose: function() {
  18355. if(!settings.silent && settings.verbose && settings.debug) {
  18356. if(settings.performance) {
  18357. module.performance.log(arguments);
  18358. }
  18359. else {
  18360. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18361. module.verbose.apply(console, arguments);
  18362. }
  18363. }
  18364. },
  18365. error: function() {
  18366. if(!settings.silent) {
  18367. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  18368. module.error.apply(console, arguments);
  18369. }
  18370. },
  18371. performance: {
  18372. log: function(message) {
  18373. var
  18374. currentTime,
  18375. executionTime,
  18376. previousTime
  18377. ;
  18378. if(settings.performance) {
  18379. currentTime = new Date().getTime();
  18380. previousTime = time || currentTime;
  18381. executionTime = currentTime - previousTime;
  18382. time = currentTime;
  18383. performance.push({
  18384. 'Name' : message[0],
  18385. 'Arguments' : [].slice.call(message, 1) || '',
  18386. 'Element' : element,
  18387. 'Execution Time' : executionTime
  18388. });
  18389. }
  18390. clearTimeout(module.performance.timer);
  18391. module.performance.timer = setTimeout(module.performance.display, 500);
  18392. },
  18393. display: function() {
  18394. var
  18395. title = settings.name + ':',
  18396. totalTime = 0
  18397. ;
  18398. time = false;
  18399. clearTimeout(module.performance.timer);
  18400. $.each(performance, function(index, data) {
  18401. totalTime += data['Execution Time'];
  18402. });
  18403. title += ' ' + totalTime + 'ms';
  18404. if(moduleSelector) {
  18405. title += ' \'' + moduleSelector + '\'';
  18406. }
  18407. if($allModules.length > 1) {
  18408. title += ' ' + '(' + $allModules.length + ')';
  18409. }
  18410. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  18411. console.groupCollapsed(title);
  18412. if(console.table) {
  18413. console.table(performance);
  18414. }
  18415. else {
  18416. $.each(performance, function(index, data) {
  18417. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  18418. });
  18419. }
  18420. console.groupEnd();
  18421. }
  18422. performance = [];
  18423. }
  18424. },
  18425. // modified for transition to return invoke success
  18426. invoke: function(query, passedArguments, context) {
  18427. var
  18428. object = instance,
  18429. maxDepth,
  18430. found,
  18431. response
  18432. ;
  18433. passedArguments = passedArguments || queryArguments;
  18434. context = element || context;
  18435. if(typeof query == 'string' && object !== undefined) {
  18436. query = query.split(/[\. ]/);
  18437. maxDepth = query.length - 1;
  18438. $.each(query, function(depth, value) {
  18439. var camelCaseValue = (depth != maxDepth)
  18440. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  18441. : query
  18442. ;
  18443. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  18444. object = object[camelCaseValue];
  18445. }
  18446. else if( object[camelCaseValue] !== undefined ) {
  18447. found = object[camelCaseValue];
  18448. return false;
  18449. }
  18450. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  18451. object = object[value];
  18452. }
  18453. else if( object[value] !== undefined ) {
  18454. found = object[value];
  18455. return false;
  18456. }
  18457. else {
  18458. return false;
  18459. }
  18460. });
  18461. }
  18462. if ( $.isFunction( found ) ) {
  18463. response = found.apply(context, passedArguments);
  18464. }
  18465. else if(found !== undefined) {
  18466. response = found;
  18467. }
  18468. if($.isArray(returnedValue)) {
  18469. returnedValue.push(response);
  18470. }
  18471. else if(returnedValue !== undefined) {
  18472. returnedValue = [returnedValue, response];
  18473. }
  18474. else if(response !== undefined) {
  18475. returnedValue = response;
  18476. }
  18477. return (found !== undefined)
  18478. ? found
  18479. : false
  18480. ;
  18481. }
  18482. };
  18483. module.initialize();
  18484. })
  18485. ;
  18486. return (returnedValue !== undefined)
  18487. ? returnedValue
  18488. : this
  18489. ;
  18490. };
  18491. // Records if CSS transition is available
  18492. $.fn.transition.exists = {};
  18493. $.fn.transition.settings = {
  18494. // module info
  18495. name : 'Transition',
  18496. // hide all output from this component regardless of other settings
  18497. silent : false,
  18498. // debug content outputted to console
  18499. debug : false,
  18500. // verbose debug output
  18501. verbose : false,
  18502. // performance data output
  18503. performance : true,
  18504. // event namespace
  18505. namespace : 'transition',
  18506. // delay between animations in group
  18507. interval : 0,
  18508. // whether group animations should be reversed
  18509. reverse : 'auto',
  18510. // animation callback event
  18511. onStart : function() {},
  18512. onComplete : function() {},
  18513. onShow : function() {},
  18514. onHide : function() {},
  18515. // whether timeout should be used to ensure callback fires in cases animationend does not
  18516. useFailSafe : true,
  18517. // delay in ms for fail safe
  18518. failSafeDelay : 100,
  18519. // whether EXACT animation can occur twice in a row
  18520. allowRepeats : false,
  18521. // Override final display type on visible
  18522. displayType : false,
  18523. // animation duration
  18524. animation : 'fade',
  18525. duration : false,
  18526. // new animations will occur after previous ones
  18527. queue : true,
  18528. metadata : {
  18529. displayType: 'display'
  18530. },
  18531. className : {
  18532. animating : 'animating',
  18533. disabled : 'disabled',
  18534. hidden : 'hidden',
  18535. inward : 'in',
  18536. loading : 'loading',
  18537. looping : 'looping',
  18538. outward : 'out',
  18539. transition : 'transition',
  18540. visible : 'visible'
  18541. },
  18542. // possible errors
  18543. error: {
  18544. noAnimation : 'Element is no longer attached to DOM. Unable to animate. Use silent setting to surpress this warning in production.',
  18545. repeated : 'That animation is already occurring, cancelling repeated animation',
  18546. method : 'The method you called is not defined',
  18547. support : 'This browser does not support CSS animations'
  18548. }
  18549. };
  18550. })( jQuery, window, document );
  18551. /*!
  18552. * # Semantic UI 2.3.3 - API
  18553. * http://github.com/semantic-org/semantic-ui/
  18554. *
  18555. *
  18556. * Released under the MIT license
  18557. * http://opensource.org/licenses/MIT
  18558. *
  18559. */
  18560. ;(function ($, window, document, undefined) {
  18561. 'use strict';
  18562. var
  18563. window = (typeof window != 'undefined' && window.Math == Math)
  18564. ? window
  18565. : (typeof self != 'undefined' && self.Math == Math)
  18566. ? self
  18567. : Function('return this')()
  18568. ;
  18569. $.api = $.fn.api = function(parameters) {
  18570. var
  18571. // use window context if none specified
  18572. $allModules = $.isFunction(this)
  18573. ? $(window)
  18574. : $(this),
  18575. moduleSelector = $allModules.selector || '',
  18576. time = new Date().getTime(),
  18577. performance = [],
  18578. query = arguments[0],
  18579. methodInvoked = (typeof query == 'string'),
  18580. queryArguments = [].slice.call(arguments, 1),
  18581. returnedValue
  18582. ;
  18583. $allModules
  18584. .each(function() {
  18585. var
  18586. settings = ( $.isPlainObject(parameters) )
  18587. ? $.extend(true, {}, $.fn.api.settings, parameters)
  18588. : $.extend({}, $.fn.api.settings),
  18589. // internal aliases
  18590. namespace = settings.namespace,
  18591. metadata = settings.metadata,
  18592. selector = settings.selector,
  18593. error = settings.error,
  18594. className = settings.className,
  18595. // define namespaces for modules
  18596. eventNamespace = '.' + namespace,
  18597. moduleNamespace = 'module-' + namespace,
  18598. // element that creates request
  18599. $module = $(this),
  18600. $form = $module.closest(selector.form),
  18601. // context used for state
  18602. $context = (settings.stateContext)
  18603. ? $(settings.stateContext)
  18604. : $module,
  18605. // request details
  18606. ajaxSettings,
  18607. requestSettings,
  18608. url,
  18609. data,
  18610. requestStartTime,
  18611. // standard module
  18612. element = this,
  18613. context = $context[0],
  18614. instance = $module.data(moduleNamespace),
  18615. module
  18616. ;
  18617. module = {
  18618. initialize: function() {
  18619. if(!methodInvoked) {
  18620. module.bind.events();
  18621. }
  18622. module.instantiate();
  18623. },
  18624. instantiate: function() {
  18625. module.verbose('Storing instance of module', module);
  18626. instance = module;
  18627. $module
  18628. .data(moduleNamespace, instance)
  18629. ;
  18630. },
  18631. destroy: function() {
  18632. module.verbose('Destroying previous module for', element);
  18633. $module
  18634. .removeData(moduleNamespace)
  18635. .off(eventNamespace)
  18636. ;
  18637. },
  18638. bind: {
  18639. events: function() {
  18640. var
  18641. triggerEvent = module.get.event()
  18642. ;
  18643. if( triggerEvent ) {
  18644. module.verbose('Attaching API events to element', triggerEvent);
  18645. $module
  18646. .on(triggerEvent + eventNamespace, module.event.trigger)
  18647. ;
  18648. }
  18649. else if(settings.on == 'now') {
  18650. module.debug('Querying API endpoint immediately');
  18651. module.query();
  18652. }
  18653. }
  18654. },
  18655. decode: {
  18656. json: function(response) {
  18657. if(response !== undefined && typeof response == 'string') {
  18658. try {
  18659. response = JSON.parse(response);
  18660. }
  18661. catch(e) {
  18662. // isnt json string
  18663. }
  18664. }
  18665. return response;
  18666. }
  18667. },
  18668. read: {
  18669. cachedResponse: function(url) {
  18670. var
  18671. response
  18672. ;
  18673. if(window.Storage === undefined) {
  18674. module.error(error.noStorage);
  18675. return;
  18676. }
  18677. response = sessionStorage.getItem(url);
  18678. module.debug('Using cached response', url, response);
  18679. response = module.decode.json(response);
  18680. return response;
  18681. }
  18682. },
  18683. write: {
  18684. cachedResponse: function(url, response) {
  18685. if(response && response === '') {
  18686. module.debug('Response empty, not caching', response);
  18687. return;
  18688. }
  18689. if(window.Storage === undefined) {
  18690. module.error(error.noStorage);
  18691. return;
  18692. }
  18693. if( $.isPlainObject(response) ) {
  18694. response = JSON.stringify(response);
  18695. }
  18696. sessionStorage.setItem(url, response);
  18697. module.verbose('Storing cached response for url', url, response);
  18698. }
  18699. },
  18700. query: function() {
  18701. if(module.is.disabled()) {
  18702. module.debug('Element is disabled API request aborted');
  18703. return;
  18704. }
  18705. if(module.is.loading()) {
  18706. if(settings.interruptRequests) {
  18707. module.debug('Interrupting previous request');
  18708. module.abort();
  18709. }
  18710. else {
  18711. module.debug('Cancelling request, previous request is still pending');
  18712. return;
  18713. }
  18714. }
  18715. // pass element metadata to url (value, text)
  18716. if(settings.defaultData) {
  18717. $.extend(true, settings.urlData, module.get.defaultData());
  18718. }
  18719. // Add form content
  18720. if(settings.serializeForm) {
  18721. settings.data = module.add.formData(settings.data);
  18722. }
  18723. // call beforesend and get any settings changes
  18724. requestSettings = module.get.settings();
  18725. // check if before send cancelled request
  18726. if(requestSettings === false) {
  18727. module.cancelled = true;
  18728. module.error(error.beforeSend);
  18729. return;
  18730. }
  18731. else {
  18732. module.cancelled = false;
  18733. }
  18734. // get url
  18735. url = module.get.templatedURL();
  18736. if(!url && !module.is.mocked()) {
  18737. module.error(error.missingURL);
  18738. return;
  18739. }
  18740. // replace variables
  18741. url = module.add.urlData( url );
  18742. // missing url parameters
  18743. if( !url && !module.is.mocked()) {
  18744. return;
  18745. }
  18746. requestSettings.url = settings.base + url;
  18747. // look for jQuery ajax parameters in settings
  18748. ajaxSettings = $.extend(true, {}, settings, {
  18749. type : settings.method || settings.type,
  18750. data : data,
  18751. url : settings.base + url,
  18752. beforeSend : settings.beforeXHR,
  18753. success : function() {},
  18754. failure : function() {},
  18755. complete : function() {}
  18756. });
  18757. module.debug('Querying URL', ajaxSettings.url);
  18758. module.verbose('Using AJAX settings', ajaxSettings);
  18759. if(settings.cache === 'local' && module.read.cachedResponse(url)) {
  18760. module.debug('Response returned from local cache');
  18761. module.request = module.create.request();
  18762. module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
  18763. return;
  18764. }
  18765. if( !settings.throttle ) {
  18766. module.debug('Sending request', data, ajaxSettings.method);
  18767. module.send.request();
  18768. }
  18769. else {
  18770. if(!settings.throttleFirstRequest && !module.timer) {
  18771. module.debug('Sending request', data, ajaxSettings.method);
  18772. module.send.request();
  18773. module.timer = setTimeout(function(){}, settings.throttle);
  18774. }
  18775. else {
  18776. module.debug('Throttling request', settings.throttle);
  18777. clearTimeout(module.timer);
  18778. module.timer = setTimeout(function() {
  18779. if(module.timer) {
  18780. delete module.timer;
  18781. }
  18782. module.debug('Sending throttled request', data, ajaxSettings.method);
  18783. module.send.request();
  18784. }, settings.throttle);
  18785. }
  18786. }
  18787. },
  18788. should: {
  18789. removeError: function() {
  18790. return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
  18791. }
  18792. },
  18793. is: {
  18794. disabled: function() {
  18795. return ($module.filter(selector.disabled).length > 0);
  18796. },
  18797. expectingJSON: function() {
  18798. return settings.dataType === 'json' || settings.dataType === 'jsonp';
  18799. },
  18800. form: function() {
  18801. return $module.is('form') || $context.is('form');
  18802. },
  18803. mocked: function() {
  18804. return (settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync);
  18805. },
  18806. input: function() {
  18807. return $module.is('input');
  18808. },
  18809. loading: function() {
  18810. return (module.request)
  18811. ? (module.request.state() == 'pending')
  18812. : false
  18813. ;
  18814. },
  18815. abortedRequest: function(xhr) {
  18816. if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
  18817. module.verbose('XHR request determined to be aborted');
  18818. return true;
  18819. }
  18820. else {
  18821. module.verbose('XHR request was not aborted');
  18822. return false;
  18823. }
  18824. },
  18825. validResponse: function(response) {
  18826. if( (!module.is.expectingJSON()) || !$.isFunction(settings.successTest) ) {
  18827. module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
  18828. return true;
  18829. }
  18830. module.debug('Checking JSON returned success', settings.successTest, response);
  18831. if( settings.successTest(response) ) {
  18832. module.debug('Response passed success test', response);
  18833. return true;
  18834. }
  18835. else {
  18836. module.debug('Response failed success test', response);
  18837. return false;
  18838. }
  18839. }
  18840. },
  18841. was: {
  18842. cancelled: function() {
  18843. return (module.cancelled || false);
  18844. },
  18845. succesful: function() {
  18846. return (module.request && module.request.state() == 'resolved');
  18847. },
  18848. failure: function() {
  18849. return (module.request && module.request.state() == 'rejected');
  18850. },
  18851. complete: function() {
  18852. return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
  18853. }
  18854. },
  18855. add: {
  18856. urlData: function(url, urlData) {
  18857. var
  18858. requiredVariables,
  18859. optionalVariables
  18860. ;
  18861. if(url) {
  18862. requiredVariables = url.match(settings.regExp.required);
  18863. optionalVariables = url.match(settings.regExp.optional);
  18864. urlData = urlData || settings.urlData;
  18865. if(requiredVariables) {
  18866. module.debug('Looking for required URL variables', requiredVariables);
  18867. $.each(requiredVariables, function(index, templatedString) {
  18868. var
  18869. // allow legacy {$var} style
  18870. variable = (templatedString.indexOf('$') !== -1)
  18871. ? templatedString.substr(2, templatedString.length - 3)
  18872. : templatedString.substr(1, templatedString.length - 2),
  18873. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  18874. ? urlData[variable]
  18875. : ($module.data(variable) !== undefined)
  18876. ? $module.data(variable)
  18877. : ($context.data(variable) !== undefined)
  18878. ? $context.data(variable)
  18879. : urlData[variable]
  18880. ;
  18881. // remove value
  18882. if(value === undefined) {
  18883. module.error(error.requiredParameter, variable, url);
  18884. url = false;
  18885. return false;
  18886. }
  18887. else {
  18888. module.verbose('Found required variable', variable, value);
  18889. value = (settings.encodeParameters)
  18890. ? module.get.urlEncodedValue(value)
  18891. : value
  18892. ;
  18893. url = url.replace(templatedString, value);
  18894. }
  18895. });
  18896. }
  18897. if(optionalVariables) {
  18898. module.debug('Looking for optional URL variables', requiredVariables);
  18899. $.each(optionalVariables, function(index, templatedString) {
  18900. var
  18901. // allow legacy {/$var} style
  18902. variable = (templatedString.indexOf('$') !== -1)
  18903. ? templatedString.substr(3, templatedString.length - 4)
  18904. : templatedString.substr(2, templatedString.length - 3),
  18905. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  18906. ? urlData[variable]
  18907. : ($module.data(variable) !== undefined)
  18908. ? $module.data(variable)
  18909. : ($context.data(variable) !== undefined)
  18910. ? $context.data(variable)
  18911. : urlData[variable]
  18912. ;
  18913. // optional replacement
  18914. if(value !== undefined) {
  18915. module.verbose('Optional variable Found', variable, value);
  18916. url = url.replace(templatedString, value);
  18917. }
  18918. else {
  18919. module.verbose('Optional variable not found', variable);
  18920. // remove preceding slash if set
  18921. if(url.indexOf('/' + templatedString) !== -1) {
  18922. url = url.replace('/' + templatedString, '');
  18923. }
  18924. else {
  18925. url = url.replace(templatedString, '');
  18926. }
  18927. }
  18928. });
  18929. }
  18930. }
  18931. return url;
  18932. },
  18933. formData: function(data) {
  18934. var
  18935. canSerialize = ($.fn.serializeObject !== undefined),
  18936. formData = (canSerialize)
  18937. ? $form.serializeObject()
  18938. : $form.serialize(),
  18939. hasOtherData
  18940. ;
  18941. data = data || settings.data;
  18942. hasOtherData = $.isPlainObject(data);
  18943. if(hasOtherData) {
  18944. if(canSerialize) {
  18945. module.debug('Extending existing data with form data', data, formData);
  18946. data = $.extend(true, {}, data, formData);
  18947. }
  18948. else {
  18949. module.error(error.missingSerialize);
  18950. module.debug('Cant extend data. Replacing data with form data', data, formData);
  18951. data = formData;
  18952. }
  18953. }
  18954. else {
  18955. module.debug('Adding form data', formData);
  18956. data = formData;
  18957. }
  18958. return data;
  18959. }
  18960. },
  18961. send: {
  18962. request: function() {
  18963. module.set.loading();
  18964. module.request = module.create.request();
  18965. if( module.is.mocked() ) {
  18966. module.mockedXHR = module.create.mockedXHR();
  18967. }
  18968. else {
  18969. module.xhr = module.create.xhr();
  18970. }
  18971. settings.onRequest.call(context, module.request, module.xhr);
  18972. }
  18973. },
  18974. event: {
  18975. trigger: function(event) {
  18976. module.query();
  18977. if(event.type == 'submit' || event.type == 'click') {
  18978. event.preventDefault();
  18979. }
  18980. },
  18981. xhr: {
  18982. always: function() {
  18983. // nothing special
  18984. },
  18985. done: function(response, textStatus, xhr) {
  18986. var
  18987. context = this,
  18988. elapsedTime = (new Date().getTime() - requestStartTime),
  18989. timeLeft = (settings.loadingDuration - elapsedTime),
  18990. translatedResponse = ( $.isFunction(settings.onResponse) )
  18991. ? module.is.expectingJSON()
  18992. ? settings.onResponse.call(context, $.extend(true, {}, response))
  18993. : settings.onResponse.call(context, response)
  18994. : false
  18995. ;
  18996. timeLeft = (timeLeft > 0)
  18997. ? timeLeft
  18998. : 0
  18999. ;
  19000. if(translatedResponse) {
  19001. module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
  19002. response = translatedResponse;
  19003. }
  19004. if(timeLeft > 0) {
  19005. module.debug('Response completed early delaying state change by', timeLeft);
  19006. }
  19007. setTimeout(function() {
  19008. if( module.is.validResponse(response) ) {
  19009. module.request.resolveWith(context, [response, xhr]);
  19010. }
  19011. else {
  19012. module.request.rejectWith(context, [xhr, 'invalid']);
  19013. }
  19014. }, timeLeft);
  19015. },
  19016. fail: function(xhr, status, httpMessage) {
  19017. var
  19018. context = this,
  19019. elapsedTime = (new Date().getTime() - requestStartTime),
  19020. timeLeft = (settings.loadingDuration - elapsedTime)
  19021. ;
  19022. timeLeft = (timeLeft > 0)
  19023. ? timeLeft
  19024. : 0
  19025. ;
  19026. if(timeLeft > 0) {
  19027. module.debug('Response completed early delaying state change by', timeLeft);
  19028. }
  19029. setTimeout(function() {
  19030. if( module.is.abortedRequest(xhr) ) {
  19031. module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
  19032. }
  19033. else {
  19034. module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
  19035. }
  19036. }, timeLeft);
  19037. }
  19038. },
  19039. request: {
  19040. done: function(response, xhr) {
  19041. module.debug('Successful API Response', response);
  19042. if(settings.cache === 'local' && url) {
  19043. module.write.cachedResponse(url, response);
  19044. module.debug('Saving server response locally', module.cache);
  19045. }
  19046. settings.onSuccess.call(context, response, $module, xhr);
  19047. },
  19048. complete: function(firstParameter, secondParameter) {
  19049. var
  19050. xhr,
  19051. response
  19052. ;
  19053. // have to guess callback parameters based on request success
  19054. if( module.was.succesful() ) {
  19055. response = firstParameter;
  19056. xhr = secondParameter;
  19057. }
  19058. else {
  19059. xhr = firstParameter;
  19060. response = module.get.responseFromXHR(xhr);
  19061. }
  19062. module.remove.loading();
  19063. settings.onComplete.call(context, response, $module, xhr);
  19064. },
  19065. fail: function(xhr, status, httpMessage) {
  19066. var
  19067. // pull response from xhr if available
  19068. response = module.get.responseFromXHR(xhr),
  19069. errorMessage = module.get.errorFromRequest(response, status, httpMessage)
  19070. ;
  19071. if(status == 'aborted') {
  19072. module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
  19073. settings.onAbort.call(context, status, $module, xhr);
  19074. return true;
  19075. }
  19076. else if(status == 'invalid') {
  19077. module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
  19078. }
  19079. else if(status == 'error') {
  19080. if(xhr !== undefined) {
  19081. module.debug('XHR produced a server error', status, httpMessage);
  19082. // make sure we have an error to display to console
  19083. if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
  19084. module.error(error.statusMessage + httpMessage, ajaxSettings.url);
  19085. }
  19086. settings.onError.call(context, errorMessage, $module, xhr);
  19087. }
  19088. }
  19089. if(settings.errorDuration && status !== 'aborted') {
  19090. module.debug('Adding error state');
  19091. module.set.error();
  19092. if( module.should.removeError() ) {
  19093. setTimeout(module.remove.error, settings.errorDuration);
  19094. }
  19095. }
  19096. module.debug('API Request failed', errorMessage, xhr);
  19097. settings.onFailure.call(context, response, $module, xhr);
  19098. }
  19099. }
  19100. },
  19101. create: {
  19102. request: function() {
  19103. // api request promise
  19104. return $.Deferred()
  19105. .always(module.event.request.complete)
  19106. .done(module.event.request.done)
  19107. .fail(module.event.request.fail)
  19108. ;
  19109. },
  19110. mockedXHR: function () {
  19111. var
  19112. // xhr does not simulate these properties of xhr but must return them
  19113. textStatus = false,
  19114. status = false,
  19115. httpMessage = false,
  19116. responder = settings.mockResponse || settings.response,
  19117. asyncResponder = settings.mockResponseAsync || settings.responseAsync,
  19118. asyncCallback,
  19119. response,
  19120. mockedXHR
  19121. ;
  19122. mockedXHR = $.Deferred()
  19123. .always(module.event.xhr.complete)
  19124. .done(module.event.xhr.done)
  19125. .fail(module.event.xhr.fail)
  19126. ;
  19127. if(responder) {
  19128. if( $.isFunction(responder) ) {
  19129. module.debug('Using specified synchronous callback', responder);
  19130. response = responder.call(context, requestSettings);
  19131. }
  19132. else {
  19133. module.debug('Using settings specified response', responder);
  19134. response = responder;
  19135. }
  19136. // simulating response
  19137. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  19138. }
  19139. else if( $.isFunction(asyncResponder) ) {
  19140. asyncCallback = function(response) {
  19141. module.debug('Async callback returned response', response);
  19142. if(response) {
  19143. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  19144. }
  19145. else {
  19146. mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
  19147. }
  19148. };
  19149. module.debug('Using specified async response callback', asyncResponder);
  19150. asyncResponder.call(context, requestSettings, asyncCallback);
  19151. }
  19152. return mockedXHR;
  19153. },
  19154. xhr: function() {
  19155. var
  19156. xhr
  19157. ;
  19158. // ajax request promise
  19159. xhr = $.ajax(ajaxSettings)
  19160. .always(module.event.xhr.always)
  19161. .done(module.event.xhr.done)
  19162. .fail(module.event.xhr.fail)
  19163. ;
  19164. module.verbose('Created server request', xhr, ajaxSettings);
  19165. return xhr;
  19166. }
  19167. },
  19168. set: {
  19169. error: function() {
  19170. module.verbose('Adding error state to element', $context);
  19171. $context.addClass(className.error);
  19172. },
  19173. loading: function() {
  19174. module.verbose('Adding loading state to element', $context);
  19175. $context.addClass(className.loading);
  19176. requestStartTime = new Date().getTime();
  19177. }
  19178. },
  19179. remove: {
  19180. error: function() {
  19181. module.verbose('Removing error state from element', $context);
  19182. $context.removeClass(className.error);
  19183. },
  19184. loading: function() {
  19185. module.verbose('Removing loading state from element', $context);
  19186. $context.removeClass(className.loading);
  19187. }
  19188. },
  19189. get: {
  19190. responseFromXHR: function(xhr) {
  19191. return $.isPlainObject(xhr)
  19192. ? (module.is.expectingJSON())
  19193. ? module.decode.json(xhr.responseText)
  19194. : xhr.responseText
  19195. : false
  19196. ;
  19197. },
  19198. errorFromRequest: function(response, status, httpMessage) {
  19199. return ($.isPlainObject(response) && response.error !== undefined)
  19200. ? response.error // use json error message
  19201. : (settings.error[status] !== undefined) // use server error message
  19202. ? settings.error[status]
  19203. : httpMessage
  19204. ;
  19205. },
  19206. request: function() {
  19207. return module.request || false;
  19208. },
  19209. xhr: function() {
  19210. return module.xhr || false;
  19211. },
  19212. settings: function() {
  19213. var
  19214. runSettings
  19215. ;
  19216. runSettings = settings.beforeSend.call(context, settings);
  19217. if(runSettings) {
  19218. if(runSettings.success !== undefined) {
  19219. module.debug('Legacy success callback detected', runSettings);
  19220. module.error(error.legacyParameters, runSettings.success);
  19221. runSettings.onSuccess = runSettings.success;
  19222. }
  19223. if(runSettings.failure !== undefined) {
  19224. module.debug('Legacy failure callback detected', runSettings);
  19225. module.error(error.legacyParameters, runSettings.failure);
  19226. runSettings.onFailure = runSettings.failure;
  19227. }
  19228. if(runSettings.complete !== undefined) {
  19229. module.debug('Legacy complete callback detected', runSettings);
  19230. module.error(error.legacyParameters, runSettings.complete);
  19231. runSettings.onComplete = runSettings.complete;
  19232. }
  19233. }
  19234. if(runSettings === undefined) {
  19235. module.error(error.noReturnedValue);
  19236. }
  19237. if(runSettings === false) {
  19238. return runSettings;
  19239. }
  19240. return (runSettings !== undefined)
  19241. ? $.extend(true, {}, runSettings)
  19242. : $.extend(true, {}, settings)
  19243. ;
  19244. },
  19245. urlEncodedValue: function(value) {
  19246. var
  19247. decodedValue = window.decodeURIComponent(value),
  19248. encodedValue = window.encodeURIComponent(value),
  19249. alreadyEncoded = (decodedValue !== value)
  19250. ;
  19251. if(alreadyEncoded) {
  19252. module.debug('URL value is already encoded, avoiding double encoding', value);
  19253. return value;
  19254. }
  19255. module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
  19256. return encodedValue;
  19257. },
  19258. defaultData: function() {
  19259. var
  19260. data = {}
  19261. ;
  19262. if( !$.isWindow(element) ) {
  19263. if( module.is.input() ) {
  19264. data.value = $module.val();
  19265. }
  19266. else if( module.is.form() ) {
  19267. }
  19268. else {
  19269. data.text = $module.text();
  19270. }
  19271. }
  19272. return data;
  19273. },
  19274. event: function() {
  19275. if( $.isWindow(element) || settings.on == 'now' ) {
  19276. module.debug('API called without element, no events attached');
  19277. return false;
  19278. }
  19279. else if(settings.on == 'auto') {
  19280. if( $module.is('input') ) {
  19281. return (element.oninput !== undefined)
  19282. ? 'input'
  19283. : (element.onpropertychange !== undefined)
  19284. ? 'propertychange'
  19285. : 'keyup'
  19286. ;
  19287. }
  19288. else if( $module.is('form') ) {
  19289. return 'submit';
  19290. }
  19291. else {
  19292. return 'click';
  19293. }
  19294. }
  19295. else {
  19296. return settings.on;
  19297. }
  19298. },
  19299. templatedURL: function(action) {
  19300. action = action || $module.data(metadata.action) || settings.action || false;
  19301. url = $module.data(metadata.url) || settings.url || false;
  19302. if(url) {
  19303. module.debug('Using specified url', url);
  19304. return url;
  19305. }
  19306. if(action) {
  19307. module.debug('Looking up url for action', action, settings.api);
  19308. if(settings.api[action] === undefined && !module.is.mocked()) {
  19309. module.error(error.missingAction, settings.action, settings.api);
  19310. return;
  19311. }
  19312. url = settings.api[action];
  19313. }
  19314. else if( module.is.form() ) {
  19315. url = $module.attr('action') || $context.attr('action') || false;
  19316. module.debug('No url or action specified, defaulting to form action', url);
  19317. }
  19318. return url;
  19319. }
  19320. },
  19321. abort: function() {
  19322. var
  19323. xhr = module.get.xhr()
  19324. ;
  19325. if( xhr && xhr.state() !== 'resolved') {
  19326. module.debug('Cancelling API request');
  19327. xhr.abort();
  19328. }
  19329. },
  19330. // reset state
  19331. reset: function() {
  19332. module.remove.error();
  19333. module.remove.loading();
  19334. },
  19335. setting: function(name, value) {
  19336. module.debug('Changing setting', name, value);
  19337. if( $.isPlainObject(name) ) {
  19338. $.extend(true, settings, name);
  19339. }
  19340. else if(value !== undefined) {
  19341. if($.isPlainObject(settings[name])) {
  19342. $.extend(true, settings[name], value);
  19343. }
  19344. else {
  19345. settings[name] = value;
  19346. }
  19347. }
  19348. else {
  19349. return settings[name];
  19350. }
  19351. },
  19352. internal: function(name, value) {
  19353. if( $.isPlainObject(name) ) {
  19354. $.extend(true, module, name);
  19355. }
  19356. else if(value !== undefined) {
  19357. module[name] = value;
  19358. }
  19359. else {
  19360. return module[name];
  19361. }
  19362. },
  19363. debug: function() {
  19364. if(!settings.silent && settings.debug) {
  19365. if(settings.performance) {
  19366. module.performance.log(arguments);
  19367. }
  19368. else {
  19369. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19370. module.debug.apply(console, arguments);
  19371. }
  19372. }
  19373. },
  19374. verbose: function() {
  19375. if(!settings.silent && settings.verbose && settings.debug) {
  19376. if(settings.performance) {
  19377. module.performance.log(arguments);
  19378. }
  19379. else {
  19380. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19381. module.verbose.apply(console, arguments);
  19382. }
  19383. }
  19384. },
  19385. error: function() {
  19386. if(!settings.silent) {
  19387. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  19388. module.error.apply(console, arguments);
  19389. }
  19390. },
  19391. performance: {
  19392. log: function(message) {
  19393. var
  19394. currentTime,
  19395. executionTime,
  19396. previousTime
  19397. ;
  19398. if(settings.performance) {
  19399. currentTime = new Date().getTime();
  19400. previousTime = time || currentTime;
  19401. executionTime = currentTime - previousTime;
  19402. time = currentTime;
  19403. performance.push({
  19404. 'Name' : message[0],
  19405. 'Arguments' : [].slice.call(message, 1) || '',
  19406. //'Element' : element,
  19407. 'Execution Time' : executionTime
  19408. });
  19409. }
  19410. clearTimeout(module.performance.timer);
  19411. module.performance.timer = setTimeout(module.performance.display, 500);
  19412. },
  19413. display: function() {
  19414. var
  19415. title = settings.name + ':',
  19416. totalTime = 0
  19417. ;
  19418. time = false;
  19419. clearTimeout(module.performance.timer);
  19420. $.each(performance, function(index, data) {
  19421. totalTime += data['Execution Time'];
  19422. });
  19423. title += ' ' + totalTime + 'ms';
  19424. if(moduleSelector) {
  19425. title += ' \'' + moduleSelector + '\'';
  19426. }
  19427. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  19428. console.groupCollapsed(title);
  19429. if(console.table) {
  19430. console.table(performance);
  19431. }
  19432. else {
  19433. $.each(performance, function(index, data) {
  19434. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  19435. });
  19436. }
  19437. console.groupEnd();
  19438. }
  19439. performance = [];
  19440. }
  19441. },
  19442. invoke: function(query, passedArguments, context) {
  19443. var
  19444. object = instance,
  19445. maxDepth,
  19446. found,
  19447. response
  19448. ;
  19449. passedArguments = passedArguments || queryArguments;
  19450. context = element || context;
  19451. if(typeof query == 'string' && object !== undefined) {
  19452. query = query.split(/[\. ]/);
  19453. maxDepth = query.length - 1;
  19454. $.each(query, function(depth, value) {
  19455. var camelCaseValue = (depth != maxDepth)
  19456. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  19457. : query
  19458. ;
  19459. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  19460. object = object[camelCaseValue];
  19461. }
  19462. else if( object[camelCaseValue] !== undefined ) {
  19463. found = object[camelCaseValue];
  19464. return false;
  19465. }
  19466. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  19467. object = object[value];
  19468. }
  19469. else if( object[value] !== undefined ) {
  19470. found = object[value];
  19471. return false;
  19472. }
  19473. else {
  19474. module.error(error.method, query);
  19475. return false;
  19476. }
  19477. });
  19478. }
  19479. if ( $.isFunction( found ) ) {
  19480. response = found.apply(context, passedArguments);
  19481. }
  19482. else if(found !== undefined) {
  19483. response = found;
  19484. }
  19485. if($.isArray(returnedValue)) {
  19486. returnedValue.push(response);
  19487. }
  19488. else if(returnedValue !== undefined) {
  19489. returnedValue = [returnedValue, response];
  19490. }
  19491. else if(response !== undefined) {
  19492. returnedValue = response;
  19493. }
  19494. return found;
  19495. }
  19496. };
  19497. if(methodInvoked) {
  19498. if(instance === undefined) {
  19499. module.initialize();
  19500. }
  19501. module.invoke(query);
  19502. }
  19503. else {
  19504. if(instance !== undefined) {
  19505. instance.invoke('destroy');
  19506. }
  19507. module.initialize();
  19508. }
  19509. })
  19510. ;
  19511. return (returnedValue !== undefined)
  19512. ? returnedValue
  19513. : this
  19514. ;
  19515. };
  19516. $.api.settings = {
  19517. name : 'API',
  19518. namespace : 'api',
  19519. debug : false,
  19520. verbose : false,
  19521. performance : true,
  19522. // object containing all templates endpoints
  19523. api : {},
  19524. // whether to cache responses
  19525. cache : true,
  19526. // whether new requests should abort previous requests
  19527. interruptRequests : true,
  19528. // event binding
  19529. on : 'auto',
  19530. // context for applying state classes
  19531. stateContext : false,
  19532. // duration for loading state
  19533. loadingDuration : 0,
  19534. // whether to hide errors after a period of time
  19535. hideError : 'auto',
  19536. // duration for error state
  19537. errorDuration : 2000,
  19538. // whether parameters should be encoded with encodeURIComponent
  19539. encodeParameters : true,
  19540. // API action to use
  19541. action : false,
  19542. // templated URL to use
  19543. url : false,
  19544. // base URL to apply to all endpoints
  19545. base : '',
  19546. // data that will
  19547. urlData : {},
  19548. // whether to add default data to url data
  19549. defaultData : true,
  19550. // whether to serialize closest form
  19551. serializeForm : false,
  19552. // how long to wait before request should occur
  19553. throttle : 0,
  19554. // whether to throttle first request or only repeated
  19555. throttleFirstRequest : true,
  19556. // standard ajax settings
  19557. method : 'get',
  19558. data : {},
  19559. dataType : 'json',
  19560. // mock response
  19561. mockResponse : false,
  19562. mockResponseAsync : false,
  19563. // aliases for mock
  19564. response : false,
  19565. responseAsync : false,
  19566. // callbacks before request
  19567. beforeSend : function(settings) { return settings; },
  19568. beforeXHR : function(xhr) {},
  19569. onRequest : function(promise, xhr) {},
  19570. // after request
  19571. onResponse : false, // function(response) { },
  19572. // response was successful, if JSON passed validation
  19573. onSuccess : function(response, $module) {},
  19574. // request finished without aborting
  19575. onComplete : function(response, $module) {},
  19576. // failed JSON success test
  19577. onFailure : function(response, $module) {},
  19578. // server error
  19579. onError : function(errorMessage, $module) {},
  19580. // request aborted
  19581. onAbort : function(errorMessage, $module) {},
  19582. successTest : false,
  19583. // errors
  19584. error : {
  19585. beforeSend : 'The before send function has aborted the request',
  19586. error : 'There was an error with your request',
  19587. exitConditions : 'API Request Aborted. Exit conditions met',
  19588. JSONParse : 'JSON could not be parsed during error handling',
  19589. legacyParameters : 'You are using legacy API success callback names',
  19590. method : 'The method you called is not defined',
  19591. missingAction : 'API action used but no url was defined',
  19592. missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
  19593. missingURL : 'No URL specified for api event',
  19594. noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
  19595. noStorage : 'Caching responses locally requires session storage',
  19596. parseError : 'There was an error parsing your request',
  19597. requiredParameter : 'Missing a required URL parameter: ',
  19598. statusMessage : 'Server gave an error: ',
  19599. timeout : 'Your request timed out'
  19600. },
  19601. regExp : {
  19602. required : /\{\$*[A-z0-9]+\}/g,
  19603. optional : /\{\/\$*[A-z0-9]+\}/g,
  19604. },
  19605. className: {
  19606. loading : 'loading',
  19607. error : 'error'
  19608. },
  19609. selector: {
  19610. disabled : '.disabled',
  19611. form : 'form'
  19612. },
  19613. metadata: {
  19614. action : 'action',
  19615. url : 'url'
  19616. }
  19617. };
  19618. })( jQuery, window, document );
  19619. /*!
  19620. * # Semantic UI 2.3.3 - Visibility
  19621. * http://github.com/semantic-org/semantic-ui/
  19622. *
  19623. *
  19624. * Released under the MIT license
  19625. * http://opensource.org/licenses/MIT
  19626. *
  19627. */
  19628. ;(function ($, window, document, undefined) {
  19629. 'use strict';
  19630. window = (typeof window != 'undefined' && window.Math == Math)
  19631. ? window
  19632. : (typeof self != 'undefined' && self.Math == Math)
  19633. ? self
  19634. : Function('return this')()
  19635. ;
  19636. $.fn.visibility = function(parameters) {
  19637. var
  19638. $allModules = $(this),
  19639. moduleSelector = $allModules.selector || '',
  19640. time = new Date().getTime(),
  19641. performance = [],
  19642. query = arguments[0],
  19643. methodInvoked = (typeof query == 'string'),
  19644. queryArguments = [].slice.call(arguments, 1),
  19645. returnedValue,
  19646. moduleCount = $allModules.length,
  19647. loadedCount = 0
  19648. ;
  19649. $allModules
  19650. .each(function() {
  19651. var
  19652. settings = ( $.isPlainObject(parameters) )
  19653. ? $.extend(true, {}, $.fn.visibility.settings, parameters)
  19654. : $.extend({}, $.fn.visibility.settings),
  19655. className = settings.className,
  19656. namespace = settings.namespace,
  19657. error = settings.error,
  19658. metadata = settings.metadata,
  19659. eventNamespace = '.' + namespace,
  19660. moduleNamespace = 'module-' + namespace,
  19661. $window = $(window),
  19662. $module = $(this),
  19663. $context = $(settings.context),
  19664. $placeholder,
  19665. selector = $module.selector || '',
  19666. instance = $module.data(moduleNamespace),
  19667. requestAnimationFrame = window.requestAnimationFrame
  19668. || window.mozRequestAnimationFrame
  19669. || window.webkitRequestAnimationFrame
  19670. || window.msRequestAnimationFrame
  19671. || function(callback) { setTimeout(callback, 0); },
  19672. element = this,
  19673. disabled = false,
  19674. contextObserver,
  19675. observer,
  19676. module
  19677. ;
  19678. module = {
  19679. initialize: function() {
  19680. module.debug('Initializing', settings);
  19681. module.setup.cache();
  19682. if( module.should.trackChanges() ) {
  19683. if(settings.type == 'image') {
  19684. module.setup.image();
  19685. }
  19686. if(settings.type == 'fixed') {
  19687. module.setup.fixed();
  19688. }
  19689. if(settings.observeChanges) {
  19690. module.observeChanges();
  19691. }
  19692. module.bind.events();
  19693. }
  19694. module.save.position();
  19695. if( !module.is.visible() ) {
  19696. module.error(error.visible, $module);
  19697. }
  19698. if(settings.initialCheck) {
  19699. module.checkVisibility();
  19700. }
  19701. module.instantiate();
  19702. },
  19703. instantiate: function() {
  19704. module.debug('Storing instance', module);
  19705. $module
  19706. .data(moduleNamespace, module)
  19707. ;
  19708. instance = module;
  19709. },
  19710. destroy: function() {
  19711. module.verbose('Destroying previous module');
  19712. if(observer) {
  19713. observer.disconnect();
  19714. }
  19715. if(contextObserver) {
  19716. contextObserver.disconnect();
  19717. }
  19718. $window
  19719. .off('load' + eventNamespace, module.event.load)
  19720. .off('resize' + eventNamespace, module.event.resize)
  19721. ;
  19722. $context
  19723. .off('scroll' + eventNamespace, module.event.scroll)
  19724. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  19725. ;
  19726. if(settings.type == 'fixed') {
  19727. module.resetFixed();
  19728. module.remove.placeholder();
  19729. }
  19730. $module
  19731. .off(eventNamespace)
  19732. .removeData(moduleNamespace)
  19733. ;
  19734. },
  19735. observeChanges: function() {
  19736. if('MutationObserver' in window) {
  19737. contextObserver = new MutationObserver(module.event.contextChanged);
  19738. observer = new MutationObserver(module.event.changed);
  19739. contextObserver.observe(document, {
  19740. childList : true,
  19741. subtree : true
  19742. });
  19743. observer.observe(element, {
  19744. childList : true,
  19745. subtree : true
  19746. });
  19747. module.debug('Setting up mutation observer', observer);
  19748. }
  19749. },
  19750. bind: {
  19751. events: function() {
  19752. module.verbose('Binding visibility events to scroll and resize');
  19753. if(settings.refreshOnLoad) {
  19754. $window
  19755. .on('load' + eventNamespace, module.event.load)
  19756. ;
  19757. }
  19758. $window
  19759. .on('resize' + eventNamespace, module.event.resize)
  19760. ;
  19761. // pub/sub pattern
  19762. $context
  19763. .off('scroll' + eventNamespace)
  19764. .on('scroll' + eventNamespace, module.event.scroll)
  19765. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  19766. ;
  19767. }
  19768. },
  19769. event: {
  19770. changed: function(mutations) {
  19771. module.verbose('DOM tree modified, updating visibility calculations');
  19772. module.timer = setTimeout(function() {
  19773. module.verbose('DOM tree modified, updating sticky menu');
  19774. module.refresh();
  19775. }, 100);
  19776. },
  19777. contextChanged: function(mutations) {
  19778. [].forEach.call(mutations, function(mutation) {
  19779. if(mutation.removedNodes) {
  19780. [].forEach.call(mutation.removedNodes, function(node) {
  19781. if(node == element || $(node).find(element).length > 0) {
  19782. module.debug('Element removed from DOM, tearing down events');
  19783. module.destroy();
  19784. }
  19785. });
  19786. }
  19787. });
  19788. },
  19789. resize: function() {
  19790. module.debug('Window resized');
  19791. if(settings.refreshOnResize) {
  19792. requestAnimationFrame(module.refresh);
  19793. }
  19794. },
  19795. load: function() {
  19796. module.debug('Page finished loading');
  19797. requestAnimationFrame(module.refresh);
  19798. },
  19799. // publishes scrollchange event on one scroll
  19800. scroll: function() {
  19801. if(settings.throttle) {
  19802. clearTimeout(module.timer);
  19803. module.timer = setTimeout(function() {
  19804. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  19805. }, settings.throttle);
  19806. }
  19807. else {
  19808. requestAnimationFrame(function() {
  19809. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  19810. });
  19811. }
  19812. },
  19813. // subscribes to scrollchange
  19814. scrollchange: function(event, scrollPosition) {
  19815. module.checkVisibility(scrollPosition);
  19816. },
  19817. },
  19818. precache: function(images, callback) {
  19819. if (!(images instanceof Array)) {
  19820. images = [images];
  19821. }
  19822. var
  19823. imagesLength = images.length,
  19824. loadedCounter = 0,
  19825. cache = [],
  19826. cacheImage = document.createElement('img'),
  19827. handleLoad = function() {
  19828. loadedCounter++;
  19829. if (loadedCounter >= images.length) {
  19830. if ($.isFunction(callback)) {
  19831. callback();
  19832. }
  19833. }
  19834. }
  19835. ;
  19836. while (imagesLength--) {
  19837. cacheImage = document.createElement('img');
  19838. cacheImage.onload = handleLoad;
  19839. cacheImage.onerror = handleLoad;
  19840. cacheImage.src = images[imagesLength];
  19841. cache.push(cacheImage);
  19842. }
  19843. },
  19844. enableCallbacks: function() {
  19845. module.debug('Allowing callbacks to occur');
  19846. disabled = false;
  19847. },
  19848. disableCallbacks: function() {
  19849. module.debug('Disabling all callbacks temporarily');
  19850. disabled = true;
  19851. },
  19852. should: {
  19853. trackChanges: function() {
  19854. if(methodInvoked) {
  19855. module.debug('One time query, no need to bind events');
  19856. return false;
  19857. }
  19858. module.debug('Callbacks being attached');
  19859. return true;
  19860. }
  19861. },
  19862. setup: {
  19863. cache: function() {
  19864. module.cache = {
  19865. occurred : {},
  19866. screen : {},
  19867. element : {},
  19868. };
  19869. },
  19870. image: function() {
  19871. var
  19872. src = $module.data(metadata.src)
  19873. ;
  19874. if(src) {
  19875. module.verbose('Lazy loading image', src);
  19876. settings.once = true;
  19877. settings.observeChanges = false;
  19878. // show when top visible
  19879. settings.onOnScreen = function() {
  19880. module.debug('Image on screen', element);
  19881. module.precache(src, function() {
  19882. module.set.image(src, function() {
  19883. loadedCount++;
  19884. if(loadedCount == moduleCount) {
  19885. settings.onAllLoaded.call(this);
  19886. }
  19887. settings.onLoad.call(this);
  19888. });
  19889. });
  19890. };
  19891. }
  19892. },
  19893. fixed: function() {
  19894. module.debug('Setting up fixed');
  19895. settings.once = false;
  19896. settings.observeChanges = false;
  19897. settings.initialCheck = true;
  19898. settings.refreshOnLoad = true;
  19899. if(!parameters.transition) {
  19900. settings.transition = false;
  19901. }
  19902. module.create.placeholder();
  19903. module.debug('Added placeholder', $placeholder);
  19904. settings.onTopPassed = function() {
  19905. module.debug('Element passed, adding fixed position', $module);
  19906. module.show.placeholder();
  19907. module.set.fixed();
  19908. if(settings.transition) {
  19909. if($.fn.transition !== undefined) {
  19910. $module.transition(settings.transition, settings.duration);
  19911. }
  19912. }
  19913. };
  19914. settings.onTopPassedReverse = function() {
  19915. module.debug('Element returned to position, removing fixed', $module);
  19916. module.hide.placeholder();
  19917. module.remove.fixed();
  19918. };
  19919. }
  19920. },
  19921. create: {
  19922. placeholder: function() {
  19923. module.verbose('Creating fixed position placeholder');
  19924. $placeholder = $module
  19925. .clone(false)
  19926. .css('display', 'none')
  19927. .addClass(className.placeholder)
  19928. .insertAfter($module)
  19929. ;
  19930. }
  19931. },
  19932. show: {
  19933. placeholder: function() {
  19934. module.verbose('Showing placeholder');
  19935. $placeholder
  19936. .css('display', 'block')
  19937. .css('visibility', 'hidden')
  19938. ;
  19939. }
  19940. },
  19941. hide: {
  19942. placeholder: function() {
  19943. module.verbose('Hiding placeholder');
  19944. $placeholder
  19945. .css('display', 'none')
  19946. .css('visibility', '')
  19947. ;
  19948. }
  19949. },
  19950. set: {
  19951. fixed: function() {
  19952. module.verbose('Setting element to fixed position');
  19953. $module
  19954. .addClass(className.fixed)
  19955. .css({
  19956. position : 'fixed',
  19957. top : settings.offset + 'px',
  19958. left : 'auto',
  19959. zIndex : settings.zIndex
  19960. })
  19961. ;
  19962. settings.onFixed.call(element);
  19963. },
  19964. image: function(src, callback) {
  19965. $module
  19966. .attr('src', src)
  19967. ;
  19968. if(settings.transition) {
  19969. if( $.fn.transition !== undefined) {
  19970. if($module.hasClass(className.visible)) {
  19971. module.debug('Transition already occurred on this image, skipping animation');
  19972. return;
  19973. }
  19974. $module.transition(settings.transition, settings.duration, callback);
  19975. }
  19976. else {
  19977. $module.fadeIn(settings.duration, callback);
  19978. }
  19979. }
  19980. else {
  19981. $module.show();
  19982. }
  19983. }
  19984. },
  19985. is: {
  19986. onScreen: function() {
  19987. var
  19988. calculations = module.get.elementCalculations()
  19989. ;
  19990. return calculations.onScreen;
  19991. },
  19992. offScreen: function() {
  19993. var
  19994. calculations = module.get.elementCalculations()
  19995. ;
  19996. return calculations.offScreen;
  19997. },
  19998. visible: function() {
  19999. if(module.cache && module.cache.element) {
  20000. return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
  20001. }
  20002. return false;
  20003. },
  20004. verticallyScrollableContext: function() {
  20005. var
  20006. overflowY = ($context.get(0) !== window)
  20007. ? $context.css('overflow-y')
  20008. : false
  20009. ;
  20010. return (overflowY == 'auto' || overflowY == 'scroll');
  20011. },
  20012. horizontallyScrollableContext: function() {
  20013. var
  20014. overflowX = ($context.get(0) !== window)
  20015. ? $context.css('overflow-x')
  20016. : false
  20017. ;
  20018. return (overflowX == 'auto' || overflowX == 'scroll');
  20019. }
  20020. },
  20021. refresh: function() {
  20022. module.debug('Refreshing constants (width/height)');
  20023. if(settings.type == 'fixed') {
  20024. module.resetFixed();
  20025. }
  20026. module.reset();
  20027. module.save.position();
  20028. if(settings.checkOnRefresh) {
  20029. module.checkVisibility();
  20030. }
  20031. settings.onRefresh.call(element);
  20032. },
  20033. resetFixed: function () {
  20034. module.remove.fixed();
  20035. module.remove.occurred();
  20036. },
  20037. reset: function() {
  20038. module.verbose('Resetting all cached values');
  20039. if( $.isPlainObject(module.cache) ) {
  20040. module.cache.screen = {};
  20041. module.cache.element = {};
  20042. }
  20043. },
  20044. checkVisibility: function(scroll) {
  20045. module.verbose('Checking visibility of element', module.cache.element);
  20046. if( !disabled && module.is.visible() ) {
  20047. // save scroll position
  20048. module.save.scroll(scroll);
  20049. // update calculations derived from scroll
  20050. module.save.calculations();
  20051. // percentage
  20052. module.passed();
  20053. // reverse (must be first)
  20054. module.passingReverse();
  20055. module.topVisibleReverse();
  20056. module.bottomVisibleReverse();
  20057. module.topPassedReverse();
  20058. module.bottomPassedReverse();
  20059. // one time
  20060. module.onScreen();
  20061. module.offScreen();
  20062. module.passing();
  20063. module.topVisible();
  20064. module.bottomVisible();
  20065. module.topPassed();
  20066. module.bottomPassed();
  20067. // on update callback
  20068. if(settings.onUpdate) {
  20069. settings.onUpdate.call(element, module.get.elementCalculations());
  20070. }
  20071. }
  20072. },
  20073. passed: function(amount, newCallback) {
  20074. var
  20075. calculations = module.get.elementCalculations(),
  20076. amountInPixels
  20077. ;
  20078. // assign callback
  20079. if(amount && newCallback) {
  20080. settings.onPassed[amount] = newCallback;
  20081. }
  20082. else if(amount !== undefined) {
  20083. return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
  20084. }
  20085. else if(calculations.passing) {
  20086. $.each(settings.onPassed, function(amount, callback) {
  20087. if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
  20088. module.execute(callback, amount);
  20089. }
  20090. else if(!settings.once) {
  20091. module.remove.occurred(callback);
  20092. }
  20093. });
  20094. }
  20095. },
  20096. onScreen: function(newCallback) {
  20097. var
  20098. calculations = module.get.elementCalculations(),
  20099. callback = newCallback || settings.onOnScreen,
  20100. callbackName = 'onScreen'
  20101. ;
  20102. if(newCallback) {
  20103. module.debug('Adding callback for onScreen', newCallback);
  20104. settings.onOnScreen = newCallback;
  20105. }
  20106. if(calculations.onScreen) {
  20107. module.execute(callback, callbackName);
  20108. }
  20109. else if(!settings.once) {
  20110. module.remove.occurred(callbackName);
  20111. }
  20112. if(newCallback !== undefined) {
  20113. return calculations.onOnScreen;
  20114. }
  20115. },
  20116. offScreen: function(newCallback) {
  20117. var
  20118. calculations = module.get.elementCalculations(),
  20119. callback = newCallback || settings.onOffScreen,
  20120. callbackName = 'offScreen'
  20121. ;
  20122. if(newCallback) {
  20123. module.debug('Adding callback for offScreen', newCallback);
  20124. settings.onOffScreen = newCallback;
  20125. }
  20126. if(calculations.offScreen) {
  20127. module.execute(callback, callbackName);
  20128. }
  20129. else if(!settings.once) {
  20130. module.remove.occurred(callbackName);
  20131. }
  20132. if(newCallback !== undefined) {
  20133. return calculations.onOffScreen;
  20134. }
  20135. },
  20136. passing: function(newCallback) {
  20137. var
  20138. calculations = module.get.elementCalculations(),
  20139. callback = newCallback || settings.onPassing,
  20140. callbackName = 'passing'
  20141. ;
  20142. if(newCallback) {
  20143. module.debug('Adding callback for passing', newCallback);
  20144. settings.onPassing = newCallback;
  20145. }
  20146. if(calculations.passing) {
  20147. module.execute(callback, callbackName);
  20148. }
  20149. else if(!settings.once) {
  20150. module.remove.occurred(callbackName);
  20151. }
  20152. if(newCallback !== undefined) {
  20153. return calculations.passing;
  20154. }
  20155. },
  20156. topVisible: function(newCallback) {
  20157. var
  20158. calculations = module.get.elementCalculations(),
  20159. callback = newCallback || settings.onTopVisible,
  20160. callbackName = 'topVisible'
  20161. ;
  20162. if(newCallback) {
  20163. module.debug('Adding callback for top visible', newCallback);
  20164. settings.onTopVisible = newCallback;
  20165. }
  20166. if(calculations.topVisible) {
  20167. module.execute(callback, callbackName);
  20168. }
  20169. else if(!settings.once) {
  20170. module.remove.occurred(callbackName);
  20171. }
  20172. if(newCallback === undefined) {
  20173. return calculations.topVisible;
  20174. }
  20175. },
  20176. bottomVisible: function(newCallback) {
  20177. var
  20178. calculations = module.get.elementCalculations(),
  20179. callback = newCallback || settings.onBottomVisible,
  20180. callbackName = 'bottomVisible'
  20181. ;
  20182. if(newCallback) {
  20183. module.debug('Adding callback for bottom visible', newCallback);
  20184. settings.onBottomVisible = newCallback;
  20185. }
  20186. if(calculations.bottomVisible) {
  20187. module.execute(callback, callbackName);
  20188. }
  20189. else if(!settings.once) {
  20190. module.remove.occurred(callbackName);
  20191. }
  20192. if(newCallback === undefined) {
  20193. return calculations.bottomVisible;
  20194. }
  20195. },
  20196. topPassed: function(newCallback) {
  20197. var
  20198. calculations = module.get.elementCalculations(),
  20199. callback = newCallback || settings.onTopPassed,
  20200. callbackName = 'topPassed'
  20201. ;
  20202. if(newCallback) {
  20203. module.debug('Adding callback for top passed', newCallback);
  20204. settings.onTopPassed = newCallback;
  20205. }
  20206. if(calculations.topPassed) {
  20207. module.execute(callback, callbackName);
  20208. }
  20209. else if(!settings.once) {
  20210. module.remove.occurred(callbackName);
  20211. }
  20212. if(newCallback === undefined) {
  20213. return calculations.topPassed;
  20214. }
  20215. },
  20216. bottomPassed: function(newCallback) {
  20217. var
  20218. calculations = module.get.elementCalculations(),
  20219. callback = newCallback || settings.onBottomPassed,
  20220. callbackName = 'bottomPassed'
  20221. ;
  20222. if(newCallback) {
  20223. module.debug('Adding callback for bottom passed', newCallback);
  20224. settings.onBottomPassed = newCallback;
  20225. }
  20226. if(calculations.bottomPassed) {
  20227. module.execute(callback, callbackName);
  20228. }
  20229. else if(!settings.once) {
  20230. module.remove.occurred(callbackName);
  20231. }
  20232. if(newCallback === undefined) {
  20233. return calculations.bottomPassed;
  20234. }
  20235. },
  20236. passingReverse: function(newCallback) {
  20237. var
  20238. calculations = module.get.elementCalculations(),
  20239. callback = newCallback || settings.onPassingReverse,
  20240. callbackName = 'passingReverse'
  20241. ;
  20242. if(newCallback) {
  20243. module.debug('Adding callback for passing reverse', newCallback);
  20244. settings.onPassingReverse = newCallback;
  20245. }
  20246. if(!calculations.passing) {
  20247. if(module.get.occurred('passing')) {
  20248. module.execute(callback, callbackName);
  20249. }
  20250. }
  20251. else if(!settings.once) {
  20252. module.remove.occurred(callbackName);
  20253. }
  20254. if(newCallback !== undefined) {
  20255. return !calculations.passing;
  20256. }
  20257. },
  20258. topVisibleReverse: function(newCallback) {
  20259. var
  20260. calculations = module.get.elementCalculations(),
  20261. callback = newCallback || settings.onTopVisibleReverse,
  20262. callbackName = 'topVisibleReverse'
  20263. ;
  20264. if(newCallback) {
  20265. module.debug('Adding callback for top visible reverse', newCallback);
  20266. settings.onTopVisibleReverse = newCallback;
  20267. }
  20268. if(!calculations.topVisible) {
  20269. if(module.get.occurred('topVisible')) {
  20270. module.execute(callback, callbackName);
  20271. }
  20272. }
  20273. else if(!settings.once) {
  20274. module.remove.occurred(callbackName);
  20275. }
  20276. if(newCallback === undefined) {
  20277. return !calculations.topVisible;
  20278. }
  20279. },
  20280. bottomVisibleReverse: function(newCallback) {
  20281. var
  20282. calculations = module.get.elementCalculations(),
  20283. callback = newCallback || settings.onBottomVisibleReverse,
  20284. callbackName = 'bottomVisibleReverse'
  20285. ;
  20286. if(newCallback) {
  20287. module.debug('Adding callback for bottom visible reverse', newCallback);
  20288. settings.onBottomVisibleReverse = newCallback;
  20289. }
  20290. if(!calculations.bottomVisible) {
  20291. if(module.get.occurred('bottomVisible')) {
  20292. module.execute(callback, callbackName);
  20293. }
  20294. }
  20295. else if(!settings.once) {
  20296. module.remove.occurred(callbackName);
  20297. }
  20298. if(newCallback === undefined) {
  20299. return !calculations.bottomVisible;
  20300. }
  20301. },
  20302. topPassedReverse: function(newCallback) {
  20303. var
  20304. calculations = module.get.elementCalculations(),
  20305. callback = newCallback || settings.onTopPassedReverse,
  20306. callbackName = 'topPassedReverse'
  20307. ;
  20308. if(newCallback) {
  20309. module.debug('Adding callback for top passed reverse', newCallback);
  20310. settings.onTopPassedReverse = newCallback;
  20311. }
  20312. if(!calculations.topPassed) {
  20313. if(module.get.occurred('topPassed')) {
  20314. module.execute(callback, callbackName);
  20315. }
  20316. }
  20317. else if(!settings.once) {
  20318. module.remove.occurred(callbackName);
  20319. }
  20320. if(newCallback === undefined) {
  20321. return !calculations.onTopPassed;
  20322. }
  20323. },
  20324. bottomPassedReverse: function(newCallback) {
  20325. var
  20326. calculations = module.get.elementCalculations(),
  20327. callback = newCallback || settings.onBottomPassedReverse,
  20328. callbackName = 'bottomPassedReverse'
  20329. ;
  20330. if(newCallback) {
  20331. module.debug('Adding callback for bottom passed reverse', newCallback);
  20332. settings.onBottomPassedReverse = newCallback;
  20333. }
  20334. if(!calculations.bottomPassed) {
  20335. if(module.get.occurred('bottomPassed')) {
  20336. module.execute(callback, callbackName);
  20337. }
  20338. }
  20339. else if(!settings.once) {
  20340. module.remove.occurred(callbackName);
  20341. }
  20342. if(newCallback === undefined) {
  20343. return !calculations.bottomPassed;
  20344. }
  20345. },
  20346. execute: function(callback, callbackName) {
  20347. var
  20348. calculations = module.get.elementCalculations(),
  20349. screen = module.get.screenCalculations()
  20350. ;
  20351. callback = callback || false;
  20352. if(callback) {
  20353. if(settings.continuous) {
  20354. module.debug('Callback being called continuously', callbackName, calculations);
  20355. callback.call(element, calculations, screen);
  20356. }
  20357. else if(!module.get.occurred(callbackName)) {
  20358. module.debug('Conditions met', callbackName, calculations);
  20359. callback.call(element, calculations, screen);
  20360. }
  20361. }
  20362. module.save.occurred(callbackName);
  20363. },
  20364. remove: {
  20365. fixed: function() {
  20366. module.debug('Removing fixed position');
  20367. $module
  20368. .removeClass(className.fixed)
  20369. .css({
  20370. position : '',
  20371. top : '',
  20372. left : '',
  20373. zIndex : ''
  20374. })
  20375. ;
  20376. settings.onUnfixed.call(element);
  20377. },
  20378. placeholder: function() {
  20379. module.debug('Removing placeholder content');
  20380. if($placeholder) {
  20381. $placeholder.remove();
  20382. }
  20383. },
  20384. occurred: function(callback) {
  20385. if(callback) {
  20386. var
  20387. occurred = module.cache.occurred
  20388. ;
  20389. if(occurred[callback] !== undefined && occurred[callback] === true) {
  20390. module.debug('Callback can now be called again', callback);
  20391. module.cache.occurred[callback] = false;
  20392. }
  20393. }
  20394. else {
  20395. module.cache.occurred = {};
  20396. }
  20397. }
  20398. },
  20399. save: {
  20400. calculations: function() {
  20401. module.verbose('Saving all calculations necessary to determine positioning');
  20402. module.save.direction();
  20403. module.save.screenCalculations();
  20404. module.save.elementCalculations();
  20405. },
  20406. occurred: function(callback) {
  20407. if(callback) {
  20408. if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
  20409. module.verbose('Saving callback occurred', callback);
  20410. module.cache.occurred[callback] = true;
  20411. }
  20412. }
  20413. },
  20414. scroll: function(scrollPosition) {
  20415. scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
  20416. module.cache.scroll = scrollPosition;
  20417. },
  20418. direction: function() {
  20419. var
  20420. scroll = module.get.scroll(),
  20421. lastScroll = module.get.lastScroll(),
  20422. direction
  20423. ;
  20424. if(scroll > lastScroll && lastScroll) {
  20425. direction = 'down';
  20426. }
  20427. else if(scroll < lastScroll && lastScroll) {
  20428. direction = 'up';
  20429. }
  20430. else {
  20431. direction = 'static';
  20432. }
  20433. module.cache.direction = direction;
  20434. return module.cache.direction;
  20435. },
  20436. elementPosition: function() {
  20437. var
  20438. element = module.cache.element,
  20439. screen = module.get.screenSize()
  20440. ;
  20441. module.verbose('Saving element position');
  20442. // (quicker than $.extend)
  20443. element.fits = (element.height < screen.height);
  20444. element.offset = $module.offset();
  20445. element.width = $module.outerWidth();
  20446. element.height = $module.outerHeight();
  20447. // compensate for scroll in context
  20448. if(module.is.verticallyScrollableContext()) {
  20449. element.offset.top += $context.scrollTop() - $context.offset().top;
  20450. }
  20451. if(module.is.horizontallyScrollableContext()) {
  20452. element.offset.left += $context.scrollLeft - $context.offset().left;
  20453. }
  20454. // store
  20455. module.cache.element = element;
  20456. return element;
  20457. },
  20458. elementCalculations: function() {
  20459. var
  20460. screen = module.get.screenCalculations(),
  20461. element = module.get.elementPosition()
  20462. ;
  20463. // offset
  20464. if(settings.includeMargin) {
  20465. element.margin = {};
  20466. element.margin.top = parseInt($module.css('margin-top'), 10);
  20467. element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
  20468. element.top = element.offset.top - element.margin.top;
  20469. element.bottom = element.offset.top + element.height + element.margin.bottom;
  20470. }
  20471. else {
  20472. element.top = element.offset.top;
  20473. element.bottom = element.offset.top + element.height;
  20474. }
  20475. // visibility
  20476. element.topPassed = (screen.top >= element.top);
  20477. element.bottomPassed = (screen.top >= element.bottom);
  20478. element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
  20479. element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
  20480. element.pixelsPassed = 0;
  20481. element.percentagePassed = 0;
  20482. // meta calculations
  20483. element.onScreen = ((element.topVisible || element.passing) && !element.bottomPassed);
  20484. element.passing = (element.topPassed && !element.bottomPassed);
  20485. element.offScreen = (!element.onScreen);
  20486. // passing calculations
  20487. if(element.passing) {
  20488. element.pixelsPassed = (screen.top - element.top);
  20489. element.percentagePassed = (screen.top - element.top) / element.height;
  20490. }
  20491. module.cache.element = element;
  20492. module.verbose('Updated element calculations', element);
  20493. return element;
  20494. },
  20495. screenCalculations: function() {
  20496. var
  20497. scroll = module.get.scroll()
  20498. ;
  20499. module.save.direction();
  20500. module.cache.screen.top = scroll;
  20501. module.cache.screen.bottom = scroll + module.cache.screen.height;
  20502. return module.cache.screen;
  20503. },
  20504. screenSize: function() {
  20505. module.verbose('Saving window position');
  20506. module.cache.screen = {
  20507. height: $context.height()
  20508. };
  20509. },
  20510. position: function() {
  20511. module.save.screenSize();
  20512. module.save.elementPosition();
  20513. }
  20514. },
  20515. get: {
  20516. pixelsPassed: function(amount) {
  20517. var
  20518. element = module.get.elementCalculations()
  20519. ;
  20520. if(amount.search('%') > -1) {
  20521. return ( element.height * (parseInt(amount, 10) / 100) );
  20522. }
  20523. return parseInt(amount, 10);
  20524. },
  20525. occurred: function(callback) {
  20526. return (module.cache.occurred !== undefined)
  20527. ? module.cache.occurred[callback] || false
  20528. : false
  20529. ;
  20530. },
  20531. direction: function() {
  20532. if(module.cache.direction === undefined) {
  20533. module.save.direction();
  20534. }
  20535. return module.cache.direction;
  20536. },
  20537. elementPosition: function() {
  20538. if(module.cache.element === undefined) {
  20539. module.save.elementPosition();
  20540. }
  20541. return module.cache.element;
  20542. },
  20543. elementCalculations: function() {
  20544. if(module.cache.element === undefined) {
  20545. module.save.elementCalculations();
  20546. }
  20547. return module.cache.element;
  20548. },
  20549. screenCalculations: function() {
  20550. if(module.cache.screen === undefined) {
  20551. module.save.screenCalculations();
  20552. }
  20553. return module.cache.screen;
  20554. },
  20555. screenSize: function() {
  20556. if(module.cache.screen === undefined) {
  20557. module.save.screenSize();
  20558. }
  20559. return module.cache.screen;
  20560. },
  20561. scroll: function() {
  20562. if(module.cache.scroll === undefined) {
  20563. module.save.scroll();
  20564. }
  20565. return module.cache.scroll;
  20566. },
  20567. lastScroll: function() {
  20568. if(module.cache.screen === undefined) {
  20569. module.debug('First scroll event, no last scroll could be found');
  20570. return false;
  20571. }
  20572. return module.cache.screen.top;
  20573. }
  20574. },
  20575. setting: function(name, value) {
  20576. if( $.isPlainObject(name) ) {
  20577. $.extend(true, settings, name);
  20578. }
  20579. else if(value !== undefined) {
  20580. settings[name] = value;
  20581. }
  20582. else {
  20583. return settings[name];
  20584. }
  20585. },
  20586. internal: function(name, value) {
  20587. if( $.isPlainObject(name) ) {
  20588. $.extend(true, module, name);
  20589. }
  20590. else if(value !== undefined) {
  20591. module[name] = value;
  20592. }
  20593. else {
  20594. return module[name];
  20595. }
  20596. },
  20597. debug: function() {
  20598. if(!settings.silent && settings.debug) {
  20599. if(settings.performance) {
  20600. module.performance.log(arguments);
  20601. }
  20602. else {
  20603. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20604. module.debug.apply(console, arguments);
  20605. }
  20606. }
  20607. },
  20608. verbose: function() {
  20609. if(!settings.silent && settings.verbose && settings.debug) {
  20610. if(settings.performance) {
  20611. module.performance.log(arguments);
  20612. }
  20613. else {
  20614. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20615. module.verbose.apply(console, arguments);
  20616. }
  20617. }
  20618. },
  20619. error: function() {
  20620. if(!settings.silent) {
  20621. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  20622. module.error.apply(console, arguments);
  20623. }
  20624. },
  20625. performance: {
  20626. log: function(message) {
  20627. var
  20628. currentTime,
  20629. executionTime,
  20630. previousTime
  20631. ;
  20632. if(settings.performance) {
  20633. currentTime = new Date().getTime();
  20634. previousTime = time || currentTime;
  20635. executionTime = currentTime - previousTime;
  20636. time = currentTime;
  20637. performance.push({
  20638. 'Name' : message[0],
  20639. 'Arguments' : [].slice.call(message, 1) || '',
  20640. 'Element' : element,
  20641. 'Execution Time' : executionTime
  20642. });
  20643. }
  20644. clearTimeout(module.performance.timer);
  20645. module.performance.timer = setTimeout(module.performance.display, 500);
  20646. },
  20647. display: function() {
  20648. var
  20649. title = settings.name + ':',
  20650. totalTime = 0
  20651. ;
  20652. time = false;
  20653. clearTimeout(module.performance.timer);
  20654. $.each(performance, function(index, data) {
  20655. totalTime += data['Execution Time'];
  20656. });
  20657. title += ' ' + totalTime + 'ms';
  20658. if(moduleSelector) {
  20659. title += ' \'' + moduleSelector + '\'';
  20660. }
  20661. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  20662. console.groupCollapsed(title);
  20663. if(console.table) {
  20664. console.table(performance);
  20665. }
  20666. else {
  20667. $.each(performance, function(index, data) {
  20668. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  20669. });
  20670. }
  20671. console.groupEnd();
  20672. }
  20673. performance = [];
  20674. }
  20675. },
  20676. invoke: function(query, passedArguments, context) {
  20677. var
  20678. object = instance,
  20679. maxDepth,
  20680. found,
  20681. response
  20682. ;
  20683. passedArguments = passedArguments || queryArguments;
  20684. context = element || context;
  20685. if(typeof query == 'string' && object !== undefined) {
  20686. query = query.split(/[\. ]/);
  20687. maxDepth = query.length - 1;
  20688. $.each(query, function(depth, value) {
  20689. var camelCaseValue = (depth != maxDepth)
  20690. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  20691. : query
  20692. ;
  20693. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  20694. object = object[camelCaseValue];
  20695. }
  20696. else if( object[camelCaseValue] !== undefined ) {
  20697. found = object[camelCaseValue];
  20698. return false;
  20699. }
  20700. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  20701. object = object[value];
  20702. }
  20703. else if( object[value] !== undefined ) {
  20704. found = object[value];
  20705. return false;
  20706. }
  20707. else {
  20708. module.error(error.method, query);
  20709. return false;
  20710. }
  20711. });
  20712. }
  20713. if ( $.isFunction( found ) ) {
  20714. response = found.apply(context, passedArguments);
  20715. }
  20716. else if(found !== undefined) {
  20717. response = found;
  20718. }
  20719. if($.isArray(returnedValue)) {
  20720. returnedValue.push(response);
  20721. }
  20722. else if(returnedValue !== undefined) {
  20723. returnedValue = [returnedValue, response];
  20724. }
  20725. else if(response !== undefined) {
  20726. returnedValue = response;
  20727. }
  20728. return found;
  20729. }
  20730. };
  20731. if(methodInvoked) {
  20732. if(instance === undefined) {
  20733. module.initialize();
  20734. }
  20735. instance.save.scroll();
  20736. instance.save.calculations();
  20737. module.invoke(query);
  20738. }
  20739. else {
  20740. if(instance !== undefined) {
  20741. instance.invoke('destroy');
  20742. }
  20743. module.initialize();
  20744. }
  20745. })
  20746. ;
  20747. return (returnedValue !== undefined)
  20748. ? returnedValue
  20749. : this
  20750. ;
  20751. };
  20752. $.fn.visibility.settings = {
  20753. name : 'Visibility',
  20754. namespace : 'visibility',
  20755. debug : false,
  20756. verbose : false,
  20757. performance : true,
  20758. // whether to use mutation observers to follow changes
  20759. observeChanges : true,
  20760. // check position immediately on init
  20761. initialCheck : true,
  20762. // whether to refresh calculations after all page images load
  20763. refreshOnLoad : true,
  20764. // whether to refresh calculations after page resize event
  20765. refreshOnResize : true,
  20766. // should call callbacks on refresh event (resize, etc)
  20767. checkOnRefresh : true,
  20768. // callback should only occur one time
  20769. once : true,
  20770. // callback should fire continuously whe evaluates to true
  20771. continuous : false,
  20772. // offset to use with scroll top
  20773. offset : 0,
  20774. // whether to include margin in elements position
  20775. includeMargin : false,
  20776. // scroll context for visibility checks
  20777. context : window,
  20778. // visibility check delay in ms (defaults to animationFrame)
  20779. throttle : false,
  20780. // special visibility type (image, fixed)
  20781. type : false,
  20782. // z-index to use with visibility 'fixed'
  20783. zIndex : '10',
  20784. // image only animation settings
  20785. transition : 'fade in',
  20786. duration : 1000,
  20787. // array of callbacks for percentage
  20788. onPassed : {},
  20789. // standard callbacks
  20790. onOnScreen : false,
  20791. onOffScreen : false,
  20792. onPassing : false,
  20793. onTopVisible : false,
  20794. onBottomVisible : false,
  20795. onTopPassed : false,
  20796. onBottomPassed : false,
  20797. // reverse callbacks
  20798. onPassingReverse : false,
  20799. onTopVisibleReverse : false,
  20800. onBottomVisibleReverse : false,
  20801. onTopPassedReverse : false,
  20802. onBottomPassedReverse : false,
  20803. // special callbacks for image
  20804. onLoad : function() {},
  20805. onAllLoaded : function() {},
  20806. // special callbacks for fixed position
  20807. onFixed : function() {},
  20808. onUnfixed : function() {},
  20809. // utility callbacks
  20810. onUpdate : false, // disabled by default for performance
  20811. onRefresh : function(){},
  20812. metadata : {
  20813. src: 'src'
  20814. },
  20815. className: {
  20816. fixed : 'fixed',
  20817. placeholder : 'placeholder',
  20818. visible : 'visible'
  20819. },
  20820. error : {
  20821. method : 'The method you called is not defined.',
  20822. visible : 'Element is hidden, you must call refresh after element becomes visible'
  20823. }
  20824. };
  20825. })( jQuery, window, document );