semantic.js 734 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068
  1. /*
  2. * # Semantic UI - 2.3.0
  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.0 - 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.0 - 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. prompt = rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
  874. requiresValue = (prompt.search('{value}') !== -1),
  875. requiresName = (prompt.search('{name}') !== -1),
  876. $label,
  877. $field,
  878. name
  879. ;
  880. if(requiresName || requiresValue) {
  881. $field = module.get.field(field.identifier);
  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.0 - 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.0 - 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.0 - 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(settings.on == 'hover') {
  3503. $dimmable
  3504. .on('mouseenter' + eventNamespace, module.show)
  3505. .on('mouseleave' + eventNamespace, module.hide)
  3506. ;
  3507. }
  3508. else if(settings.on == 'click') {
  3509. $dimmable
  3510. .on(clickEvent + eventNamespace, module.toggle)
  3511. ;
  3512. }
  3513. if( module.is.page() ) {
  3514. module.debug('Setting as a page dimmer', $dimmable);
  3515. module.set.pageDimmer();
  3516. }
  3517. if( module.is.closable() ) {
  3518. module.verbose('Adding dimmer close event', $dimmer);
  3519. $dimmable
  3520. .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
  3521. ;
  3522. }
  3523. }
  3524. },
  3525. unbind: {
  3526. events: function() {
  3527. $module
  3528. .removeData(moduleNamespace)
  3529. ;
  3530. $dimmable
  3531. .off(eventNamespace)
  3532. ;
  3533. }
  3534. },
  3535. event: {
  3536. click: function(event) {
  3537. module.verbose('Determining if event occured on dimmer', event);
  3538. if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
  3539. module.hide();
  3540. event.stopImmediatePropagation();
  3541. }
  3542. }
  3543. },
  3544. addContent: function(element) {
  3545. var
  3546. $content = $(element)
  3547. ;
  3548. module.debug('Add content to dimmer', $content);
  3549. if($content.parent()[0] !== $dimmer[0]) {
  3550. $content.detach().appendTo($dimmer);
  3551. }
  3552. },
  3553. create: function() {
  3554. var
  3555. $element = $( settings.template.dimmer() )
  3556. ;
  3557. if(settings.dimmerName) {
  3558. module.debug('Creating named dimmer', settings.dimmerName);
  3559. $element.addClass(settings.dimmerName);
  3560. }
  3561. $element
  3562. .appendTo($dimmable)
  3563. ;
  3564. return $element;
  3565. },
  3566. show: function(callback) {
  3567. callback = $.isFunction(callback)
  3568. ? callback
  3569. : function(){}
  3570. ;
  3571. module.debug('Showing dimmer', $dimmer, settings);
  3572. if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
  3573. module.animate.show(callback);
  3574. settings.onShow.call(element);
  3575. settings.onChange.call(element);
  3576. }
  3577. else {
  3578. module.debug('Dimmer is already shown or disabled');
  3579. }
  3580. },
  3581. hide: function(callback) {
  3582. callback = $.isFunction(callback)
  3583. ? callback
  3584. : function(){}
  3585. ;
  3586. if( module.is.dimmed() || module.is.animating() ) {
  3587. module.debug('Hiding dimmer', $dimmer);
  3588. module.animate.hide(callback);
  3589. settings.onHide.call(element);
  3590. settings.onChange.call(element);
  3591. }
  3592. else {
  3593. module.debug('Dimmer is not visible');
  3594. }
  3595. },
  3596. toggle: function() {
  3597. module.verbose('Toggling dimmer visibility', $dimmer);
  3598. if( !module.is.dimmed() ) {
  3599. module.show();
  3600. }
  3601. else {
  3602. module.hide();
  3603. }
  3604. },
  3605. animate: {
  3606. show: function(callback) {
  3607. callback = $.isFunction(callback)
  3608. ? callback
  3609. : function(){}
  3610. ;
  3611. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3612. if(settings.opacity !== 'auto') {
  3613. module.set.opacity();
  3614. }
  3615. $dimmer
  3616. .transition({
  3617. displayType : 'flex',
  3618. animation : settings.transition + ' in',
  3619. queue : false,
  3620. duration : module.get.duration(),
  3621. useFailSafe : true,
  3622. onStart : function() {
  3623. module.set.dimmed();
  3624. },
  3625. onComplete : function() {
  3626. module.set.active();
  3627. callback();
  3628. }
  3629. })
  3630. ;
  3631. }
  3632. else {
  3633. module.verbose('Showing dimmer animation with javascript');
  3634. module.set.dimmed();
  3635. if(settings.opacity == 'auto') {
  3636. settings.opacity = 0.8;
  3637. }
  3638. $dimmer
  3639. .stop()
  3640. .css({
  3641. opacity : 0,
  3642. width : '100%',
  3643. height : '100%'
  3644. })
  3645. .fadeTo(module.get.duration(), settings.opacity, function() {
  3646. $dimmer.removeAttr('style');
  3647. module.set.active();
  3648. callback();
  3649. })
  3650. ;
  3651. }
  3652. },
  3653. hide: function(callback) {
  3654. callback = $.isFunction(callback)
  3655. ? callback
  3656. : function(){}
  3657. ;
  3658. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3659. module.verbose('Hiding dimmer with css');
  3660. $dimmer
  3661. .transition({
  3662. displayType : 'flex',
  3663. animation : settings.transition + ' out',
  3664. queue : false,
  3665. duration : module.get.duration(),
  3666. useFailSafe : true,
  3667. onStart : function() {
  3668. module.remove.dimmed();
  3669. },
  3670. onComplete : function() {
  3671. module.remove.active();
  3672. callback();
  3673. }
  3674. })
  3675. ;
  3676. }
  3677. else {
  3678. module.verbose('Hiding dimmer with javascript');
  3679. module.remove.dimmed();
  3680. $dimmer
  3681. .stop()
  3682. .fadeOut(module.get.duration(), function() {
  3683. module.remove.active();
  3684. $dimmer.removeAttr('style');
  3685. callback();
  3686. })
  3687. ;
  3688. }
  3689. }
  3690. },
  3691. get: {
  3692. dimmer: function() {
  3693. return $dimmer;
  3694. },
  3695. duration: function() {
  3696. if(typeof settings.duration == 'object') {
  3697. if( module.is.active() ) {
  3698. return settings.duration.hide;
  3699. }
  3700. else {
  3701. return settings.duration.show;
  3702. }
  3703. }
  3704. return settings.duration;
  3705. }
  3706. },
  3707. has: {
  3708. dimmer: function() {
  3709. if(settings.dimmerName) {
  3710. return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
  3711. }
  3712. else {
  3713. return ( $module.find(selector.dimmer).length > 0 );
  3714. }
  3715. }
  3716. },
  3717. is: {
  3718. active: function() {
  3719. return $dimmer.hasClass(className.active);
  3720. },
  3721. animating: function() {
  3722. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
  3723. },
  3724. closable: function() {
  3725. if(settings.closable == 'auto') {
  3726. if(settings.on == 'hover') {
  3727. return false;
  3728. }
  3729. return true;
  3730. }
  3731. return settings.closable;
  3732. },
  3733. dimmer: function() {
  3734. return $module.hasClass(className.dimmer);
  3735. },
  3736. dimmable: function() {
  3737. return $module.hasClass(className.dimmable);
  3738. },
  3739. dimmed: function() {
  3740. return $dimmable.hasClass(className.dimmed);
  3741. },
  3742. disabled: function() {
  3743. return $dimmable.hasClass(className.disabled);
  3744. },
  3745. enabled: function() {
  3746. return !module.is.disabled();
  3747. },
  3748. page: function () {
  3749. return $dimmable.is('body');
  3750. },
  3751. pageDimmer: function() {
  3752. return $dimmer.hasClass(className.pageDimmer);
  3753. }
  3754. },
  3755. can: {
  3756. show: function() {
  3757. return !$dimmer.hasClass(className.disabled);
  3758. }
  3759. },
  3760. set: {
  3761. opacity: function(opacity) {
  3762. var
  3763. color = $dimmer.css('background-color'),
  3764. colorArray = color.split(','),
  3765. isRGB = (colorArray && colorArray.length == 3),
  3766. isRGBA = (colorArray && colorArray.length == 4)
  3767. ;
  3768. opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
  3769. if(isRGB || isRGBA) {
  3770. colorArray[3] = opacity + ')';
  3771. color = colorArray.join(',');
  3772. }
  3773. else {
  3774. color = 'rgba(0, 0, 0, ' + opacity + ')';
  3775. }
  3776. module.debug('Setting opacity to', opacity);
  3777. $dimmer.css('background-color', color);
  3778. },
  3779. active: function() {
  3780. $dimmer.addClass(className.active);
  3781. },
  3782. dimmable: function() {
  3783. $dimmable.addClass(className.dimmable);
  3784. },
  3785. dimmed: function() {
  3786. $dimmable.addClass(className.dimmed);
  3787. },
  3788. pageDimmer: function() {
  3789. $dimmer.addClass(className.pageDimmer);
  3790. },
  3791. disabled: function() {
  3792. $dimmer.addClass(className.disabled);
  3793. },
  3794. variation: function(variation) {
  3795. variation = variation || settings.variation;
  3796. if(variation) {
  3797. $dimmer.addClass(variation);
  3798. }
  3799. }
  3800. },
  3801. remove: {
  3802. active: function() {
  3803. $dimmer
  3804. .removeClass(className.active)
  3805. ;
  3806. },
  3807. dimmed: function() {
  3808. $dimmable.removeClass(className.dimmed);
  3809. },
  3810. disabled: function() {
  3811. $dimmer.removeClass(className.disabled);
  3812. },
  3813. variation: function(variation) {
  3814. variation = variation || settings.variation;
  3815. if(variation) {
  3816. $dimmer.removeClass(variation);
  3817. }
  3818. }
  3819. },
  3820. setting: function(name, value) {
  3821. module.debug('Changing setting', name, value);
  3822. if( $.isPlainObject(name) ) {
  3823. $.extend(true, settings, name);
  3824. }
  3825. else if(value !== undefined) {
  3826. if($.isPlainObject(settings[name])) {
  3827. $.extend(true, settings[name], value);
  3828. }
  3829. else {
  3830. settings[name] = value;
  3831. }
  3832. }
  3833. else {
  3834. return settings[name];
  3835. }
  3836. },
  3837. internal: function(name, value) {
  3838. if( $.isPlainObject(name) ) {
  3839. $.extend(true, module, name);
  3840. }
  3841. else if(value !== undefined) {
  3842. module[name] = value;
  3843. }
  3844. else {
  3845. return module[name];
  3846. }
  3847. },
  3848. debug: function() {
  3849. if(!settings.silent && settings.debug) {
  3850. if(settings.performance) {
  3851. module.performance.log(arguments);
  3852. }
  3853. else {
  3854. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3855. module.debug.apply(console, arguments);
  3856. }
  3857. }
  3858. },
  3859. verbose: function() {
  3860. if(!settings.silent && settings.verbose && settings.debug) {
  3861. if(settings.performance) {
  3862. module.performance.log(arguments);
  3863. }
  3864. else {
  3865. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3866. module.verbose.apply(console, arguments);
  3867. }
  3868. }
  3869. },
  3870. error: function() {
  3871. if(!settings.silent) {
  3872. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3873. module.error.apply(console, arguments);
  3874. }
  3875. },
  3876. performance: {
  3877. log: function(message) {
  3878. var
  3879. currentTime,
  3880. executionTime,
  3881. previousTime
  3882. ;
  3883. if(settings.performance) {
  3884. currentTime = new Date().getTime();
  3885. previousTime = time || currentTime;
  3886. executionTime = currentTime - previousTime;
  3887. time = currentTime;
  3888. performance.push({
  3889. 'Name' : message[0],
  3890. 'Arguments' : [].slice.call(message, 1) || '',
  3891. 'Element' : element,
  3892. 'Execution Time' : executionTime
  3893. });
  3894. }
  3895. clearTimeout(module.performance.timer);
  3896. module.performance.timer = setTimeout(module.performance.display, 500);
  3897. },
  3898. display: function() {
  3899. var
  3900. title = settings.name + ':',
  3901. totalTime = 0
  3902. ;
  3903. time = false;
  3904. clearTimeout(module.performance.timer);
  3905. $.each(performance, function(index, data) {
  3906. totalTime += data['Execution Time'];
  3907. });
  3908. title += ' ' + totalTime + 'ms';
  3909. if(moduleSelector) {
  3910. title += ' \'' + moduleSelector + '\'';
  3911. }
  3912. if($allModules.length > 1) {
  3913. title += ' ' + '(' + $allModules.length + ')';
  3914. }
  3915. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3916. console.groupCollapsed(title);
  3917. if(console.table) {
  3918. console.table(performance);
  3919. }
  3920. else {
  3921. $.each(performance, function(index, data) {
  3922. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  3923. });
  3924. }
  3925. console.groupEnd();
  3926. }
  3927. performance = [];
  3928. }
  3929. },
  3930. invoke: function(query, passedArguments, context) {
  3931. var
  3932. object = instance,
  3933. maxDepth,
  3934. found,
  3935. response
  3936. ;
  3937. passedArguments = passedArguments || queryArguments;
  3938. context = element || context;
  3939. if(typeof query == 'string' && object !== undefined) {
  3940. query = query.split(/[\. ]/);
  3941. maxDepth = query.length - 1;
  3942. $.each(query, function(depth, value) {
  3943. var camelCaseValue = (depth != maxDepth)
  3944. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3945. : query
  3946. ;
  3947. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  3948. object = object[camelCaseValue];
  3949. }
  3950. else if( object[camelCaseValue] !== undefined ) {
  3951. found = object[camelCaseValue];
  3952. return false;
  3953. }
  3954. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  3955. object = object[value];
  3956. }
  3957. else if( object[value] !== undefined ) {
  3958. found = object[value];
  3959. return false;
  3960. }
  3961. else {
  3962. module.error(error.method, query);
  3963. return false;
  3964. }
  3965. });
  3966. }
  3967. if ( $.isFunction( found ) ) {
  3968. response = found.apply(context, passedArguments);
  3969. }
  3970. else if(found !== undefined) {
  3971. response = found;
  3972. }
  3973. if($.isArray(returnedValue)) {
  3974. returnedValue.push(response);
  3975. }
  3976. else if(returnedValue !== undefined) {
  3977. returnedValue = [returnedValue, response];
  3978. }
  3979. else if(response !== undefined) {
  3980. returnedValue = response;
  3981. }
  3982. return found;
  3983. }
  3984. };
  3985. module.preinitialize();
  3986. if(methodInvoked) {
  3987. if(instance === undefined) {
  3988. module.initialize();
  3989. }
  3990. module.invoke(query);
  3991. }
  3992. else {
  3993. if(instance !== undefined) {
  3994. instance.invoke('destroy');
  3995. }
  3996. module.initialize();
  3997. }
  3998. })
  3999. ;
  4000. return (returnedValue !== undefined)
  4001. ? returnedValue
  4002. : this
  4003. ;
  4004. };
  4005. $.fn.dimmer.settings = {
  4006. name : 'Dimmer',
  4007. namespace : 'dimmer',
  4008. silent : false,
  4009. debug : false,
  4010. verbose : false,
  4011. performance : true,
  4012. // name to distinguish between multiple dimmers in context
  4013. dimmerName : false,
  4014. // whether to add a variation type
  4015. variation : false,
  4016. // whether to bind close events
  4017. closable : 'auto',
  4018. // whether to use css animations
  4019. useCSS : true,
  4020. // css animation to use
  4021. transition : 'fade',
  4022. // event to bind to
  4023. on : false,
  4024. // overriding opacity value
  4025. opacity : 'auto',
  4026. // transition durations
  4027. duration : {
  4028. show : 500,
  4029. hide : 500
  4030. },
  4031. onChange : function(){},
  4032. onShow : function(){},
  4033. onHide : function(){},
  4034. error : {
  4035. method : 'The method you called is not defined.'
  4036. },
  4037. className : {
  4038. active : 'active',
  4039. animating : 'animating',
  4040. dimmable : 'dimmable',
  4041. dimmed : 'dimmed',
  4042. dimmer : 'dimmer',
  4043. disabled : 'disabled',
  4044. hide : 'hide',
  4045. pageDimmer : 'page',
  4046. show : 'show'
  4047. },
  4048. selector: {
  4049. dimmer : '> .ui.dimmer',
  4050. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  4051. },
  4052. template: {
  4053. dimmer: function() {
  4054. return $('<div />').attr('class', 'ui dimmer');
  4055. }
  4056. }
  4057. };
  4058. })( jQuery, window, document );
  4059. /*!
  4060. * # Semantic UI 2.3.0 - Dropdown
  4061. * http://github.com/semantic-org/semantic-ui/
  4062. *
  4063. *
  4064. * Released under the MIT license
  4065. * http://opensource.org/licenses/MIT
  4066. *
  4067. */
  4068. ;(function ($, window, document, undefined) {
  4069. "use strict";
  4070. window = (typeof window != 'undefined' && window.Math == Math)
  4071. ? window
  4072. : (typeof self != 'undefined' && self.Math == Math)
  4073. ? self
  4074. : Function('return this')()
  4075. ;
  4076. $.fn.dropdown = function(parameters) {
  4077. var
  4078. $allModules = $(this),
  4079. $document = $(document),
  4080. moduleSelector = $allModules.selector || '',
  4081. hasTouch = ('ontouchstart' in document.documentElement),
  4082. time = new Date().getTime(),
  4083. performance = [],
  4084. query = arguments[0],
  4085. methodInvoked = (typeof query == 'string'),
  4086. queryArguments = [].slice.call(arguments, 1),
  4087. returnedValue
  4088. ;
  4089. $allModules
  4090. .each(function(elementIndex) {
  4091. var
  4092. settings = ( $.isPlainObject(parameters) )
  4093. ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
  4094. : $.extend({}, $.fn.dropdown.settings),
  4095. className = settings.className,
  4096. message = settings.message,
  4097. fields = settings.fields,
  4098. keys = settings.keys,
  4099. metadata = settings.metadata,
  4100. namespace = settings.namespace,
  4101. regExp = settings.regExp,
  4102. selector = settings.selector,
  4103. error = settings.error,
  4104. templates = settings.templates,
  4105. eventNamespace = '.' + namespace,
  4106. moduleNamespace = 'module-' + namespace,
  4107. $module = $(this),
  4108. $context = $(settings.context),
  4109. $text = $module.find(selector.text),
  4110. $search = $module.find(selector.search),
  4111. $sizer = $module.find(selector.sizer),
  4112. $input = $module.find(selector.input),
  4113. $icon = $module.find(selector.icon),
  4114. $combo = ($module.prev().find(selector.text).length > 0)
  4115. ? $module.prev().find(selector.text)
  4116. : $module.prev(),
  4117. $menu = $module.children(selector.menu),
  4118. $item = $menu.find(selector.item),
  4119. activated = false,
  4120. itemActivated = false,
  4121. internalChange = false,
  4122. element = this,
  4123. instance = $module.data(moduleNamespace),
  4124. initialLoad,
  4125. pageLostFocus,
  4126. willRefocus,
  4127. elementNamespace,
  4128. id,
  4129. selectObserver,
  4130. menuObserver,
  4131. module
  4132. ;
  4133. module = {
  4134. initialize: function() {
  4135. module.debug('Initializing dropdown', settings);
  4136. if( module.is.alreadySetup() ) {
  4137. module.setup.reference();
  4138. }
  4139. else {
  4140. module.setup.layout();
  4141. if(settings.values) {
  4142. module.change.values(settings.values);
  4143. }
  4144. module.refreshData();
  4145. module.save.defaults();
  4146. module.restore.selected();
  4147. module.create.id();
  4148. module.bind.events();
  4149. module.observeChanges();
  4150. module.instantiate();
  4151. }
  4152. },
  4153. instantiate: function() {
  4154. module.verbose('Storing instance of dropdown', module);
  4155. instance = module;
  4156. $module
  4157. .data(moduleNamespace, module)
  4158. ;
  4159. },
  4160. destroy: function() {
  4161. module.verbose('Destroying previous dropdown', $module);
  4162. module.remove.tabbable();
  4163. $module
  4164. .off(eventNamespace)
  4165. .removeData(moduleNamespace)
  4166. ;
  4167. $menu
  4168. .off(eventNamespace)
  4169. ;
  4170. $document
  4171. .off(elementNamespace)
  4172. ;
  4173. module.disconnect.menuObserver();
  4174. module.disconnect.selectObserver();
  4175. },
  4176. observeChanges: function() {
  4177. if('MutationObserver' in window) {
  4178. selectObserver = new MutationObserver(module.event.select.mutation);
  4179. menuObserver = new MutationObserver(module.event.menu.mutation);
  4180. module.debug('Setting up mutation observer', selectObserver, menuObserver);
  4181. module.observe.select();
  4182. module.observe.menu();
  4183. }
  4184. },
  4185. disconnect: {
  4186. menuObserver: function() {
  4187. if(menuObserver) {
  4188. menuObserver.disconnect();
  4189. }
  4190. },
  4191. selectObserver: function() {
  4192. if(selectObserver) {
  4193. selectObserver.disconnect();
  4194. }
  4195. }
  4196. },
  4197. observe: {
  4198. select: function() {
  4199. if(module.has.input()) {
  4200. selectObserver.observe($module[0], {
  4201. childList : true,
  4202. subtree : true
  4203. });
  4204. }
  4205. },
  4206. menu: function() {
  4207. if(module.has.menu()) {
  4208. menuObserver.observe($menu[0], {
  4209. childList : true,
  4210. subtree : true
  4211. });
  4212. }
  4213. }
  4214. },
  4215. create: {
  4216. id: function() {
  4217. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  4218. elementNamespace = '.' + id;
  4219. module.verbose('Creating unique id for element', id);
  4220. },
  4221. userChoice: function(values) {
  4222. var
  4223. $userChoices,
  4224. $userChoice,
  4225. isUserValue,
  4226. html
  4227. ;
  4228. values = values || module.get.userValues();
  4229. if(!values) {
  4230. return false;
  4231. }
  4232. values = $.isArray(values)
  4233. ? values
  4234. : [values]
  4235. ;
  4236. $.each(values, function(index, value) {
  4237. if(module.get.item(value) === false) {
  4238. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  4239. $userChoice = $('<div />')
  4240. .html(html)
  4241. .attr('data-' + metadata.value, value)
  4242. .attr('data-' + metadata.text, value)
  4243. .addClass(className.addition)
  4244. .addClass(className.item)
  4245. ;
  4246. if(settings.hideAdditions) {
  4247. $userChoice.addClass(className.hidden);
  4248. }
  4249. $userChoices = ($userChoices === undefined)
  4250. ? $userChoice
  4251. : $userChoices.add($userChoice)
  4252. ;
  4253. module.verbose('Creating user choices for value', value, $userChoice);
  4254. }
  4255. });
  4256. return $userChoices;
  4257. },
  4258. userLabels: function(value) {
  4259. var
  4260. userValues = module.get.userValues()
  4261. ;
  4262. if(userValues) {
  4263. module.debug('Adding user labels', userValues);
  4264. $.each(userValues, function(index, value) {
  4265. module.verbose('Adding custom user value');
  4266. module.add.label(value, value);
  4267. });
  4268. }
  4269. },
  4270. menu: function() {
  4271. $menu = $('<div />')
  4272. .addClass(className.menu)
  4273. .appendTo($module)
  4274. ;
  4275. },
  4276. sizer: function() {
  4277. $sizer = $('<span />')
  4278. .addClass(className.sizer)
  4279. .insertAfter($search)
  4280. ;
  4281. }
  4282. },
  4283. search: function(query) {
  4284. query = (query !== undefined)
  4285. ? query
  4286. : module.get.query()
  4287. ;
  4288. module.verbose('Searching for query', query);
  4289. if(module.has.minCharacters(query)) {
  4290. module.filter(query);
  4291. }
  4292. else {
  4293. module.hide();
  4294. }
  4295. },
  4296. select: {
  4297. firstUnfiltered: function() {
  4298. module.verbose('Selecting first non-filtered element');
  4299. module.remove.selectedItem();
  4300. $item
  4301. .not(selector.unselectable)
  4302. .not(selector.addition + selector.hidden)
  4303. .eq(0)
  4304. .addClass(className.selected)
  4305. ;
  4306. },
  4307. nextAvailable: function($selected) {
  4308. $selected = $selected.eq(0);
  4309. var
  4310. $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
  4311. $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
  4312. hasNext = ($nextAvailable.length > 0)
  4313. ;
  4314. if(hasNext) {
  4315. module.verbose('Moving selection to', $nextAvailable);
  4316. $nextAvailable.addClass(className.selected);
  4317. }
  4318. else {
  4319. module.verbose('Moving selection to', $prevAvailable);
  4320. $prevAvailable.addClass(className.selected);
  4321. }
  4322. }
  4323. },
  4324. setup: {
  4325. api: function() {
  4326. var
  4327. apiSettings = {
  4328. debug : settings.debug,
  4329. urlData : {
  4330. value : module.get.value(),
  4331. query : module.get.query()
  4332. },
  4333. on : false
  4334. }
  4335. ;
  4336. module.verbose('First request, initializing API');
  4337. $module
  4338. .api(apiSettings)
  4339. ;
  4340. },
  4341. layout: function() {
  4342. if( $module.is('select') ) {
  4343. module.setup.select();
  4344. module.setup.returnedObject();
  4345. }
  4346. if( !module.has.menu() ) {
  4347. module.create.menu();
  4348. }
  4349. if( module.is.search() && !module.has.search() ) {
  4350. module.verbose('Adding search input');
  4351. $search = $('<input />')
  4352. .addClass(className.search)
  4353. .prop('autocomplete', 'off')
  4354. .insertBefore($text)
  4355. ;
  4356. }
  4357. if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
  4358. module.create.sizer();
  4359. }
  4360. if(settings.allowTab) {
  4361. module.set.tabbable();
  4362. }
  4363. },
  4364. select: function() {
  4365. var
  4366. selectValues = module.get.selectValues()
  4367. ;
  4368. module.debug('Dropdown initialized on a select', selectValues);
  4369. if( $module.is('select') ) {
  4370. $input = $module;
  4371. }
  4372. // see if select is placed correctly already
  4373. if($input.parent(selector.dropdown).length > 0) {
  4374. module.debug('UI dropdown already exists. Creating dropdown menu only');
  4375. $module = $input.closest(selector.dropdown);
  4376. if( !module.has.menu() ) {
  4377. module.create.menu();
  4378. }
  4379. $menu = $module.children(selector.menu);
  4380. module.setup.menu(selectValues);
  4381. }
  4382. else {
  4383. module.debug('Creating entire dropdown from select');
  4384. $module = $('<div />')
  4385. .attr('class', $input.attr('class') )
  4386. .addClass(className.selection)
  4387. .addClass(className.dropdown)
  4388. .html( templates.dropdown(selectValues) )
  4389. .insertBefore($input)
  4390. ;
  4391. if($input.hasClass(className.multiple) && $input.prop('multiple') === false) {
  4392. module.error(error.missingMultiple);
  4393. $input.prop('multiple', true);
  4394. }
  4395. if($input.is('[multiple]')) {
  4396. module.set.multiple();
  4397. }
  4398. if ($input.prop('disabled')) {
  4399. module.debug('Disabling dropdown');
  4400. $module.addClass(className.disabled);
  4401. }
  4402. $input
  4403. .removeAttr('class')
  4404. .detach()
  4405. .prependTo($module)
  4406. ;
  4407. }
  4408. module.refresh();
  4409. },
  4410. menu: function(values) {
  4411. $menu.html( templates.menu(values, fields));
  4412. $item = $menu.find(selector.item);
  4413. },
  4414. reference: function() {
  4415. module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
  4416. // replace module reference
  4417. $module = $module.parent(selector.dropdown);
  4418. instance = $module.data(moduleNamespace);
  4419. element = $module.get(0);
  4420. module.refresh();
  4421. module.setup.returnedObject();
  4422. },
  4423. returnedObject: function() {
  4424. var
  4425. $firstModules = $allModules.slice(0, elementIndex),
  4426. $lastModules = $allModules.slice(elementIndex + 1)
  4427. ;
  4428. // adjust all modules to use correct reference
  4429. $allModules = $firstModules.add($module).add($lastModules);
  4430. }
  4431. },
  4432. refresh: function() {
  4433. module.refreshSelectors();
  4434. module.refreshData();
  4435. },
  4436. refreshItems: function() {
  4437. $item = $menu.find(selector.item);
  4438. },
  4439. refreshSelectors: function() {
  4440. module.verbose('Refreshing selector cache');
  4441. $text = $module.find(selector.text);
  4442. $search = $module.find(selector.search);
  4443. $input = $module.find(selector.input);
  4444. $icon = $module.find(selector.icon);
  4445. $combo = ($module.prev().find(selector.text).length > 0)
  4446. ? $module.prev().find(selector.text)
  4447. : $module.prev()
  4448. ;
  4449. $menu = $module.children(selector.menu);
  4450. $item = $menu.find(selector.item);
  4451. },
  4452. refreshData: function() {
  4453. module.verbose('Refreshing cached metadata');
  4454. $item
  4455. .removeData(metadata.text)
  4456. .removeData(metadata.value)
  4457. ;
  4458. },
  4459. clearData: function() {
  4460. module.verbose('Clearing metadata');
  4461. $item
  4462. .removeData(metadata.text)
  4463. .removeData(metadata.value)
  4464. ;
  4465. $module
  4466. .removeData(metadata.defaultText)
  4467. .removeData(metadata.defaultValue)
  4468. .removeData(metadata.placeholderText)
  4469. ;
  4470. },
  4471. toggle: function() {
  4472. module.verbose('Toggling menu visibility');
  4473. if( !module.is.active() ) {
  4474. module.show();
  4475. }
  4476. else {
  4477. module.hide();
  4478. }
  4479. },
  4480. show: function(callback) {
  4481. callback = $.isFunction(callback)
  4482. ? callback
  4483. : function(){}
  4484. ;
  4485. if(!module.can.show() && module.is.remote()) {
  4486. module.debug('No API results retrieved, searching before show');
  4487. module.queryRemote(module.get.query(), module.show);
  4488. }
  4489. if( module.can.show() && !module.is.active() ) {
  4490. module.debug('Showing dropdown');
  4491. if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
  4492. module.remove.message();
  4493. }
  4494. if(module.is.allFiltered()) {
  4495. return true;
  4496. }
  4497. if(settings.onShow.call(element) !== false) {
  4498. module.animate.show(function() {
  4499. if( module.can.click() ) {
  4500. module.bind.intent();
  4501. }
  4502. if(module.has.menuSearch()) {
  4503. module.focusSearch();
  4504. }
  4505. module.set.visible();
  4506. callback.call(element);
  4507. });
  4508. }
  4509. }
  4510. },
  4511. hide: function(callback) {
  4512. callback = $.isFunction(callback)
  4513. ? callback
  4514. : function(){}
  4515. ;
  4516. if( module.is.active() && !module.is.animatingOutward() ) {
  4517. module.debug('Hiding dropdown');
  4518. if(settings.onHide.call(element) !== false) {
  4519. module.animate.hide(function() {
  4520. module.remove.visible();
  4521. callback.call(element);
  4522. });
  4523. }
  4524. }
  4525. },
  4526. hideOthers: function() {
  4527. module.verbose('Finding other dropdowns to hide');
  4528. $allModules
  4529. .not($module)
  4530. .has(selector.menu + '.' + className.visible)
  4531. .dropdown('hide')
  4532. ;
  4533. },
  4534. hideMenu: function() {
  4535. module.verbose('Hiding menu instantaneously');
  4536. module.remove.active();
  4537. module.remove.visible();
  4538. $menu.transition('hide');
  4539. },
  4540. hideSubMenus: function() {
  4541. var
  4542. $subMenus = $menu.children(selector.item).find(selector.menu)
  4543. ;
  4544. module.verbose('Hiding sub menus', $subMenus);
  4545. $subMenus.transition('hide');
  4546. },
  4547. bind: {
  4548. events: function() {
  4549. if(hasTouch) {
  4550. module.bind.touchEvents();
  4551. }
  4552. module.bind.keyboardEvents();
  4553. module.bind.inputEvents();
  4554. module.bind.mouseEvents();
  4555. },
  4556. touchEvents: function() {
  4557. module.debug('Touch device detected binding additional touch events');
  4558. if( module.is.searchSelection() ) {
  4559. // do nothing special yet
  4560. }
  4561. else if( module.is.single() ) {
  4562. $module
  4563. .on('touchstart' + eventNamespace, module.event.test.toggle)
  4564. ;
  4565. }
  4566. $menu
  4567. .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
  4568. ;
  4569. },
  4570. keyboardEvents: function() {
  4571. module.verbose('Binding keyboard events');
  4572. $module
  4573. .on('keydown' + eventNamespace, module.event.keydown)
  4574. ;
  4575. if( module.has.search() ) {
  4576. $module
  4577. .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
  4578. ;
  4579. }
  4580. if( module.is.multiple() ) {
  4581. $document
  4582. .on('keydown' + elementNamespace, module.event.document.keydown)
  4583. ;
  4584. }
  4585. },
  4586. inputEvents: function() {
  4587. module.verbose('Binding input change events');
  4588. $module
  4589. .on('change' + eventNamespace, selector.input, module.event.change)
  4590. ;
  4591. },
  4592. mouseEvents: function() {
  4593. module.verbose('Binding mouse events');
  4594. if(module.is.multiple()) {
  4595. $module
  4596. .on('click' + eventNamespace, selector.label, module.event.label.click)
  4597. .on('click' + eventNamespace, selector.remove, module.event.remove.click)
  4598. ;
  4599. }
  4600. if( module.is.searchSelection() ) {
  4601. $module
  4602. .on('mousedown' + eventNamespace, module.event.mousedown)
  4603. .on('mouseup' + eventNamespace, module.event.mouseup)
  4604. .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
  4605. .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
  4606. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  4607. .on('focus' + eventNamespace, selector.search, module.event.search.focus)
  4608. .on('click' + eventNamespace, selector.search, module.event.search.focus)
  4609. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  4610. .on('click' + eventNamespace, selector.text, module.event.text.focus)
  4611. ;
  4612. if(module.is.multiple()) {
  4613. $module
  4614. .on('click' + eventNamespace, module.event.click)
  4615. ;
  4616. }
  4617. }
  4618. else {
  4619. if(settings.on == 'click') {
  4620. $module
  4621. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  4622. .on('click' + eventNamespace, module.event.test.toggle)
  4623. ;
  4624. }
  4625. else if(settings.on == 'hover') {
  4626. $module
  4627. .on('mouseenter' + eventNamespace, module.delay.show)
  4628. .on('mouseleave' + eventNamespace, module.delay.hide)
  4629. ;
  4630. }
  4631. else {
  4632. $module
  4633. .on(settings.on + eventNamespace, module.toggle)
  4634. ;
  4635. }
  4636. $module
  4637. .on('mousedown' + eventNamespace, module.event.mousedown)
  4638. .on('mouseup' + eventNamespace, module.event.mouseup)
  4639. .on('focus' + eventNamespace, module.event.focus)
  4640. ;
  4641. if(module.has.menuSearch() ) {
  4642. $module
  4643. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  4644. ;
  4645. }
  4646. else {
  4647. $module
  4648. .on('blur' + eventNamespace, module.event.blur)
  4649. ;
  4650. }
  4651. }
  4652. $menu
  4653. .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
  4654. .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
  4655. .on('click' + eventNamespace, selector.item, module.event.item.click)
  4656. ;
  4657. },
  4658. intent: function() {
  4659. module.verbose('Binding hide intent event to document');
  4660. if(hasTouch) {
  4661. $document
  4662. .on('touchstart' + elementNamespace, module.event.test.touch)
  4663. .on('touchmove' + elementNamespace, module.event.test.touch)
  4664. ;
  4665. }
  4666. $document
  4667. .on('click' + elementNamespace, module.event.test.hide)
  4668. ;
  4669. }
  4670. },
  4671. unbind: {
  4672. intent: function() {
  4673. module.verbose('Removing hide intent event from document');
  4674. if(hasTouch) {
  4675. $document
  4676. .off('touchstart' + elementNamespace)
  4677. .off('touchmove' + elementNamespace)
  4678. ;
  4679. }
  4680. $document
  4681. .off('click' + elementNamespace)
  4682. ;
  4683. }
  4684. },
  4685. filter: function(query) {
  4686. var
  4687. searchTerm = (query !== undefined)
  4688. ? query
  4689. : module.get.query(),
  4690. afterFiltered = function() {
  4691. if(module.is.multiple()) {
  4692. module.filterActive();
  4693. }
  4694. if(query || (!query && module.get.activeItem().length == 0)) {
  4695. module.select.firstUnfiltered();
  4696. }
  4697. if( module.has.allResultsFiltered() ) {
  4698. if( settings.onNoResults.call(element, searchTerm) ) {
  4699. if(settings.allowAdditions) {
  4700. if(settings.hideAdditions) {
  4701. module.verbose('User addition with no menu, setting empty style');
  4702. module.set.empty();
  4703. module.hideMenu();
  4704. }
  4705. }
  4706. else {
  4707. module.verbose('All items filtered, showing message', searchTerm);
  4708. module.add.message(message.noResults);
  4709. }
  4710. }
  4711. else {
  4712. module.verbose('All items filtered, hiding dropdown', searchTerm);
  4713. module.hideMenu();
  4714. }
  4715. }
  4716. else {
  4717. module.remove.empty();
  4718. module.remove.message();
  4719. }
  4720. if(settings.allowAdditions) {
  4721. module.add.userSuggestion(query);
  4722. }
  4723. if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
  4724. module.show();
  4725. }
  4726. }
  4727. ;
  4728. if(settings.useLabels && module.has.maxSelections()) {
  4729. return;
  4730. }
  4731. if(settings.apiSettings) {
  4732. if( module.can.useAPI() ) {
  4733. module.queryRemote(searchTerm, function() {
  4734. if(settings.filterRemoteData) {
  4735. module.filterItems(searchTerm);
  4736. }
  4737. afterFiltered();
  4738. });
  4739. }
  4740. else {
  4741. module.error(error.noAPI);
  4742. }
  4743. }
  4744. else {
  4745. module.filterItems(searchTerm);
  4746. afterFiltered();
  4747. }
  4748. },
  4749. queryRemote: function(query, callback) {
  4750. var
  4751. apiSettings = {
  4752. errorDuration : false,
  4753. cache : 'local',
  4754. throttle : settings.throttle,
  4755. urlData : {
  4756. query: query
  4757. },
  4758. onError: function() {
  4759. module.add.message(message.serverError);
  4760. callback();
  4761. },
  4762. onFailure: function() {
  4763. module.add.message(message.serverError);
  4764. callback();
  4765. },
  4766. onSuccess : function(response) {
  4767. module.remove.message();
  4768. module.setup.menu({
  4769. values: response[fields.remoteValues]
  4770. });
  4771. callback();
  4772. }
  4773. }
  4774. ;
  4775. if( !$module.api('get request') ) {
  4776. module.setup.api();
  4777. }
  4778. apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
  4779. $module
  4780. .api('setting', apiSettings)
  4781. .api('query')
  4782. ;
  4783. },
  4784. filterItems: function(query) {
  4785. var
  4786. searchTerm = (query !== undefined)
  4787. ? query
  4788. : module.get.query(),
  4789. results = null,
  4790. escapedTerm = module.escape.string(searchTerm),
  4791. beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm')
  4792. ;
  4793. // avoid loop if we're matching nothing
  4794. if( module.has.query() ) {
  4795. results = [];
  4796. module.verbose('Searching for matching values', searchTerm);
  4797. $item
  4798. .each(function(){
  4799. var
  4800. $choice = $(this),
  4801. text,
  4802. value
  4803. ;
  4804. if(settings.match == 'both' || settings.match == 'text') {
  4805. text = String(module.get.choiceText($choice, false));
  4806. if(text.search(beginsWithRegExp) !== -1) {
  4807. results.push(this);
  4808. return true;
  4809. }
  4810. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) {
  4811. results.push(this);
  4812. return true;
  4813. }
  4814. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) {
  4815. results.push(this);
  4816. return true;
  4817. }
  4818. }
  4819. if(settings.match == 'both' || settings.match == 'value') {
  4820. value = String(module.get.choiceValue($choice, text));
  4821. if(value.search(beginsWithRegExp) !== -1) {
  4822. results.push(this);
  4823. return true;
  4824. }
  4825. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, value)) {
  4826. results.push(this);
  4827. return true;
  4828. }
  4829. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, value)) {
  4830. results.push(this);
  4831. return true;
  4832. }
  4833. }
  4834. })
  4835. ;
  4836. }
  4837. module.debug('Showing only matched items', searchTerm);
  4838. module.remove.filteredItem();
  4839. if(results) {
  4840. $item
  4841. .not(results)
  4842. .addClass(className.filtered)
  4843. ;
  4844. }
  4845. },
  4846. fuzzySearch: function(query, term) {
  4847. var
  4848. termLength = term.length,
  4849. queryLength = query.length
  4850. ;
  4851. query = query.toLowerCase();
  4852. term = term.toLowerCase();
  4853. if(queryLength > termLength) {
  4854. return false;
  4855. }
  4856. if(queryLength === termLength) {
  4857. return (query === term);
  4858. }
  4859. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  4860. var
  4861. queryCharacter = query.charCodeAt(characterIndex)
  4862. ;
  4863. while(nextCharacterIndex < termLength) {
  4864. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  4865. continue search;
  4866. }
  4867. }
  4868. return false;
  4869. }
  4870. return true;
  4871. },
  4872. exactSearch: function (query, term) {
  4873. query = query.toLowerCase();
  4874. term = term.toLowerCase();
  4875. if(term.indexOf(query) > -1) {
  4876. return true;
  4877. }
  4878. return false;
  4879. },
  4880. filterActive: function() {
  4881. if(settings.useLabels) {
  4882. $item.filter('.' + className.active)
  4883. .addClass(className.filtered)
  4884. ;
  4885. }
  4886. },
  4887. focusSearch: function(skipHandler) {
  4888. if( module.has.search() && !module.is.focusedOnSearch() ) {
  4889. if(skipHandler) {
  4890. $module.off('focus' + eventNamespace, selector.search);
  4891. $search.focus();
  4892. $module.on('focus' + eventNamespace, selector.search, module.event.search.focus);
  4893. }
  4894. else {
  4895. $search.focus();
  4896. }
  4897. }
  4898. },
  4899. forceSelection: function() {
  4900. var
  4901. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  4902. $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
  4903. $selectedItem = ($currentlySelected.length > 0)
  4904. ? $currentlySelected
  4905. : $activeItem,
  4906. hasSelected = ($selectedItem.length > 0)
  4907. ;
  4908. if(hasSelected && !module.is.multiple()) {
  4909. module.debug('Forcing partial selection to selected item', $selectedItem);
  4910. module.event.item.click.call($selectedItem, {}, true);
  4911. return;
  4912. }
  4913. else {
  4914. if(settings.allowAdditions) {
  4915. module.set.selected(module.get.query());
  4916. module.remove.searchTerm();
  4917. }
  4918. else {
  4919. module.remove.searchTerm();
  4920. }
  4921. }
  4922. },
  4923. change: {
  4924. values: function(values) {
  4925. if(!settings.allowAdditions) {
  4926. module.clear();
  4927. }
  4928. module.debug('Creating dropdown with specified values', values);
  4929. module.setup.menu({values: values});
  4930. $.each(values, function(index, item) {
  4931. if(item.selected == true) {
  4932. module.debug('Setting initial selection to', item.value);
  4933. module.set.selected(item.value);
  4934. return true;
  4935. }
  4936. });
  4937. }
  4938. },
  4939. event: {
  4940. change: function() {
  4941. if(!internalChange) {
  4942. module.debug('Input changed, updating selection');
  4943. module.set.selected();
  4944. }
  4945. },
  4946. focus: function() {
  4947. if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
  4948. module.show();
  4949. }
  4950. },
  4951. blur: function(event) {
  4952. pageLostFocus = (document.activeElement === this);
  4953. if(!activated && !pageLostFocus) {
  4954. module.remove.activeLabel();
  4955. module.hide();
  4956. }
  4957. },
  4958. mousedown: function() {
  4959. if(module.is.searchSelection()) {
  4960. // prevent menu hiding on immediate re-focus
  4961. willRefocus = true;
  4962. }
  4963. else {
  4964. // prevents focus callback from occurring on mousedown
  4965. activated = true;
  4966. }
  4967. },
  4968. mouseup: function() {
  4969. if(module.is.searchSelection()) {
  4970. // prevent menu hiding on immediate re-focus
  4971. willRefocus = false;
  4972. }
  4973. else {
  4974. activated = false;
  4975. }
  4976. },
  4977. click: function(event) {
  4978. var
  4979. $target = $(event.target)
  4980. ;
  4981. // focus search
  4982. if($target.is($module)) {
  4983. if(!module.is.focusedOnSearch()) {
  4984. module.focusSearch();
  4985. }
  4986. else {
  4987. module.show();
  4988. }
  4989. }
  4990. },
  4991. search: {
  4992. focus: function() {
  4993. activated = true;
  4994. if(module.is.multiple()) {
  4995. module.remove.activeLabel();
  4996. }
  4997. if(settings.showOnFocus) {
  4998. module.search();
  4999. }
  5000. },
  5001. blur: function(event) {
  5002. pageLostFocus = (document.activeElement === this);
  5003. if(module.is.searchSelection() && !willRefocus) {
  5004. if(!itemActivated && !pageLostFocus) {
  5005. if(settings.forceSelection) {
  5006. module.forceSelection();
  5007. }
  5008. module.hide();
  5009. }
  5010. }
  5011. willRefocus = false;
  5012. }
  5013. },
  5014. icon: {
  5015. click: function(event) {
  5016. module.toggle();
  5017. }
  5018. },
  5019. text: {
  5020. focus: function(event) {
  5021. activated = true;
  5022. module.focusSearch();
  5023. }
  5024. },
  5025. input: function(event) {
  5026. if(module.is.multiple() || module.is.searchSelection()) {
  5027. module.set.filtered();
  5028. }
  5029. clearTimeout(module.timer);
  5030. module.timer = setTimeout(module.search, settings.delay.search);
  5031. },
  5032. label: {
  5033. click: function(event) {
  5034. var
  5035. $label = $(this),
  5036. $labels = $module.find(selector.label),
  5037. $activeLabels = $labels.filter('.' + className.active),
  5038. $nextActive = $label.nextAll('.' + className.active),
  5039. $prevActive = $label.prevAll('.' + className.active),
  5040. $range = ($nextActive.length > 0)
  5041. ? $label.nextUntil($nextActive).add($activeLabels).add($label)
  5042. : $label.prevUntil($prevActive).add($activeLabels).add($label)
  5043. ;
  5044. if(event.shiftKey) {
  5045. $activeLabels.removeClass(className.active);
  5046. $range.addClass(className.active);
  5047. }
  5048. else if(event.ctrlKey) {
  5049. $label.toggleClass(className.active);
  5050. }
  5051. else {
  5052. $activeLabels.removeClass(className.active);
  5053. $label.addClass(className.active);
  5054. }
  5055. settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
  5056. }
  5057. },
  5058. remove: {
  5059. click: function() {
  5060. var
  5061. $label = $(this).parent()
  5062. ;
  5063. if( $label.hasClass(className.active) ) {
  5064. // remove all selected labels
  5065. module.remove.activeLabels();
  5066. }
  5067. else {
  5068. // remove this label only
  5069. module.remove.activeLabels( $label );
  5070. }
  5071. }
  5072. },
  5073. test: {
  5074. toggle: function(event) {
  5075. var
  5076. toggleBehavior = (module.is.multiple())
  5077. ? module.show
  5078. : module.toggle
  5079. ;
  5080. if(module.is.bubbledLabelClick(event) || module.is.bubbledIconClick(event)) {
  5081. return;
  5082. }
  5083. if( module.determine.eventOnElement(event, toggleBehavior) ) {
  5084. event.preventDefault();
  5085. }
  5086. },
  5087. touch: function(event) {
  5088. module.determine.eventOnElement(event, function() {
  5089. if(event.type == 'touchstart') {
  5090. module.timer = setTimeout(function() {
  5091. module.hide();
  5092. }, settings.delay.touch);
  5093. }
  5094. else if(event.type == 'touchmove') {
  5095. clearTimeout(module.timer);
  5096. }
  5097. });
  5098. event.stopPropagation();
  5099. },
  5100. hide: function(event) {
  5101. module.determine.eventInModule(event, module.hide);
  5102. }
  5103. },
  5104. select: {
  5105. mutation: function(mutations) {
  5106. module.debug('<select> modified, recreating menu');
  5107. var
  5108. isSelectMutation = false
  5109. ;
  5110. $.each(mutations, function(index, mutation) {
  5111. if($(mutation.target).is('select') || $(mutation.addedNodes).is('select')) {
  5112. isSelectMutation = true;
  5113. return true;
  5114. }
  5115. });
  5116. if(isSelectMutation) {
  5117. module.disconnect.selectObserver();
  5118. module.refresh();
  5119. module.setup.select();
  5120. module.set.selected();
  5121. module.observe.select();
  5122. }
  5123. }
  5124. },
  5125. menu: {
  5126. mutation: function(mutations) {
  5127. var
  5128. mutation = mutations[0],
  5129. $addedNode = mutation.addedNodes
  5130. ? $(mutation.addedNodes[0])
  5131. : $(false),
  5132. $removedNode = mutation.removedNodes
  5133. ? $(mutation.removedNodes[0])
  5134. : $(false),
  5135. $changedNodes = $addedNode.add($removedNode),
  5136. isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
  5137. isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
  5138. ;
  5139. if(isUserAddition || isMessage) {
  5140. module.debug('Updating item selector cache');
  5141. module.refreshItems();
  5142. }
  5143. else {
  5144. module.debug('Menu modified, updating selector cache');
  5145. module.refresh();
  5146. }
  5147. },
  5148. mousedown: function() {
  5149. itemActivated = true;
  5150. },
  5151. mouseup: function() {
  5152. itemActivated = false;
  5153. }
  5154. },
  5155. item: {
  5156. mouseenter: function(event) {
  5157. var
  5158. $target = $(event.target),
  5159. $item = $(this),
  5160. $subMenu = $item.children(selector.menu),
  5161. $otherMenus = $item.siblings(selector.item).children(selector.menu),
  5162. hasSubMenu = ($subMenu.length > 0),
  5163. isBubbledEvent = ($subMenu.find($target).length > 0)
  5164. ;
  5165. if( !isBubbledEvent && hasSubMenu ) {
  5166. clearTimeout(module.itemTimer);
  5167. module.itemTimer = setTimeout(function() {
  5168. module.verbose('Showing sub-menu', $subMenu);
  5169. $.each($otherMenus, function() {
  5170. module.animate.hide(false, $(this));
  5171. });
  5172. module.animate.show(false, $subMenu);
  5173. }, settings.delay.show);
  5174. event.preventDefault();
  5175. }
  5176. },
  5177. mouseleave: function(event) {
  5178. var
  5179. $subMenu = $(this).children(selector.menu)
  5180. ;
  5181. if($subMenu.length > 0) {
  5182. clearTimeout(module.itemTimer);
  5183. module.itemTimer = setTimeout(function() {
  5184. module.verbose('Hiding sub-menu', $subMenu);
  5185. module.animate.hide(false, $subMenu);
  5186. }, settings.delay.hide);
  5187. }
  5188. },
  5189. click: function (event, skipRefocus) {
  5190. var
  5191. $choice = $(this),
  5192. $target = (event)
  5193. ? $(event.target)
  5194. : $(''),
  5195. $subMenu = $choice.find(selector.menu),
  5196. text = module.get.choiceText($choice),
  5197. value = module.get.choiceValue($choice, text),
  5198. hasSubMenu = ($subMenu.length > 0),
  5199. isBubbledEvent = ($subMenu.find($target).length > 0)
  5200. ;
  5201. // prevents IE11 bug where menu receives focus even though `tabindex=-1`
  5202. if(module.has.menuSearch()) {
  5203. $(document.activeElement).blur();
  5204. }
  5205. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  5206. if(module.is.searchSelection()) {
  5207. if(settings.allowAdditions) {
  5208. module.remove.userAddition();
  5209. }
  5210. module.remove.searchTerm();
  5211. if(!module.is.focusedOnSearch() && !(skipRefocus == true)) {
  5212. module.focusSearch(true);
  5213. }
  5214. }
  5215. if(!settings.useLabels) {
  5216. module.remove.filteredItem();
  5217. module.set.scrollPosition($choice);
  5218. }
  5219. module.determine.selectAction.call(this, text, value);
  5220. }
  5221. }
  5222. },
  5223. document: {
  5224. // label selection should occur even when element has no focus
  5225. keydown: function(event) {
  5226. var
  5227. pressedKey = event.which,
  5228. isShortcutKey = module.is.inObject(pressedKey, keys)
  5229. ;
  5230. if(isShortcutKey) {
  5231. var
  5232. $label = $module.find(selector.label),
  5233. $activeLabel = $label.filter('.' + className.active),
  5234. activeValue = $activeLabel.data(metadata.value),
  5235. labelIndex = $label.index($activeLabel),
  5236. labelCount = $label.length,
  5237. hasActiveLabel = ($activeLabel.length > 0),
  5238. hasMultipleActive = ($activeLabel.length > 1),
  5239. isFirstLabel = (labelIndex === 0),
  5240. isLastLabel = (labelIndex + 1 == labelCount),
  5241. isSearch = module.is.searchSelection(),
  5242. isFocusedOnSearch = module.is.focusedOnSearch(),
  5243. isFocused = module.is.focused(),
  5244. caretAtStart = (isFocusedOnSearch && module.get.caretPosition() === 0),
  5245. $nextLabel
  5246. ;
  5247. if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
  5248. return;
  5249. }
  5250. if(pressedKey == keys.leftArrow) {
  5251. // activate previous label
  5252. if((isFocused || caretAtStart) && !hasActiveLabel) {
  5253. module.verbose('Selecting previous label');
  5254. $label.last().addClass(className.active);
  5255. }
  5256. else if(hasActiveLabel) {
  5257. if(!event.shiftKey) {
  5258. module.verbose('Selecting previous label');
  5259. $label.removeClass(className.active);
  5260. }
  5261. else {
  5262. module.verbose('Adding previous label to selection');
  5263. }
  5264. if(isFirstLabel && !hasMultipleActive) {
  5265. $activeLabel.addClass(className.active);
  5266. }
  5267. else {
  5268. $activeLabel.prev(selector.siblingLabel)
  5269. .addClass(className.active)
  5270. .end()
  5271. ;
  5272. }
  5273. event.preventDefault();
  5274. }
  5275. }
  5276. else if(pressedKey == keys.rightArrow) {
  5277. // activate first label
  5278. if(isFocused && !hasActiveLabel) {
  5279. $label.first().addClass(className.active);
  5280. }
  5281. // activate next label
  5282. if(hasActiveLabel) {
  5283. if(!event.shiftKey) {
  5284. module.verbose('Selecting next label');
  5285. $label.removeClass(className.active);
  5286. }
  5287. else {
  5288. module.verbose('Adding next label to selection');
  5289. }
  5290. if(isLastLabel) {
  5291. if(isSearch) {
  5292. if(!isFocusedOnSearch) {
  5293. module.focusSearch();
  5294. }
  5295. else {
  5296. $label.removeClass(className.active);
  5297. }
  5298. }
  5299. else if(hasMultipleActive) {
  5300. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  5301. }
  5302. else {
  5303. $activeLabel.addClass(className.active);
  5304. }
  5305. }
  5306. else {
  5307. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  5308. }
  5309. event.preventDefault();
  5310. }
  5311. }
  5312. else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
  5313. if(hasActiveLabel) {
  5314. module.verbose('Removing active labels');
  5315. if(isLastLabel) {
  5316. if(isSearch && !isFocusedOnSearch) {
  5317. module.focusSearch();
  5318. }
  5319. }
  5320. $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
  5321. module.remove.activeLabels($activeLabel);
  5322. event.preventDefault();
  5323. }
  5324. else if(caretAtStart && !hasActiveLabel && pressedKey == keys.backspace) {
  5325. module.verbose('Removing last label on input backspace');
  5326. $activeLabel = $label.last().addClass(className.active);
  5327. module.remove.activeLabels($activeLabel);
  5328. }
  5329. }
  5330. else {
  5331. $activeLabel.removeClass(className.active);
  5332. }
  5333. }
  5334. }
  5335. },
  5336. keydown: function(event) {
  5337. var
  5338. pressedKey = event.which,
  5339. isShortcutKey = module.is.inObject(pressedKey, keys)
  5340. ;
  5341. if(isShortcutKey) {
  5342. var
  5343. $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
  5344. $activeItem = $menu.children('.' + className.active).eq(0),
  5345. $selectedItem = ($currentlySelected.length > 0)
  5346. ? $currentlySelected
  5347. : $activeItem,
  5348. $visibleItems = ($selectedItem.length > 0)
  5349. ? $selectedItem.siblings(':not(.' + className.filtered +')').addBack()
  5350. : $menu.children(':not(.' + className.filtered +')'),
  5351. $subMenu = $selectedItem.children(selector.menu),
  5352. $parentMenu = $selectedItem.closest(selector.menu),
  5353. inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
  5354. hasSubMenu = ($subMenu.length> 0),
  5355. hasSelectedItem = ($selectedItem.length > 0),
  5356. selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
  5357. delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
  5358. isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable),
  5359. $nextItem,
  5360. isSubMenuItem,
  5361. newIndex
  5362. ;
  5363. // allow selection with menu closed
  5364. if(isAdditionWithoutMenu) {
  5365. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  5366. module.event.item.click.call($selectedItem, event);
  5367. if(module.is.searchSelection()) {
  5368. module.remove.searchTerm();
  5369. }
  5370. }
  5371. // visible menu keyboard shortcuts
  5372. if( module.is.visible() ) {
  5373. // enter (select or open sub-menu)
  5374. if(pressedKey == keys.enter || delimiterPressed) {
  5375. if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
  5376. module.verbose('Pressed enter on unselectable category, opening sub menu');
  5377. pressedKey = keys.rightArrow;
  5378. }
  5379. else if(selectedIsSelectable) {
  5380. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  5381. module.event.item.click.call($selectedItem, event);
  5382. if(module.is.searchSelection()) {
  5383. module.remove.searchTerm();
  5384. }
  5385. }
  5386. event.preventDefault();
  5387. }
  5388. // sub-menu actions
  5389. if(hasSelectedItem) {
  5390. if(pressedKey == keys.leftArrow) {
  5391. isSubMenuItem = ($parentMenu[0] !== $menu[0]);
  5392. if(isSubMenuItem) {
  5393. module.verbose('Left key pressed, closing sub-menu');
  5394. module.animate.hide(false, $parentMenu);
  5395. $selectedItem
  5396. .removeClass(className.selected)
  5397. ;
  5398. $parentMenu
  5399. .closest(selector.item)
  5400. .addClass(className.selected)
  5401. ;
  5402. event.preventDefault();
  5403. }
  5404. }
  5405. // right arrow (show sub-menu)
  5406. if(pressedKey == keys.rightArrow) {
  5407. if(hasSubMenu) {
  5408. module.verbose('Right key pressed, opening sub-menu');
  5409. module.animate.show(false, $subMenu);
  5410. $selectedItem
  5411. .removeClass(className.selected)
  5412. ;
  5413. $subMenu
  5414. .find(selector.item).eq(0)
  5415. .addClass(className.selected)
  5416. ;
  5417. event.preventDefault();
  5418. }
  5419. }
  5420. }
  5421. // up arrow (traverse menu up)
  5422. if(pressedKey == keys.upArrow) {
  5423. $nextItem = (hasSelectedItem && inVisibleMenu)
  5424. ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  5425. : $item.eq(0)
  5426. ;
  5427. if($visibleItems.index( $nextItem ) < 0) {
  5428. module.verbose('Up key pressed but reached top of current menu');
  5429. event.preventDefault();
  5430. return;
  5431. }
  5432. else {
  5433. module.verbose('Up key pressed, changing active item');
  5434. $selectedItem
  5435. .removeClass(className.selected)
  5436. ;
  5437. $nextItem
  5438. .addClass(className.selected)
  5439. ;
  5440. module.set.scrollPosition($nextItem);
  5441. if(settings.selectOnKeydown && module.is.single()) {
  5442. module.set.selectedItem($nextItem);
  5443. }
  5444. }
  5445. event.preventDefault();
  5446. }
  5447. // down arrow (traverse menu down)
  5448. if(pressedKey == keys.downArrow) {
  5449. $nextItem = (hasSelectedItem && inVisibleMenu)
  5450. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  5451. : $item.eq(0)
  5452. ;
  5453. if($nextItem.length === 0) {
  5454. module.verbose('Down key pressed but reached bottom of current menu');
  5455. event.preventDefault();
  5456. return;
  5457. }
  5458. else {
  5459. module.verbose('Down key pressed, changing active item');
  5460. $item
  5461. .removeClass(className.selected)
  5462. ;
  5463. $nextItem
  5464. .addClass(className.selected)
  5465. ;
  5466. module.set.scrollPosition($nextItem);
  5467. if(settings.selectOnKeydown && module.is.single()) {
  5468. module.set.selectedItem($nextItem);
  5469. }
  5470. }
  5471. event.preventDefault();
  5472. }
  5473. // page down (show next page)
  5474. if(pressedKey == keys.pageUp) {
  5475. module.scrollPage('up');
  5476. event.preventDefault();
  5477. }
  5478. if(pressedKey == keys.pageDown) {
  5479. module.scrollPage('down');
  5480. event.preventDefault();
  5481. }
  5482. // escape (close menu)
  5483. if(pressedKey == keys.escape) {
  5484. module.verbose('Escape key pressed, closing dropdown');
  5485. module.hide();
  5486. }
  5487. }
  5488. else {
  5489. // delimiter key
  5490. if(delimiterPressed) {
  5491. event.preventDefault();
  5492. }
  5493. // down arrow (open menu)
  5494. if(pressedKey == keys.downArrow && !module.is.visible()) {
  5495. module.verbose('Down key pressed, showing dropdown');
  5496. module.show();
  5497. event.preventDefault();
  5498. }
  5499. }
  5500. }
  5501. else {
  5502. if( !module.has.search() ) {
  5503. module.set.selectedLetter( String.fromCharCode(pressedKey) );
  5504. }
  5505. }
  5506. }
  5507. },
  5508. trigger: {
  5509. change: function() {
  5510. var
  5511. events = document.createEvent('HTMLEvents'),
  5512. inputElement = $input[0]
  5513. ;
  5514. if(inputElement) {
  5515. module.verbose('Triggering native change event');
  5516. events.initEvent('change', true, false);
  5517. inputElement.dispatchEvent(events);
  5518. }
  5519. }
  5520. },
  5521. determine: {
  5522. selectAction: function(text, value) {
  5523. module.verbose('Determining action', settings.action);
  5524. if( $.isFunction( module.action[settings.action] ) ) {
  5525. module.verbose('Triggering preset action', settings.action, text, value);
  5526. module.action[ settings.action ].call(element, text, value, this);
  5527. }
  5528. else if( $.isFunction(settings.action) ) {
  5529. module.verbose('Triggering user action', settings.action, text, value);
  5530. settings.action.call(element, text, value, this);
  5531. }
  5532. else {
  5533. module.error(error.action, settings.action);
  5534. }
  5535. },
  5536. eventInModule: function(event, callback) {
  5537. var
  5538. $target = $(event.target),
  5539. inDocument = ($target.closest(document.documentElement).length > 0),
  5540. inModule = ($target.closest($module).length > 0)
  5541. ;
  5542. callback = $.isFunction(callback)
  5543. ? callback
  5544. : function(){}
  5545. ;
  5546. if(inDocument && !inModule) {
  5547. module.verbose('Triggering event', callback);
  5548. callback();
  5549. return true;
  5550. }
  5551. else {
  5552. module.verbose('Event occurred in dropdown, canceling callback');
  5553. return false;
  5554. }
  5555. },
  5556. eventOnElement: function(event, callback) {
  5557. var
  5558. $target = $(event.target),
  5559. $label = $target.closest(selector.siblingLabel),
  5560. inVisibleDOM = document.body.contains(event.target),
  5561. notOnLabel = ($module.find($label).length === 0),
  5562. notInMenu = ($target.closest($menu).length === 0)
  5563. ;
  5564. callback = $.isFunction(callback)
  5565. ? callback
  5566. : function(){}
  5567. ;
  5568. if(inVisibleDOM && notOnLabel && notInMenu) {
  5569. module.verbose('Triggering event', callback);
  5570. callback();
  5571. return true;
  5572. }
  5573. else {
  5574. module.verbose('Event occurred in dropdown menu, canceling callback');
  5575. return false;
  5576. }
  5577. }
  5578. },
  5579. action: {
  5580. nothing: function() {},
  5581. activate: function(text, value, element) {
  5582. value = (value !== undefined)
  5583. ? value
  5584. : text
  5585. ;
  5586. if( module.can.activate( $(element) ) ) {
  5587. module.set.selected(value, $(element));
  5588. if(module.is.multiple() && !module.is.allFiltered()) {
  5589. return;
  5590. }
  5591. else {
  5592. module.hideAndClear();
  5593. }
  5594. }
  5595. },
  5596. select: function(text, value, element) {
  5597. value = (value !== undefined)
  5598. ? value
  5599. : text
  5600. ;
  5601. if( module.can.activate( $(element) ) ) {
  5602. module.set.value(value, $(element));
  5603. if(module.is.multiple() && !module.is.allFiltered()) {
  5604. return;
  5605. }
  5606. else {
  5607. module.hideAndClear();
  5608. }
  5609. }
  5610. },
  5611. combo: function(text, value, element) {
  5612. value = (value !== undefined)
  5613. ? value
  5614. : text
  5615. ;
  5616. module.set.selected(value, $(element));
  5617. module.hideAndClear();
  5618. },
  5619. hide: function(text, value, element) {
  5620. module.set.value(value, text);
  5621. module.hideAndClear();
  5622. }
  5623. },
  5624. get: {
  5625. id: function() {
  5626. return id;
  5627. },
  5628. defaultText: function() {
  5629. return $module.data(metadata.defaultText);
  5630. },
  5631. defaultValue: function() {
  5632. return $module.data(metadata.defaultValue);
  5633. },
  5634. placeholderText: function() {
  5635. if(settings.placeholder != 'auto' && typeof settings.placeholder == 'string') {
  5636. return settings.placeholder;
  5637. }
  5638. return $module.data(metadata.placeholderText) || '';
  5639. },
  5640. text: function() {
  5641. return $text.text();
  5642. },
  5643. query: function() {
  5644. return $.trim($search.val());
  5645. },
  5646. searchWidth: function(value) {
  5647. value = (value !== undefined)
  5648. ? value
  5649. : $search.val()
  5650. ;
  5651. $sizer.text(value);
  5652. // prevent rounding issues
  5653. return Math.ceil( $sizer.width() + 1);
  5654. },
  5655. selectionCount: function() {
  5656. var
  5657. values = module.get.values(),
  5658. count
  5659. ;
  5660. count = ( module.is.multiple() )
  5661. ? $.isArray(values)
  5662. ? values.length
  5663. : 0
  5664. : (module.get.value() !== '')
  5665. ? 1
  5666. : 0
  5667. ;
  5668. return count;
  5669. },
  5670. transition: function($subMenu) {
  5671. return (settings.transition == 'auto')
  5672. ? module.is.upward($subMenu)
  5673. ? 'slide up'
  5674. : 'slide down'
  5675. : settings.transition
  5676. ;
  5677. },
  5678. userValues: function() {
  5679. var
  5680. values = module.get.values()
  5681. ;
  5682. if(!values) {
  5683. return false;
  5684. }
  5685. values = $.isArray(values)
  5686. ? values
  5687. : [values]
  5688. ;
  5689. return $.grep(values, function(value) {
  5690. return (module.get.item(value) === false);
  5691. });
  5692. },
  5693. uniqueArray: function(array) {
  5694. return $.grep(array, function (value, index) {
  5695. return $.inArray(value, array) === index;
  5696. });
  5697. },
  5698. caretPosition: function() {
  5699. var
  5700. input = $search.get(0),
  5701. range,
  5702. rangeLength
  5703. ;
  5704. if('selectionStart' in input) {
  5705. return input.selectionStart;
  5706. }
  5707. else if (document.selection) {
  5708. input.focus();
  5709. range = document.selection.createRange();
  5710. rangeLength = range.text.length;
  5711. range.moveStart('character', -input.value.length);
  5712. return range.text.length - rangeLength;
  5713. }
  5714. },
  5715. value: function() {
  5716. var
  5717. value = ($input.length > 0)
  5718. ? $input.val()
  5719. : $module.data(metadata.value),
  5720. isEmptyMultiselect = ($.isArray(value) && value.length === 1 && value[0] === '')
  5721. ;
  5722. // prevents placeholder element from being selected when multiple
  5723. return (value === undefined || isEmptyMultiselect)
  5724. ? ''
  5725. : value
  5726. ;
  5727. },
  5728. values: function() {
  5729. var
  5730. value = module.get.value()
  5731. ;
  5732. if(value === '') {
  5733. return '';
  5734. }
  5735. return ( !module.has.selectInput() && module.is.multiple() )
  5736. ? (typeof value == 'string') // delimited string
  5737. ? value.split(settings.delimiter)
  5738. : ''
  5739. : value
  5740. ;
  5741. },
  5742. remoteValues: function() {
  5743. var
  5744. values = module.get.values(),
  5745. remoteValues = false
  5746. ;
  5747. if(values) {
  5748. if(typeof values == 'string') {
  5749. values = [values];
  5750. }
  5751. $.each(values, function(index, value) {
  5752. var
  5753. name = module.read.remoteData(value)
  5754. ;
  5755. module.verbose('Restoring value from session data', name, value);
  5756. if(name) {
  5757. if(!remoteValues) {
  5758. remoteValues = {};
  5759. }
  5760. remoteValues[value] = name;
  5761. }
  5762. });
  5763. }
  5764. return remoteValues;
  5765. },
  5766. choiceText: function($choice, preserveHTML) {
  5767. preserveHTML = (preserveHTML !== undefined)
  5768. ? preserveHTML
  5769. : settings.preserveHTML
  5770. ;
  5771. if($choice) {
  5772. if($choice.find(selector.menu).length > 0) {
  5773. module.verbose('Retrieving text of element with sub-menu');
  5774. $choice = $choice.clone();
  5775. $choice.find(selector.menu).remove();
  5776. $choice.find(selector.menuIcon).remove();
  5777. }
  5778. return ($choice.data(metadata.text) !== undefined)
  5779. ? $choice.data(metadata.text)
  5780. : (preserveHTML)
  5781. ? $.trim($choice.html())
  5782. : $.trim($choice.text())
  5783. ;
  5784. }
  5785. },
  5786. choiceValue: function($choice, choiceText) {
  5787. choiceText = choiceText || module.get.choiceText($choice);
  5788. if(!$choice) {
  5789. return false;
  5790. }
  5791. return ($choice.data(metadata.value) !== undefined)
  5792. ? String( $choice.data(metadata.value) )
  5793. : (typeof choiceText === 'string')
  5794. ? $.trim(choiceText.toLowerCase())
  5795. : String(choiceText)
  5796. ;
  5797. },
  5798. inputEvent: function() {
  5799. var
  5800. input = $search[0]
  5801. ;
  5802. if(input) {
  5803. return (input.oninput !== undefined)
  5804. ? 'input'
  5805. : (input.onpropertychange !== undefined)
  5806. ? 'propertychange'
  5807. : 'keyup'
  5808. ;
  5809. }
  5810. return false;
  5811. },
  5812. selectValues: function() {
  5813. var
  5814. select = {}
  5815. ;
  5816. select.values = [];
  5817. $module
  5818. .find('option')
  5819. .each(function() {
  5820. var
  5821. $option = $(this),
  5822. name = $option.html(),
  5823. disabled = $option.attr('disabled'),
  5824. value = ( $option.attr('value') !== undefined )
  5825. ? $option.attr('value')
  5826. : name
  5827. ;
  5828. if(settings.placeholder === 'auto' && value === '') {
  5829. select.placeholder = name;
  5830. }
  5831. else {
  5832. select.values.push({
  5833. name : name,
  5834. value : value,
  5835. disabled : disabled
  5836. });
  5837. }
  5838. })
  5839. ;
  5840. if(settings.placeholder && settings.placeholder !== 'auto') {
  5841. module.debug('Setting placeholder value to', settings.placeholder);
  5842. select.placeholder = settings.placeholder;
  5843. }
  5844. if(settings.sortSelect) {
  5845. select.values.sort(function(a, b) {
  5846. return (a.name > b.name)
  5847. ? 1
  5848. : -1
  5849. ;
  5850. });
  5851. module.debug('Retrieved and sorted values from select', select);
  5852. }
  5853. else {
  5854. module.debug('Retrieved values from select', select);
  5855. }
  5856. return select;
  5857. },
  5858. activeItem: function() {
  5859. return $item.filter('.' + className.active);
  5860. },
  5861. selectedItem: function() {
  5862. var
  5863. $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
  5864. ;
  5865. return ($selectedItem.length > 0)
  5866. ? $selectedItem
  5867. : $item.eq(0)
  5868. ;
  5869. },
  5870. itemWithAdditions: function(value) {
  5871. var
  5872. $items = module.get.item(value),
  5873. $userItems = module.create.userChoice(value),
  5874. hasUserItems = ($userItems && $userItems.length > 0)
  5875. ;
  5876. if(hasUserItems) {
  5877. $items = ($items.length > 0)
  5878. ? $items.add($userItems)
  5879. : $userItems
  5880. ;
  5881. }
  5882. return $items;
  5883. },
  5884. item: function(value, strict) {
  5885. var
  5886. $selectedItem = false,
  5887. shouldSearch,
  5888. isMultiple
  5889. ;
  5890. value = (value !== undefined)
  5891. ? value
  5892. : ( module.get.values() !== undefined)
  5893. ? module.get.values()
  5894. : module.get.text()
  5895. ;
  5896. shouldSearch = (isMultiple)
  5897. ? (value.length > 0)
  5898. : (value !== undefined && value !== null)
  5899. ;
  5900. isMultiple = (module.is.multiple() && $.isArray(value));
  5901. strict = (value === '' || value === 0)
  5902. ? true
  5903. : strict || false
  5904. ;
  5905. if(shouldSearch) {
  5906. $item
  5907. .each(function() {
  5908. var
  5909. $choice = $(this),
  5910. optionText = module.get.choiceText($choice),
  5911. optionValue = module.get.choiceValue($choice, optionText)
  5912. ;
  5913. // safe early exit
  5914. if(optionValue === null || optionValue === undefined) {
  5915. return;
  5916. }
  5917. if(isMultiple) {
  5918. if($.inArray( String(optionValue), value) !== -1 || $.inArray(optionText, value) !== -1) {
  5919. $selectedItem = ($selectedItem)
  5920. ? $selectedItem.add($choice)
  5921. : $choice
  5922. ;
  5923. }
  5924. }
  5925. else if(strict) {
  5926. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  5927. if( optionValue === value || optionText === value) {
  5928. $selectedItem = $choice;
  5929. return true;
  5930. }
  5931. }
  5932. else {
  5933. if( String(optionValue) == String(value) || optionText == value) {
  5934. module.verbose('Found select item by value', optionValue, value);
  5935. $selectedItem = $choice;
  5936. return true;
  5937. }
  5938. }
  5939. })
  5940. ;
  5941. }
  5942. return $selectedItem;
  5943. }
  5944. },
  5945. check: {
  5946. maxSelections: function(selectionCount) {
  5947. if(settings.maxSelections) {
  5948. selectionCount = (selectionCount !== undefined)
  5949. ? selectionCount
  5950. : module.get.selectionCount()
  5951. ;
  5952. if(selectionCount >= settings.maxSelections) {
  5953. module.debug('Maximum selection count reached');
  5954. if(settings.useLabels) {
  5955. $item.addClass(className.filtered);
  5956. module.add.message(message.maxSelections);
  5957. }
  5958. return true;
  5959. }
  5960. else {
  5961. module.verbose('No longer at maximum selection count');
  5962. module.remove.message();
  5963. module.remove.filteredItem();
  5964. if(module.is.searchSelection()) {
  5965. module.filterItems();
  5966. }
  5967. return false;
  5968. }
  5969. }
  5970. return true;
  5971. }
  5972. },
  5973. restore: {
  5974. defaults: function() {
  5975. module.clear();
  5976. module.restore.defaultText();
  5977. module.restore.defaultValue();
  5978. },
  5979. defaultText: function() {
  5980. var
  5981. defaultText = module.get.defaultText(),
  5982. placeholderText = module.get.placeholderText
  5983. ;
  5984. if(defaultText === placeholderText) {
  5985. module.debug('Restoring default placeholder text', defaultText);
  5986. module.set.placeholderText(defaultText);
  5987. }
  5988. else {
  5989. module.debug('Restoring default text', defaultText);
  5990. module.set.text(defaultText);
  5991. }
  5992. },
  5993. placeholderText: function() {
  5994. module.set.placeholderText();
  5995. },
  5996. defaultValue: function() {
  5997. var
  5998. defaultValue = module.get.defaultValue()
  5999. ;
  6000. if(defaultValue !== undefined) {
  6001. module.debug('Restoring default value', defaultValue);
  6002. if(defaultValue !== '') {
  6003. module.set.value(defaultValue);
  6004. module.set.selected();
  6005. }
  6006. else {
  6007. module.remove.activeItem();
  6008. module.remove.selectedItem();
  6009. }
  6010. }
  6011. },
  6012. labels: function() {
  6013. if(settings.allowAdditions) {
  6014. if(!settings.useLabels) {
  6015. module.error(error.labels);
  6016. settings.useLabels = true;
  6017. }
  6018. module.debug('Restoring selected values');
  6019. module.create.userLabels();
  6020. }
  6021. module.check.maxSelections();
  6022. },
  6023. selected: function() {
  6024. module.restore.values();
  6025. if(module.is.multiple()) {
  6026. module.debug('Restoring previously selected values and labels');
  6027. module.restore.labels();
  6028. }
  6029. else {
  6030. module.debug('Restoring previously selected values');
  6031. }
  6032. },
  6033. values: function() {
  6034. // prevents callbacks from occurring on initial load
  6035. module.set.initialLoad();
  6036. if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) {
  6037. module.restore.remoteValues();
  6038. }
  6039. else {
  6040. module.set.selected();
  6041. }
  6042. module.remove.initialLoad();
  6043. },
  6044. remoteValues: function() {
  6045. var
  6046. values = module.get.remoteValues()
  6047. ;
  6048. module.debug('Recreating selected from session data', values);
  6049. if(values) {
  6050. if( module.is.single() ) {
  6051. $.each(values, function(value, name) {
  6052. module.set.text(name);
  6053. });
  6054. }
  6055. else {
  6056. $.each(values, function(value, name) {
  6057. module.add.label(value, name);
  6058. });
  6059. }
  6060. }
  6061. }
  6062. },
  6063. read: {
  6064. remoteData: function(value) {
  6065. var
  6066. name
  6067. ;
  6068. if(window.Storage === undefined) {
  6069. module.error(error.noStorage);
  6070. return;
  6071. }
  6072. name = sessionStorage.getItem(value);
  6073. return (name !== undefined)
  6074. ? name
  6075. : false
  6076. ;
  6077. }
  6078. },
  6079. save: {
  6080. defaults: function() {
  6081. module.save.defaultText();
  6082. module.save.placeholderText();
  6083. module.save.defaultValue();
  6084. },
  6085. defaultValue: function() {
  6086. var
  6087. value = module.get.value()
  6088. ;
  6089. module.verbose('Saving default value as', value);
  6090. $module.data(metadata.defaultValue, value);
  6091. },
  6092. defaultText: function() {
  6093. var
  6094. text = module.get.text()
  6095. ;
  6096. module.verbose('Saving default text as', text);
  6097. $module.data(metadata.defaultText, text);
  6098. },
  6099. placeholderText: function() {
  6100. var
  6101. text
  6102. ;
  6103. if(settings.placeholder !== false && $text.hasClass(className.placeholder)) {
  6104. text = module.get.text();
  6105. module.verbose('Saving placeholder text as', text);
  6106. $module.data(metadata.placeholderText, text);
  6107. }
  6108. },
  6109. remoteData: function(name, value) {
  6110. if(window.Storage === undefined) {
  6111. module.error(error.noStorage);
  6112. return;
  6113. }
  6114. module.verbose('Saving remote data to session storage', value, name);
  6115. sessionStorage.setItem(value, name);
  6116. }
  6117. },
  6118. clear: function() {
  6119. if(module.is.multiple() && settings.useLabels) {
  6120. module.remove.labels();
  6121. }
  6122. else {
  6123. module.remove.activeItem();
  6124. module.remove.selectedItem();
  6125. }
  6126. module.set.placeholderText();
  6127. module.clearValue();
  6128. },
  6129. clearValue: function() {
  6130. module.set.value('');
  6131. },
  6132. scrollPage: function(direction, $selectedItem) {
  6133. var
  6134. $currentItem = $selectedItem || module.get.selectedItem(),
  6135. $menu = $currentItem.closest(selector.menu),
  6136. menuHeight = $menu.outerHeight(),
  6137. currentScroll = $menu.scrollTop(),
  6138. itemHeight = $item.eq(0).outerHeight(),
  6139. itemsPerPage = Math.floor(menuHeight / itemHeight),
  6140. maxScroll = $menu.prop('scrollHeight'),
  6141. newScroll = (direction == 'up')
  6142. ? currentScroll - (itemHeight * itemsPerPage)
  6143. : currentScroll + (itemHeight * itemsPerPage),
  6144. $selectableItem = $item.not(selector.unselectable),
  6145. isWithinRange,
  6146. $nextSelectedItem,
  6147. elementIndex
  6148. ;
  6149. elementIndex = (direction == 'up')
  6150. ? $selectableItem.index($currentItem) - itemsPerPage
  6151. : $selectableItem.index($currentItem) + itemsPerPage
  6152. ;
  6153. isWithinRange = (direction == 'up')
  6154. ? (elementIndex >= 0)
  6155. : (elementIndex < $selectableItem.length)
  6156. ;
  6157. $nextSelectedItem = (isWithinRange)
  6158. ? $selectableItem.eq(elementIndex)
  6159. : (direction == 'up')
  6160. ? $selectableItem.first()
  6161. : $selectableItem.last()
  6162. ;
  6163. if($nextSelectedItem.length > 0) {
  6164. module.debug('Scrolling page', direction, $nextSelectedItem);
  6165. $currentItem
  6166. .removeClass(className.selected)
  6167. ;
  6168. $nextSelectedItem
  6169. .addClass(className.selected)
  6170. ;
  6171. if(settings.selectOnKeydown && module.is.single()) {
  6172. module.set.selectedItem($nextSelectedItem);
  6173. }
  6174. $menu
  6175. .scrollTop(newScroll)
  6176. ;
  6177. }
  6178. },
  6179. set: {
  6180. filtered: function() {
  6181. var
  6182. isMultiple = module.is.multiple(),
  6183. isSearch = module.is.searchSelection(),
  6184. isSearchMultiple = (isMultiple && isSearch),
  6185. searchValue = (isSearch)
  6186. ? module.get.query()
  6187. : '',
  6188. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
  6189. searchWidth = module.get.searchWidth(),
  6190. valueIsSet = searchValue !== ''
  6191. ;
  6192. if(isMultiple && hasSearchValue) {
  6193. module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
  6194. $search.css('width', searchWidth);
  6195. }
  6196. if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
  6197. module.verbose('Hiding placeholder text');
  6198. $text.addClass(className.filtered);
  6199. }
  6200. else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
  6201. module.verbose('Showing placeholder text');
  6202. $text.removeClass(className.filtered);
  6203. }
  6204. },
  6205. empty: function() {
  6206. $module.addClass(className.empty);
  6207. },
  6208. loading: function() {
  6209. $module.addClass(className.loading);
  6210. },
  6211. placeholderText: function(text) {
  6212. text = text || module.get.placeholderText();
  6213. module.debug('Setting placeholder text', text);
  6214. module.set.text(text);
  6215. $text.addClass(className.placeholder);
  6216. },
  6217. tabbable: function() {
  6218. if( module.is.searchSelection() ) {
  6219. module.debug('Added tabindex to searchable dropdown');
  6220. $search
  6221. .val('')
  6222. .attr('tabindex', 0)
  6223. ;
  6224. $menu
  6225. .attr('tabindex', -1)
  6226. ;
  6227. }
  6228. else {
  6229. module.debug('Added tabindex to dropdown');
  6230. if( $module.attr('tabindex') === undefined) {
  6231. $module
  6232. .attr('tabindex', 0)
  6233. ;
  6234. $menu
  6235. .attr('tabindex', -1)
  6236. ;
  6237. }
  6238. }
  6239. },
  6240. initialLoad: function() {
  6241. module.verbose('Setting initial load');
  6242. initialLoad = true;
  6243. },
  6244. activeItem: function($item) {
  6245. if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) {
  6246. $item.addClass(className.filtered);
  6247. }
  6248. else {
  6249. $item.addClass(className.active);
  6250. }
  6251. },
  6252. partialSearch: function(text) {
  6253. var
  6254. length = module.get.query().length
  6255. ;
  6256. $search.val( text.substr(0 , length));
  6257. },
  6258. scrollPosition: function($item, forceScroll) {
  6259. var
  6260. edgeTolerance = 5,
  6261. $menu,
  6262. hasActive,
  6263. offset,
  6264. itemHeight,
  6265. itemOffset,
  6266. menuOffset,
  6267. menuScroll,
  6268. menuHeight,
  6269. abovePage,
  6270. belowPage
  6271. ;
  6272. $item = $item || module.get.selectedItem();
  6273. $menu = $item.closest(selector.menu);
  6274. hasActive = ($item && $item.length > 0);
  6275. forceScroll = (forceScroll !== undefined)
  6276. ? forceScroll
  6277. : false
  6278. ;
  6279. if($item && $menu.length > 0 && hasActive) {
  6280. itemOffset = $item.position().top;
  6281. $menu.addClass(className.loading);
  6282. menuScroll = $menu.scrollTop();
  6283. menuOffset = $menu.offset().top;
  6284. itemOffset = $item.offset().top;
  6285. offset = menuScroll - menuOffset + itemOffset;
  6286. if(!forceScroll) {
  6287. menuHeight = $menu.height();
  6288. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  6289. abovePage = ((offset - edgeTolerance) < menuScroll);
  6290. }
  6291. module.debug('Scrolling to active item', offset);
  6292. if(forceScroll || abovePage || belowPage) {
  6293. $menu.scrollTop(offset);
  6294. }
  6295. $menu.removeClass(className.loading);
  6296. }
  6297. },
  6298. text: function(text) {
  6299. if(settings.action !== 'select') {
  6300. if(settings.action == 'combo') {
  6301. module.debug('Changing combo button text', text, $combo);
  6302. if(settings.preserveHTML) {
  6303. $combo.html(text);
  6304. }
  6305. else {
  6306. $combo.text(text);
  6307. }
  6308. }
  6309. else {
  6310. if(text !== module.get.placeholderText()) {
  6311. $text.removeClass(className.placeholder);
  6312. }
  6313. module.debug('Changing text', text, $text);
  6314. $text
  6315. .removeClass(className.filtered)
  6316. ;
  6317. if(settings.preserveHTML) {
  6318. $text.html(text);
  6319. }
  6320. else {
  6321. $text.text(text);
  6322. }
  6323. }
  6324. }
  6325. },
  6326. selectedItem: function($item) {
  6327. var
  6328. value = module.get.choiceValue($item),
  6329. searchText = module.get.choiceText($item, false),
  6330. text = module.get.choiceText($item, true)
  6331. ;
  6332. module.debug('Setting user selection to item', $item);
  6333. module.remove.activeItem();
  6334. module.set.partialSearch(searchText);
  6335. module.set.activeItem($item);
  6336. module.set.selected(value, $item);
  6337. module.set.text(text);
  6338. },
  6339. selectedLetter: function(letter) {
  6340. var
  6341. $selectedItem = $item.filter('.' + className.selected),
  6342. alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter),
  6343. $nextValue = false,
  6344. $nextItem
  6345. ;
  6346. // check next of same letter
  6347. if(alreadySelectedLetter) {
  6348. $nextItem = $selectedItem.nextAll($item).eq(0);
  6349. if( module.has.firstLetter($nextItem, letter) ) {
  6350. $nextValue = $nextItem;
  6351. }
  6352. }
  6353. // check all values
  6354. if(!$nextValue) {
  6355. $item
  6356. .each(function(){
  6357. if(module.has.firstLetter($(this), letter)) {
  6358. $nextValue = $(this);
  6359. return false;
  6360. }
  6361. })
  6362. ;
  6363. }
  6364. // set next value
  6365. if($nextValue) {
  6366. module.verbose('Scrolling to next value with letter', letter);
  6367. module.set.scrollPosition($nextValue);
  6368. $selectedItem.removeClass(className.selected);
  6369. $nextValue.addClass(className.selected);
  6370. if(settings.selectOnKeydown && module.is.single()) {
  6371. module.set.selectedItem($nextValue);
  6372. }
  6373. }
  6374. },
  6375. direction: function($menu) {
  6376. if(settings.direction == 'auto') {
  6377. // reset position
  6378. module.remove.upward();
  6379. if(module.can.openDownward($menu)) {
  6380. module.remove.upward($menu);
  6381. }
  6382. else {
  6383. module.set.upward($menu);
  6384. }
  6385. if(!module.is.leftward($menu) && !module.can.openRightward($menu)) {
  6386. module.set.leftward($menu);
  6387. }
  6388. }
  6389. else if(settings.direction == 'upward') {
  6390. module.set.upward($menu);
  6391. }
  6392. },
  6393. upward: function($currentMenu) {
  6394. var $element = $currentMenu || $module;
  6395. $element.addClass(className.upward);
  6396. },
  6397. leftward: function($currentMenu) {
  6398. var $element = $currentMenu || $menu;
  6399. $element.addClass(className.leftward);
  6400. },
  6401. value: function(value, text, $selected) {
  6402. var
  6403. escapedValue = module.escape.value(value),
  6404. hasInput = ($input.length > 0),
  6405. currentValue = module.get.values(),
  6406. stringValue = (value !== undefined)
  6407. ? String(value)
  6408. : value,
  6409. newValue
  6410. ;
  6411. if(hasInput) {
  6412. if(!settings.allowReselection && stringValue == currentValue) {
  6413. module.verbose('Skipping value update already same value', value, currentValue);
  6414. if(!module.is.initialLoad()) {
  6415. return;
  6416. }
  6417. }
  6418. if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) {
  6419. module.debug('Adding user option', value);
  6420. module.add.optionValue(value);
  6421. }
  6422. module.debug('Updating input value', escapedValue, currentValue);
  6423. internalChange = true;
  6424. $input
  6425. .val(escapedValue)
  6426. ;
  6427. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6428. module.debug('Input native change event ignored on initial load');
  6429. }
  6430. else {
  6431. module.trigger.change();
  6432. }
  6433. internalChange = false;
  6434. }
  6435. else {
  6436. module.verbose('Storing value in metadata', escapedValue, $input);
  6437. if(escapedValue !== currentValue) {
  6438. $module.data(metadata.value, stringValue);
  6439. }
  6440. }
  6441. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6442. module.verbose('No callback on initial load', settings.onChange);
  6443. }
  6444. else {
  6445. settings.onChange.call(element, value, text, $selected);
  6446. }
  6447. },
  6448. active: function() {
  6449. $module
  6450. .addClass(className.active)
  6451. ;
  6452. },
  6453. multiple: function() {
  6454. $module.addClass(className.multiple);
  6455. },
  6456. visible: function() {
  6457. $module.addClass(className.visible);
  6458. },
  6459. exactly: function(value, $selectedItem) {
  6460. module.debug('Setting selected to exact values');
  6461. module.clear();
  6462. module.set.selected(value, $selectedItem);
  6463. },
  6464. selected: function(value, $selectedItem) {
  6465. var
  6466. isMultiple = module.is.multiple(),
  6467. $userSelectedItem
  6468. ;
  6469. $selectedItem = (settings.allowAdditions)
  6470. ? $selectedItem || module.get.itemWithAdditions(value)
  6471. : $selectedItem || module.get.item(value)
  6472. ;
  6473. if(!$selectedItem) {
  6474. return;
  6475. }
  6476. module.debug('Setting selected menu item to', $selectedItem);
  6477. if(module.is.multiple()) {
  6478. module.remove.searchWidth();
  6479. }
  6480. if(module.is.single()) {
  6481. module.remove.activeItem();
  6482. module.remove.selectedItem();
  6483. }
  6484. else if(settings.useLabels) {
  6485. module.remove.selectedItem();
  6486. }
  6487. // select each item
  6488. $selectedItem
  6489. .each(function() {
  6490. var
  6491. $selected = $(this),
  6492. selectedText = module.get.choiceText($selected),
  6493. selectedValue = module.get.choiceValue($selected, selectedText),
  6494. isFiltered = $selected.hasClass(className.filtered),
  6495. isActive = $selected.hasClass(className.active),
  6496. isUserValue = $selected.hasClass(className.addition),
  6497. shouldAnimate = (isMultiple && $selectedItem.length == 1)
  6498. ;
  6499. if(isMultiple) {
  6500. if(!isActive || isUserValue) {
  6501. if(settings.apiSettings && settings.saveRemoteData) {
  6502. module.save.remoteData(selectedText, selectedValue);
  6503. }
  6504. if(settings.useLabels) {
  6505. module.add.label(selectedValue, selectedText, shouldAnimate);
  6506. module.add.value(selectedValue, selectedText, $selected);
  6507. module.set.activeItem($selected);
  6508. module.filterActive();
  6509. module.select.nextAvailable($selectedItem);
  6510. }
  6511. else {
  6512. module.add.value(selectedValue, selectedText, $selected);
  6513. module.set.text(module.add.variables(message.count));
  6514. module.set.activeItem($selected);
  6515. }
  6516. }
  6517. else if(!isFiltered) {
  6518. module.debug('Selected active value, removing label');
  6519. module.remove.selected(selectedValue);
  6520. }
  6521. }
  6522. else {
  6523. if(settings.apiSettings && settings.saveRemoteData) {
  6524. module.save.remoteData(selectedText, selectedValue);
  6525. }
  6526. module.set.text(selectedText);
  6527. module.set.value(selectedValue, selectedText, $selected);
  6528. $selected
  6529. .addClass(className.active)
  6530. .addClass(className.selected)
  6531. ;
  6532. }
  6533. })
  6534. ;
  6535. }
  6536. },
  6537. add: {
  6538. label: function(value, text, shouldAnimate) {
  6539. var
  6540. $next = module.is.searchSelection()
  6541. ? $search
  6542. : $text,
  6543. escapedValue = module.escape.value(value),
  6544. $label
  6545. ;
  6546. $label = $('<a />')
  6547. .addClass(className.label)
  6548. .attr('data-' + metadata.value, escapedValue)
  6549. .html(templates.label(escapedValue, text))
  6550. ;
  6551. $label = settings.onLabelCreate.call($label, escapedValue, text);
  6552. if(module.has.value(value)) {
  6553. module.debug('User selection already exists, skipping', escapedValue);
  6554. return;
  6555. }
  6556. if(settings.label.variation) {
  6557. $label.addClass(settings.label.variation);
  6558. }
  6559. if(shouldAnimate === true) {
  6560. module.debug('Animating in label', $label);
  6561. $label
  6562. .addClass(className.hidden)
  6563. .insertBefore($next)
  6564. .transition(settings.label.transition, settings.label.duration)
  6565. ;
  6566. }
  6567. else {
  6568. module.debug('Adding selection label', $label);
  6569. $label
  6570. .insertBefore($next)
  6571. ;
  6572. }
  6573. },
  6574. message: function(message) {
  6575. var
  6576. $message = $menu.children(selector.message),
  6577. html = settings.templates.message(module.add.variables(message))
  6578. ;
  6579. if($message.length > 0) {
  6580. $message
  6581. .html(html)
  6582. ;
  6583. }
  6584. else {
  6585. $message = $('<div/>')
  6586. .html(html)
  6587. .addClass(className.message)
  6588. .appendTo($menu)
  6589. ;
  6590. }
  6591. },
  6592. optionValue: function(value) {
  6593. var
  6594. escapedValue = module.escape.value(value),
  6595. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  6596. hasOption = ($option.length > 0)
  6597. ;
  6598. if(hasOption) {
  6599. return;
  6600. }
  6601. // temporarily disconnect observer
  6602. module.disconnect.selectObserver();
  6603. if( module.is.single() ) {
  6604. module.verbose('Removing previous user addition');
  6605. $input.find('option.' + className.addition).remove();
  6606. }
  6607. $('<option/>')
  6608. .prop('value', escapedValue)
  6609. .addClass(className.addition)
  6610. .html(value)
  6611. .appendTo($input)
  6612. ;
  6613. module.verbose('Adding user addition as an <option>', value);
  6614. module.observe.select();
  6615. },
  6616. userSuggestion: function(value) {
  6617. var
  6618. $addition = $menu.children(selector.addition),
  6619. $existingItem = module.get.item(value),
  6620. alreadyHasValue = $existingItem && $existingItem.not(selector.addition).length,
  6621. hasUserSuggestion = $addition.length > 0,
  6622. html
  6623. ;
  6624. if(settings.useLabels && module.has.maxSelections()) {
  6625. return;
  6626. }
  6627. if(value === '' || alreadyHasValue) {
  6628. $addition.remove();
  6629. return;
  6630. }
  6631. if(hasUserSuggestion) {
  6632. $addition
  6633. .data(metadata.value, value)
  6634. .data(metadata.text, value)
  6635. .attr('data-' + metadata.value, value)
  6636. .attr('data-' + metadata.text, value)
  6637. .removeClass(className.filtered)
  6638. ;
  6639. if(!settings.hideAdditions) {
  6640. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  6641. $addition
  6642. .html(html)
  6643. ;
  6644. }
  6645. module.verbose('Replacing user suggestion with new value', $addition);
  6646. }
  6647. else {
  6648. $addition = module.create.userChoice(value);
  6649. $addition
  6650. .prependTo($menu)
  6651. ;
  6652. module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
  6653. }
  6654. if(!settings.hideAdditions || module.is.allFiltered()) {
  6655. $addition
  6656. .addClass(className.selected)
  6657. .siblings()
  6658. .removeClass(className.selected)
  6659. ;
  6660. }
  6661. module.refreshItems();
  6662. },
  6663. variables: function(message, term) {
  6664. var
  6665. hasCount = (message.search('{count}') !== -1),
  6666. hasMaxCount = (message.search('{maxCount}') !== -1),
  6667. hasTerm = (message.search('{term}') !== -1),
  6668. values,
  6669. count,
  6670. query
  6671. ;
  6672. module.verbose('Adding templated variables to message', message);
  6673. if(hasCount) {
  6674. count = module.get.selectionCount();
  6675. message = message.replace('{count}', count);
  6676. }
  6677. if(hasMaxCount) {
  6678. count = module.get.selectionCount();
  6679. message = message.replace('{maxCount}', settings.maxSelections);
  6680. }
  6681. if(hasTerm) {
  6682. query = term || module.get.query();
  6683. message = message.replace('{term}', query);
  6684. }
  6685. return message;
  6686. },
  6687. value: function(addedValue, addedText, $selectedItem) {
  6688. var
  6689. currentValue = module.get.values(),
  6690. newValue
  6691. ;
  6692. if(module.has.value(addedValue)) {
  6693. module.debug('Value already selected');
  6694. return;
  6695. }
  6696. if(addedValue === '') {
  6697. module.debug('Cannot select blank values from multiselect');
  6698. return;
  6699. }
  6700. // extend current array
  6701. if($.isArray(currentValue)) {
  6702. newValue = currentValue.concat([addedValue]);
  6703. newValue = module.get.uniqueArray(newValue);
  6704. }
  6705. else {
  6706. newValue = [addedValue];
  6707. }
  6708. // add values
  6709. if( module.has.selectInput() ) {
  6710. if(module.can.extendSelect()) {
  6711. module.debug('Adding value to select', addedValue, newValue, $input);
  6712. module.add.optionValue(addedValue);
  6713. }
  6714. }
  6715. else {
  6716. newValue = newValue.join(settings.delimiter);
  6717. module.debug('Setting hidden input to delimited value', newValue, $input);
  6718. }
  6719. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6720. module.verbose('Skipping onadd callback on initial load', settings.onAdd);
  6721. }
  6722. else {
  6723. settings.onAdd.call(element, addedValue, addedText, $selectedItem);
  6724. }
  6725. module.set.value(newValue, addedValue, addedText, $selectedItem);
  6726. module.check.maxSelections();
  6727. }
  6728. },
  6729. remove: {
  6730. active: function() {
  6731. $module.removeClass(className.active);
  6732. },
  6733. activeLabel: function() {
  6734. $module.find(selector.label).removeClass(className.active);
  6735. },
  6736. empty: function() {
  6737. $module.removeClass(className.empty);
  6738. },
  6739. loading: function() {
  6740. $module.removeClass(className.loading);
  6741. },
  6742. initialLoad: function() {
  6743. initialLoad = false;
  6744. },
  6745. upward: function($currentMenu) {
  6746. var $element = $currentMenu || $module;
  6747. $element.removeClass(className.upward);
  6748. },
  6749. leftward: function($currentMenu) {
  6750. var $element = $currentMenu || $menu;
  6751. $element.removeClass(className.leftward);
  6752. },
  6753. visible: function() {
  6754. $module.removeClass(className.visible);
  6755. },
  6756. activeItem: function() {
  6757. $item.removeClass(className.active);
  6758. },
  6759. filteredItem: function() {
  6760. if(settings.useLabels && module.has.maxSelections() ) {
  6761. return;
  6762. }
  6763. if(settings.useLabels && module.is.multiple()) {
  6764. $item.not('.' + className.active).removeClass(className.filtered);
  6765. }
  6766. else {
  6767. $item.removeClass(className.filtered);
  6768. }
  6769. module.remove.empty();
  6770. },
  6771. optionValue: function(value) {
  6772. var
  6773. escapedValue = module.escape.value(value),
  6774. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  6775. hasOption = ($option.length > 0)
  6776. ;
  6777. if(!hasOption || !$option.hasClass(className.addition)) {
  6778. return;
  6779. }
  6780. // temporarily disconnect observer
  6781. if(selectObserver) {
  6782. selectObserver.disconnect();
  6783. module.verbose('Temporarily disconnecting mutation observer');
  6784. }
  6785. $option.remove();
  6786. module.verbose('Removing user addition as an <option>', escapedValue);
  6787. if(selectObserver) {
  6788. selectObserver.observe($input[0], {
  6789. childList : true,
  6790. subtree : true
  6791. });
  6792. }
  6793. },
  6794. message: function() {
  6795. $menu.children(selector.message).remove();
  6796. },
  6797. searchWidth: function() {
  6798. $search.css('width', '');
  6799. },
  6800. searchTerm: function() {
  6801. module.verbose('Cleared search term');
  6802. $search.val('');
  6803. module.set.filtered();
  6804. },
  6805. userAddition: function() {
  6806. $item.filter(selector.addition).remove();
  6807. },
  6808. selected: function(value, $selectedItem) {
  6809. $selectedItem = (settings.allowAdditions)
  6810. ? $selectedItem || module.get.itemWithAdditions(value)
  6811. : $selectedItem || module.get.item(value)
  6812. ;
  6813. if(!$selectedItem) {
  6814. return false;
  6815. }
  6816. $selectedItem
  6817. .each(function() {
  6818. var
  6819. $selected = $(this),
  6820. selectedText = module.get.choiceText($selected),
  6821. selectedValue = module.get.choiceValue($selected, selectedText)
  6822. ;
  6823. if(module.is.multiple()) {
  6824. if(settings.useLabels) {
  6825. module.remove.value(selectedValue, selectedText, $selected);
  6826. module.remove.label(selectedValue);
  6827. }
  6828. else {
  6829. module.remove.value(selectedValue, selectedText, $selected);
  6830. if(module.get.selectionCount() === 0) {
  6831. module.set.placeholderText();
  6832. }
  6833. else {
  6834. module.set.text(module.add.variables(message.count));
  6835. }
  6836. }
  6837. }
  6838. else {
  6839. module.remove.value(selectedValue, selectedText, $selected);
  6840. }
  6841. $selected
  6842. .removeClass(className.filtered)
  6843. .removeClass(className.active)
  6844. ;
  6845. if(settings.useLabels) {
  6846. $selected.removeClass(className.selected);
  6847. }
  6848. })
  6849. ;
  6850. },
  6851. selectedItem: function() {
  6852. $item.removeClass(className.selected);
  6853. },
  6854. value: function(removedValue, removedText, $removedItem) {
  6855. var
  6856. values = module.get.values(),
  6857. newValue
  6858. ;
  6859. if( module.has.selectInput() ) {
  6860. module.verbose('Input is <select> removing selected option', removedValue);
  6861. newValue = module.remove.arrayValue(removedValue, values);
  6862. module.remove.optionValue(removedValue);
  6863. }
  6864. else {
  6865. module.verbose('Removing from delimited values', removedValue);
  6866. newValue = module.remove.arrayValue(removedValue, values);
  6867. newValue = newValue.join(settings.delimiter);
  6868. }
  6869. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6870. module.verbose('No callback on initial load', settings.onRemove);
  6871. }
  6872. else {
  6873. settings.onRemove.call(element, removedValue, removedText, $removedItem);
  6874. }
  6875. module.set.value(newValue, removedText, $removedItem);
  6876. module.check.maxSelections();
  6877. },
  6878. arrayValue: function(removedValue, values) {
  6879. if( !$.isArray(values) ) {
  6880. values = [values];
  6881. }
  6882. values = $.grep(values, function(value){
  6883. return (removedValue != value);
  6884. });
  6885. module.verbose('Removed value from delimited string', removedValue, values);
  6886. return values;
  6887. },
  6888. label: function(value, shouldAnimate) {
  6889. var
  6890. $labels = $module.find(selector.label),
  6891. $removedLabel = $labels.filter('[data-' + metadata.value + '="' + module.escape.string(value) +'"]')
  6892. ;
  6893. module.verbose('Removing label', $removedLabel);
  6894. $removedLabel.remove();
  6895. },
  6896. activeLabels: function($activeLabels) {
  6897. $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
  6898. module.verbose('Removing active label selections', $activeLabels);
  6899. module.remove.labels($activeLabels);
  6900. },
  6901. labels: function($labels) {
  6902. $labels = $labels || $module.find(selector.label);
  6903. module.verbose('Removing labels', $labels);
  6904. $labels
  6905. .each(function(){
  6906. var
  6907. $label = $(this),
  6908. value = $label.data(metadata.value),
  6909. stringValue = (value !== undefined)
  6910. ? String(value)
  6911. : value,
  6912. isUserValue = module.is.userValue(stringValue)
  6913. ;
  6914. if(settings.onLabelRemove.call($label, value) === false) {
  6915. module.debug('Label remove callback cancelled removal');
  6916. return;
  6917. }
  6918. module.remove.message();
  6919. if(isUserValue) {
  6920. module.remove.value(stringValue);
  6921. module.remove.label(stringValue);
  6922. }
  6923. else {
  6924. // selected will also remove label
  6925. module.remove.selected(stringValue);
  6926. }
  6927. })
  6928. ;
  6929. },
  6930. tabbable: function() {
  6931. if( module.is.searchSelection() ) {
  6932. module.debug('Searchable dropdown initialized');
  6933. $search
  6934. .removeAttr('tabindex')
  6935. ;
  6936. $menu
  6937. .removeAttr('tabindex')
  6938. ;
  6939. }
  6940. else {
  6941. module.debug('Simple selection dropdown initialized');
  6942. $module
  6943. .removeAttr('tabindex')
  6944. ;
  6945. $menu
  6946. .removeAttr('tabindex')
  6947. ;
  6948. }
  6949. }
  6950. },
  6951. has: {
  6952. menuSearch: function() {
  6953. return (module.has.search() && $search.closest($menu).length > 0);
  6954. },
  6955. search: function() {
  6956. return ($search.length > 0);
  6957. },
  6958. sizer: function() {
  6959. return ($sizer.length > 0);
  6960. },
  6961. selectInput: function() {
  6962. return ( $input.is('select') );
  6963. },
  6964. minCharacters: function(searchTerm) {
  6965. if(settings.minCharacters) {
  6966. searchTerm = (searchTerm !== undefined)
  6967. ? String(searchTerm)
  6968. : String(module.get.query())
  6969. ;
  6970. return (searchTerm.length >= settings.minCharacters);
  6971. }
  6972. return true;
  6973. },
  6974. firstLetter: function($item, letter) {
  6975. var
  6976. text,
  6977. firstLetter
  6978. ;
  6979. if(!$item || $item.length === 0 || typeof letter !== 'string') {
  6980. return false;
  6981. }
  6982. text = module.get.choiceText($item, false);
  6983. letter = letter.toLowerCase();
  6984. firstLetter = String(text).charAt(0).toLowerCase();
  6985. return (letter == firstLetter);
  6986. },
  6987. input: function() {
  6988. return ($input.length > 0);
  6989. },
  6990. items: function() {
  6991. return ($item.length > 0);
  6992. },
  6993. menu: function() {
  6994. return ($menu.length > 0);
  6995. },
  6996. message: function() {
  6997. return ($menu.children(selector.message).length !== 0);
  6998. },
  6999. label: function(value) {
  7000. var
  7001. escapedValue = module.escape.value(value),
  7002. $labels = $module.find(selector.label)
  7003. ;
  7004. return ($labels.filter('[data-' + metadata.value + '="' + module.escape.string(escapedValue) +'"]').length > 0);
  7005. },
  7006. maxSelections: function() {
  7007. return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
  7008. },
  7009. allResultsFiltered: function() {
  7010. var
  7011. $normalResults = $item.not(selector.addition)
  7012. ;
  7013. return ($normalResults.filter(selector.unselectable).length === $normalResults.length);
  7014. },
  7015. userSuggestion: function() {
  7016. return ($menu.children(selector.addition).length > 0);
  7017. },
  7018. query: function() {
  7019. return (module.get.query() !== '');
  7020. },
  7021. value: function(value) {
  7022. return (settings.ignoreCase)
  7023. ? module.has.valueIgnoringCase(value)
  7024. : module.has.valueMatchingCase(value)
  7025. ;
  7026. },
  7027. valueMatchingCase: function(value) {
  7028. var
  7029. values = module.get.values(),
  7030. hasValue = $.isArray(values)
  7031. ? values && ($.inArray(value, values) !== -1)
  7032. : (values == value)
  7033. ;
  7034. return (hasValue)
  7035. ? true
  7036. : false
  7037. ;
  7038. },
  7039. valueIgnoringCase: function(value) {
  7040. var
  7041. values = module.get.values(),
  7042. hasValue = false
  7043. ;
  7044. if(!$.isArray(values)) {
  7045. values = [values];
  7046. }
  7047. $.each(values, function(index, existingValue) {
  7048. if(String(value).toLowerCase() == String(existingValue).toLowerCase()) {
  7049. hasValue = true;
  7050. return false;
  7051. }
  7052. });
  7053. return hasValue;
  7054. }
  7055. },
  7056. is: {
  7057. active: function() {
  7058. return $module.hasClass(className.active);
  7059. },
  7060. animatingInward: function() {
  7061. return $menu.transition('is inward');
  7062. },
  7063. animatingOutward: function() {
  7064. return $menu.transition('is outward');
  7065. },
  7066. bubbledLabelClick: function(event) {
  7067. return $(event.target).is('select, input') && $module.closest('label').length > 0;
  7068. },
  7069. bubbledIconClick: function(event) {
  7070. return $(event.target).closest($icon).length > 0;
  7071. },
  7072. alreadySetup: function() {
  7073. return ($module.is('select') && $module.parent(selector.dropdown).data(moduleNamespace) !== undefined && $module.prev().length === 0);
  7074. },
  7075. animating: function($subMenu) {
  7076. return ($subMenu)
  7077. ? $subMenu.transition && $subMenu.transition('is animating')
  7078. : $menu.transition && $menu.transition('is animating')
  7079. ;
  7080. },
  7081. leftward: function($subMenu) {
  7082. var $selectedMenu = $subMenu || $menu;
  7083. return $selectedMenu.hasClass(className.leftward);
  7084. },
  7085. disabled: function() {
  7086. return $module.hasClass(className.disabled);
  7087. },
  7088. focused: function() {
  7089. return (document.activeElement === $module[0]);
  7090. },
  7091. focusedOnSearch: function() {
  7092. return (document.activeElement === $search[0]);
  7093. },
  7094. allFiltered: function() {
  7095. return( (module.is.multiple() || module.has.search()) && !(settings.hideAdditions == false && module.has.userSuggestion()) && !module.has.message() && module.has.allResultsFiltered() );
  7096. },
  7097. hidden: function($subMenu) {
  7098. return !module.is.visible($subMenu);
  7099. },
  7100. initialLoad: function() {
  7101. return initialLoad;
  7102. },
  7103. inObject: function(needle, object) {
  7104. var
  7105. found = false
  7106. ;
  7107. $.each(object, function(index, property) {
  7108. if(property == needle) {
  7109. found = true;
  7110. return true;
  7111. }
  7112. });
  7113. return found;
  7114. },
  7115. multiple: function() {
  7116. return $module.hasClass(className.multiple);
  7117. },
  7118. remote: function() {
  7119. return settings.apiSettings && module.can.useAPI();
  7120. },
  7121. single: function() {
  7122. return !module.is.multiple();
  7123. },
  7124. selectMutation: function(mutations) {
  7125. var
  7126. selectChanged = false
  7127. ;
  7128. $.each(mutations, function(index, mutation) {
  7129. if(mutation.target && $(mutation.target).is('select')) {
  7130. selectChanged = true;
  7131. return true;
  7132. }
  7133. });
  7134. return selectChanged;
  7135. },
  7136. search: function() {
  7137. return $module.hasClass(className.search);
  7138. },
  7139. searchSelection: function() {
  7140. return ( module.has.search() && $search.parent(selector.dropdown).length === 1 );
  7141. },
  7142. selection: function() {
  7143. return $module.hasClass(className.selection);
  7144. },
  7145. userValue: function(value) {
  7146. return ($.inArray(value, module.get.userValues()) !== -1);
  7147. },
  7148. upward: function($menu) {
  7149. var $element = $menu || $module;
  7150. return $element.hasClass(className.upward);
  7151. },
  7152. visible: function($subMenu) {
  7153. return ($subMenu)
  7154. ? $subMenu.hasClass(className.visible)
  7155. : $menu.hasClass(className.visible)
  7156. ;
  7157. },
  7158. verticallyScrollableContext: function() {
  7159. var
  7160. overflowY = ($context.get(0) !== window)
  7161. ? $context.css('overflow-y')
  7162. : false
  7163. ;
  7164. return (overflowY == 'auto' || overflowY == 'scroll');
  7165. },
  7166. horizontallyScrollableContext: function() {
  7167. var
  7168. overflowX = ($context.get(0) !== window)
  7169. ? $context.css('overflow-X')
  7170. : false
  7171. ;
  7172. return (overflowX == 'auto' || overflowX == 'scroll');
  7173. }
  7174. },
  7175. can: {
  7176. activate: function($item) {
  7177. if(settings.useLabels) {
  7178. return true;
  7179. }
  7180. if(!module.has.maxSelections()) {
  7181. return true;
  7182. }
  7183. if(module.has.maxSelections() && $item.hasClass(className.active)) {
  7184. return true;
  7185. }
  7186. return false;
  7187. },
  7188. openDownward: function($subMenu) {
  7189. var
  7190. $currentMenu = $subMenu || $menu,
  7191. canOpenDownward = true,
  7192. onScreen = {},
  7193. calculations
  7194. ;
  7195. $currentMenu
  7196. .addClass(className.loading)
  7197. ;
  7198. calculations = {
  7199. context: {
  7200. offset : ($context.get(0) === window)
  7201. ? { top: 0, left: 0}
  7202. : $context.offset(),
  7203. scrollTop : $context.scrollTop(),
  7204. height : $context.outerHeight()
  7205. },
  7206. menu : {
  7207. offset: $currentMenu.offset(),
  7208. height: $currentMenu.outerHeight()
  7209. }
  7210. };
  7211. if(module.is.verticallyScrollableContext()) {
  7212. calculations.menu.offset.top += calculations.context.scrollTop;
  7213. }
  7214. onScreen = {
  7215. above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.context.offset.top - calculations.menu.height,
  7216. below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top - calculations.context.offset.top + calculations.menu.height
  7217. };
  7218. if(onScreen.below) {
  7219. module.verbose('Dropdown can fit in context downward', onScreen);
  7220. canOpenDownward = true;
  7221. }
  7222. else if(!onScreen.below && !onScreen.above) {
  7223. module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
  7224. canOpenDownward = true;
  7225. }
  7226. else {
  7227. module.verbose('Dropdown cannot fit below, opening upward', onScreen);
  7228. canOpenDownward = false;
  7229. }
  7230. $currentMenu.removeClass(className.loading);
  7231. return canOpenDownward;
  7232. },
  7233. openRightward: function($subMenu) {
  7234. var
  7235. $currentMenu = $subMenu || $menu,
  7236. canOpenRightward = true,
  7237. isOffscreenRight = false,
  7238. calculations
  7239. ;
  7240. $currentMenu
  7241. .addClass(className.loading)
  7242. ;
  7243. calculations = {
  7244. context: {
  7245. offset : ($context.get(0) === window)
  7246. ? { top: 0, left: 0}
  7247. : $context.offset(),
  7248. scrollLeft : $context.scrollLeft(),
  7249. width : $context.outerWidth()
  7250. },
  7251. menu: {
  7252. offset : $currentMenu.offset(),
  7253. width : $currentMenu.outerWidth()
  7254. }
  7255. };
  7256. if(module.is.horizontallyScrollableContext()) {
  7257. calculations.menu.offset.left += calculations.context.scrollLeft;
  7258. }
  7259. isOffscreenRight = (calculations.menu.offset.left - calculations.context.offset.left + calculations.menu.width >= calculations.context.scrollLeft + calculations.context.width);
  7260. if(isOffscreenRight) {
  7261. module.verbose('Dropdown cannot fit in context rightward', isOffscreenRight);
  7262. canOpenRightward = false;
  7263. }
  7264. $currentMenu.removeClass(className.loading);
  7265. return canOpenRightward;
  7266. },
  7267. click: function() {
  7268. return (hasTouch || settings.on == 'click');
  7269. },
  7270. extendSelect: function() {
  7271. return settings.allowAdditions || settings.apiSettings;
  7272. },
  7273. show: function() {
  7274. return !module.is.disabled() && (module.has.items() || module.has.message());
  7275. },
  7276. useAPI: function() {
  7277. return $.fn.api !== undefined;
  7278. }
  7279. },
  7280. animate: {
  7281. show: function(callback, $subMenu) {
  7282. var
  7283. $currentMenu = $subMenu || $menu,
  7284. start = ($subMenu)
  7285. ? function() {}
  7286. : function() {
  7287. module.hideSubMenus();
  7288. module.hideOthers();
  7289. module.set.active();
  7290. },
  7291. transition
  7292. ;
  7293. callback = $.isFunction(callback)
  7294. ? callback
  7295. : function(){}
  7296. ;
  7297. module.verbose('Doing menu show animation', $currentMenu);
  7298. module.set.direction($subMenu);
  7299. transition = module.get.transition($subMenu);
  7300. if( module.is.selection() ) {
  7301. module.set.scrollPosition(module.get.selectedItem(), true);
  7302. }
  7303. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  7304. if(transition == 'none') {
  7305. start();
  7306. $currentMenu.transition('show');
  7307. callback.call(element);
  7308. }
  7309. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  7310. $currentMenu
  7311. .transition({
  7312. animation : transition + ' in',
  7313. debug : settings.debug,
  7314. verbose : settings.verbose,
  7315. duration : settings.duration,
  7316. queue : true,
  7317. onStart : start,
  7318. onComplete : function() {
  7319. callback.call(element);
  7320. }
  7321. })
  7322. ;
  7323. }
  7324. else {
  7325. module.error(error.noTransition, transition);
  7326. }
  7327. }
  7328. },
  7329. hide: function(callback, $subMenu) {
  7330. var
  7331. $currentMenu = $subMenu || $menu,
  7332. duration = ($subMenu)
  7333. ? (settings.duration * 0.9)
  7334. : settings.duration,
  7335. start = ($subMenu)
  7336. ? function() {}
  7337. : function() {
  7338. if( module.can.click() ) {
  7339. module.unbind.intent();
  7340. }
  7341. module.remove.active();
  7342. },
  7343. transition = module.get.transition($subMenu)
  7344. ;
  7345. callback = $.isFunction(callback)
  7346. ? callback
  7347. : function(){}
  7348. ;
  7349. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  7350. module.verbose('Doing menu hide animation', $currentMenu);
  7351. if(transition == 'none') {
  7352. start();
  7353. $currentMenu.transition('hide');
  7354. callback.call(element);
  7355. }
  7356. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  7357. $currentMenu
  7358. .transition({
  7359. animation : transition + ' out',
  7360. duration : settings.duration,
  7361. debug : settings.debug,
  7362. verbose : settings.verbose,
  7363. queue : false,
  7364. onStart : start,
  7365. onComplete : function() {
  7366. callback.call(element);
  7367. }
  7368. })
  7369. ;
  7370. }
  7371. else {
  7372. module.error(error.transition);
  7373. }
  7374. }
  7375. }
  7376. },
  7377. hideAndClear: function() {
  7378. module.remove.searchTerm();
  7379. if( module.has.maxSelections() ) {
  7380. return;
  7381. }
  7382. if(module.has.search()) {
  7383. module.hide(function() {
  7384. module.remove.filteredItem();
  7385. });
  7386. }
  7387. else {
  7388. module.hide();
  7389. }
  7390. },
  7391. delay: {
  7392. show: function() {
  7393. module.verbose('Delaying show event to ensure user intent');
  7394. clearTimeout(module.timer);
  7395. module.timer = setTimeout(module.show, settings.delay.show);
  7396. },
  7397. hide: function() {
  7398. module.verbose('Delaying hide event to ensure user intent');
  7399. clearTimeout(module.timer);
  7400. module.timer = setTimeout(module.hide, settings.delay.hide);
  7401. }
  7402. },
  7403. escape: {
  7404. value: function(value) {
  7405. var
  7406. multipleValues = $.isArray(value),
  7407. stringValue = (typeof value === 'string'),
  7408. isUnparsable = (!stringValue && !multipleValues),
  7409. hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
  7410. values = []
  7411. ;
  7412. if(isUnparsable || !hasQuotes) {
  7413. return value;
  7414. }
  7415. module.debug('Encoding quote values for use in select', value);
  7416. if(multipleValues) {
  7417. $.each(value, function(index, value){
  7418. values.push(value.replace(regExp.quote, '&quot;'));
  7419. });
  7420. return values;
  7421. }
  7422. return value.replace(regExp.quote, '&quot;');
  7423. },
  7424. string: function(text) {
  7425. text = String(text);
  7426. return text.replace(regExp.escape, '\\$&');
  7427. }
  7428. },
  7429. setting: function(name, value) {
  7430. module.debug('Changing setting', name, value);
  7431. if( $.isPlainObject(name) ) {
  7432. $.extend(true, settings, name);
  7433. }
  7434. else if(value !== undefined) {
  7435. if($.isPlainObject(settings[name])) {
  7436. $.extend(true, settings[name], value);
  7437. }
  7438. else {
  7439. settings[name] = value;
  7440. }
  7441. }
  7442. else {
  7443. return settings[name];
  7444. }
  7445. },
  7446. internal: function(name, value) {
  7447. if( $.isPlainObject(name) ) {
  7448. $.extend(true, module, name);
  7449. }
  7450. else if(value !== undefined) {
  7451. module[name] = value;
  7452. }
  7453. else {
  7454. return module[name];
  7455. }
  7456. },
  7457. debug: function() {
  7458. if(!settings.silent && settings.debug) {
  7459. if(settings.performance) {
  7460. module.performance.log(arguments);
  7461. }
  7462. else {
  7463. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7464. module.debug.apply(console, arguments);
  7465. }
  7466. }
  7467. },
  7468. verbose: function() {
  7469. if(!settings.silent && settings.verbose && settings.debug) {
  7470. if(settings.performance) {
  7471. module.performance.log(arguments);
  7472. }
  7473. else {
  7474. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7475. module.verbose.apply(console, arguments);
  7476. }
  7477. }
  7478. },
  7479. error: function() {
  7480. if(!settings.silent) {
  7481. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  7482. module.error.apply(console, arguments);
  7483. }
  7484. },
  7485. performance: {
  7486. log: function(message) {
  7487. var
  7488. currentTime,
  7489. executionTime,
  7490. previousTime
  7491. ;
  7492. if(settings.performance) {
  7493. currentTime = new Date().getTime();
  7494. previousTime = time || currentTime;
  7495. executionTime = currentTime - previousTime;
  7496. time = currentTime;
  7497. performance.push({
  7498. 'Name' : message[0],
  7499. 'Arguments' : [].slice.call(message, 1) || '',
  7500. 'Element' : element,
  7501. 'Execution Time' : executionTime
  7502. });
  7503. }
  7504. clearTimeout(module.performance.timer);
  7505. module.performance.timer = setTimeout(module.performance.display, 500);
  7506. },
  7507. display: function() {
  7508. var
  7509. title = settings.name + ':',
  7510. totalTime = 0
  7511. ;
  7512. time = false;
  7513. clearTimeout(module.performance.timer);
  7514. $.each(performance, function(index, data) {
  7515. totalTime += data['Execution Time'];
  7516. });
  7517. title += ' ' + totalTime + 'ms';
  7518. if(moduleSelector) {
  7519. title += ' \'' + moduleSelector + '\'';
  7520. }
  7521. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  7522. console.groupCollapsed(title);
  7523. if(console.table) {
  7524. console.table(performance);
  7525. }
  7526. else {
  7527. $.each(performance, function(index, data) {
  7528. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  7529. });
  7530. }
  7531. console.groupEnd();
  7532. }
  7533. performance = [];
  7534. }
  7535. },
  7536. invoke: function(query, passedArguments, context) {
  7537. var
  7538. object = instance,
  7539. maxDepth,
  7540. found,
  7541. response
  7542. ;
  7543. passedArguments = passedArguments || queryArguments;
  7544. context = element || context;
  7545. if(typeof query == 'string' && object !== undefined) {
  7546. query = query.split(/[\. ]/);
  7547. maxDepth = query.length - 1;
  7548. $.each(query, function(depth, value) {
  7549. var camelCaseValue = (depth != maxDepth)
  7550. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  7551. : query
  7552. ;
  7553. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  7554. object = object[camelCaseValue];
  7555. }
  7556. else if( object[camelCaseValue] !== undefined ) {
  7557. found = object[camelCaseValue];
  7558. return false;
  7559. }
  7560. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  7561. object = object[value];
  7562. }
  7563. else if( object[value] !== undefined ) {
  7564. found = object[value];
  7565. return false;
  7566. }
  7567. else {
  7568. module.error(error.method, query);
  7569. return false;
  7570. }
  7571. });
  7572. }
  7573. if ( $.isFunction( found ) ) {
  7574. response = found.apply(context, passedArguments);
  7575. }
  7576. else if(found !== undefined) {
  7577. response = found;
  7578. }
  7579. if($.isArray(returnedValue)) {
  7580. returnedValue.push(response);
  7581. }
  7582. else if(returnedValue !== undefined) {
  7583. returnedValue = [returnedValue, response];
  7584. }
  7585. else if(response !== undefined) {
  7586. returnedValue = response;
  7587. }
  7588. return found;
  7589. }
  7590. };
  7591. if(methodInvoked) {
  7592. if(instance === undefined) {
  7593. module.initialize();
  7594. }
  7595. module.invoke(query);
  7596. }
  7597. else {
  7598. if(instance !== undefined) {
  7599. instance.invoke('destroy');
  7600. }
  7601. module.initialize();
  7602. }
  7603. })
  7604. ;
  7605. return (returnedValue !== undefined)
  7606. ? returnedValue
  7607. : $allModules
  7608. ;
  7609. };
  7610. $.fn.dropdown.settings = {
  7611. silent : false,
  7612. debug : false,
  7613. verbose : false,
  7614. performance : true,
  7615. on : 'click', // what event should show menu action on item selection
  7616. action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
  7617. values : false, // specify values to use for dropdown
  7618. apiSettings : false,
  7619. selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
  7620. minCharacters : 0, // Minimum characters required to trigger API call
  7621. filterRemoteData : false, // Whether API results should be filtered after being returned for query term
  7622. saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
  7623. throttle : 200, // How long to wait after last user input to search remotely
  7624. context : window, // Context to use when determining if on screen
  7625. direction : 'auto', // Whether dropdown should always open in one direction
  7626. keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
  7627. match : 'both', // what to match against with search selection (both, text, or label)
  7628. fullTextSearch : false, // search anywhere in value (set to 'exact' to require exact matches)
  7629. placeholder : 'auto', // whether to convert blank <select> values to placeholder text
  7630. preserveHTML : true, // preserve html when selecting value
  7631. sortSelect : false, // sort selection on init
  7632. forceSelection : true, // force a choice on blur with search selection
  7633. allowAdditions : false, // whether multiple select should allow user added values
  7634. ignoreCase : false, // whether to consider values not matching in case to be the same
  7635. hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
  7636. maxSelections : false, // When set to a number limits the number of selections to this count
  7637. useLabels : true, // whether multiple select should filter currently active selections from choices
  7638. delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
  7639. showOnFocus : true, // show menu on focus
  7640. allowReselection : false, // whether current value should trigger callbacks when reselected
  7641. allowTab : true, // add tabindex to element
  7642. allowCategorySelection : false, // allow elements with sub-menus to be selected
  7643. fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
  7644. transition : 'auto', // auto transition will slide down or up based on direction
  7645. duration : 200, // duration of transition
  7646. glyphWidth : 1.037, // widest glyph width in em (W is 1.037 em) used to calculate multiselect input width
  7647. // label settings on multi-select
  7648. label: {
  7649. transition : 'scale',
  7650. duration : 200,
  7651. variation : false
  7652. },
  7653. // delay before event
  7654. delay : {
  7655. hide : 300,
  7656. show : 200,
  7657. search : 20,
  7658. touch : 50
  7659. },
  7660. /* Callbacks */
  7661. onChange : function(value, text, $selected){},
  7662. onAdd : function(value, text, $selected){},
  7663. onRemove : function(value, text, $selected){},
  7664. onLabelSelect : function($selectedLabels){},
  7665. onLabelCreate : function(value, text) { return $(this); },
  7666. onLabelRemove : function(value) { return true; },
  7667. onNoResults : function(searchTerm) { return true; },
  7668. onShow : function(){},
  7669. onHide : function(){},
  7670. /* Component */
  7671. name : 'Dropdown',
  7672. namespace : 'dropdown',
  7673. message: {
  7674. addResult : 'Add <b>{term}</b>',
  7675. count : '{count} selected',
  7676. maxSelections : 'Max {maxCount} selections',
  7677. noResults : 'No results found.',
  7678. serverError : 'There was an error contacting the server'
  7679. },
  7680. error : {
  7681. action : 'You called a dropdown action that was not defined',
  7682. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  7683. labels : 'Allowing user additions currently requires the use of labels.',
  7684. missingMultiple : '<select> requires multiple property to be set to correctly preserve multiple values',
  7685. method : 'The method you called is not defined.',
  7686. noAPI : 'The API module is required to load resources remotely',
  7687. noStorage : 'Saving remote data requires session storage',
  7688. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>'
  7689. },
  7690. regExp : {
  7691. escape : /[-[\]{}()*+?.,\\^$|#\s]/g,
  7692. quote : /"/g
  7693. },
  7694. metadata : {
  7695. defaultText : 'defaultText',
  7696. defaultValue : 'defaultValue',
  7697. placeholderText : 'placeholder',
  7698. text : 'text',
  7699. value : 'value'
  7700. },
  7701. // property names for remote query
  7702. fields: {
  7703. remoteValues : 'results', // grouping for api results
  7704. values : 'values', // grouping for all dropdown values
  7705. disabled : 'disabled', // whether value should be disabled
  7706. name : 'name', // displayed dropdown text
  7707. value : 'value', // actual dropdown value
  7708. text : 'text' // displayed text when selected
  7709. },
  7710. keys : {
  7711. backspace : 8,
  7712. delimiter : 188, // comma
  7713. deleteKey : 46,
  7714. enter : 13,
  7715. escape : 27,
  7716. pageUp : 33,
  7717. pageDown : 34,
  7718. leftArrow : 37,
  7719. upArrow : 38,
  7720. rightArrow : 39,
  7721. downArrow : 40
  7722. },
  7723. selector : {
  7724. addition : '.addition',
  7725. dropdown : '.ui.dropdown',
  7726. hidden : '.hidden',
  7727. icon : '> .dropdown.icon',
  7728. input : '> input[type="hidden"], > select',
  7729. item : '.item',
  7730. label : '> .label',
  7731. remove : '> .label > .delete.icon',
  7732. siblingLabel : '.label',
  7733. menu : '.menu',
  7734. message : '.message',
  7735. menuIcon : '.dropdown.icon',
  7736. search : 'input.search, .menu > .search > input, .menu input.search',
  7737. sizer : '> input.sizer',
  7738. text : '> .text:not(.icon)',
  7739. unselectable : '.disabled, .filtered'
  7740. },
  7741. className : {
  7742. active : 'active',
  7743. addition : 'addition',
  7744. animating : 'animating',
  7745. disabled : 'disabled',
  7746. empty : 'empty',
  7747. dropdown : 'ui dropdown',
  7748. filtered : 'filtered',
  7749. hidden : 'hidden transition',
  7750. item : 'item',
  7751. label : 'ui label',
  7752. loading : 'loading',
  7753. menu : 'menu',
  7754. message : 'message',
  7755. multiple : 'multiple',
  7756. placeholder : 'default',
  7757. sizer : 'sizer',
  7758. search : 'search',
  7759. selected : 'selected',
  7760. selection : 'selection',
  7761. upward : 'upward',
  7762. leftward : 'left',
  7763. visible : 'visible'
  7764. }
  7765. };
  7766. /* Templates */
  7767. $.fn.dropdown.settings.templates = {
  7768. // generates dropdown from select values
  7769. dropdown: function(select) {
  7770. var
  7771. placeholder = select.placeholder || false,
  7772. values = select.values || {},
  7773. html = ''
  7774. ;
  7775. html += '<i class="dropdown icon"></i>';
  7776. if(select.placeholder) {
  7777. html += '<div class="default text">' + placeholder + '</div>';
  7778. }
  7779. else {
  7780. html += '<div class="text"></div>';
  7781. }
  7782. html += '<div class="menu">';
  7783. $.each(select.values, function(index, option) {
  7784. html += (option.disabled)
  7785. ? '<div class="disabled item" data-value="' + option.value + '">' + option.name + '</div>'
  7786. : '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'
  7787. ;
  7788. });
  7789. html += '</div>';
  7790. return html;
  7791. },
  7792. // generates just menu from select
  7793. menu: function(response, fields) {
  7794. var
  7795. values = response[fields.values] || {},
  7796. html = ''
  7797. ;
  7798. $.each(values, function(index, option) {
  7799. var
  7800. maybeText = (option[fields.text])
  7801. ? 'data-text="' + option[fields.text] + '"'
  7802. : '',
  7803. maybeDisabled = (option[fields.disabled])
  7804. ? 'disabled '
  7805. : ''
  7806. ;
  7807. html += '<div class="'+ maybeDisabled +'item" data-value="' + option[fields.value] + '"' + maybeText + '>'
  7808. html += option[fields.name];
  7809. html += '</div>';
  7810. });
  7811. return html;
  7812. },
  7813. // generates label for multiselect
  7814. label: function(value, text) {
  7815. return text + '<i class="delete icon"></i>';
  7816. },
  7817. // generates messages like "No results"
  7818. message: function(message) {
  7819. return message;
  7820. },
  7821. // generates user addition to selection menu
  7822. addition: function(choice) {
  7823. return choice;
  7824. }
  7825. };
  7826. })( jQuery, window, document );
  7827. /*!
  7828. * # Semantic UI 2.3.0 - Embed
  7829. * http://github.com/semantic-org/semantic-ui/
  7830. *
  7831. *
  7832. * Released under the MIT license
  7833. * http://opensource.org/licenses/MIT
  7834. *
  7835. */
  7836. ;(function ($, window, document, undefined) {
  7837. "use strict";
  7838. window = (typeof window != 'undefined' && window.Math == Math)
  7839. ? window
  7840. : (typeof self != 'undefined' && self.Math == Math)
  7841. ? self
  7842. : Function('return this')()
  7843. ;
  7844. $.fn.embed = function(parameters) {
  7845. var
  7846. $allModules = $(this),
  7847. moduleSelector = $allModules.selector || '',
  7848. time = new Date().getTime(),
  7849. performance = [],
  7850. query = arguments[0],
  7851. methodInvoked = (typeof query == 'string'),
  7852. queryArguments = [].slice.call(arguments, 1),
  7853. returnedValue
  7854. ;
  7855. $allModules
  7856. .each(function() {
  7857. var
  7858. settings = ( $.isPlainObject(parameters) )
  7859. ? $.extend(true, {}, $.fn.embed.settings, parameters)
  7860. : $.extend({}, $.fn.embed.settings),
  7861. selector = settings.selector,
  7862. className = settings.className,
  7863. sources = settings.sources,
  7864. error = settings.error,
  7865. metadata = settings.metadata,
  7866. namespace = settings.namespace,
  7867. templates = settings.templates,
  7868. eventNamespace = '.' + namespace,
  7869. moduleNamespace = 'module-' + namespace,
  7870. $window = $(window),
  7871. $module = $(this),
  7872. $placeholder = $module.find(selector.placeholder),
  7873. $icon = $module.find(selector.icon),
  7874. $embed = $module.find(selector.embed),
  7875. element = this,
  7876. instance = $module.data(moduleNamespace),
  7877. module
  7878. ;
  7879. module = {
  7880. initialize: function() {
  7881. module.debug('Initializing embed');
  7882. module.determine.autoplay();
  7883. module.create();
  7884. module.bind.events();
  7885. module.instantiate();
  7886. },
  7887. instantiate: function() {
  7888. module.verbose('Storing instance of module', module);
  7889. instance = module;
  7890. $module
  7891. .data(moduleNamespace, module)
  7892. ;
  7893. },
  7894. destroy: function() {
  7895. module.verbose('Destroying previous instance of embed');
  7896. module.reset();
  7897. $module
  7898. .removeData(moduleNamespace)
  7899. .off(eventNamespace)
  7900. ;
  7901. },
  7902. refresh: function() {
  7903. module.verbose('Refreshing selector cache');
  7904. $placeholder = $module.find(selector.placeholder);
  7905. $icon = $module.find(selector.icon);
  7906. $embed = $module.find(selector.embed);
  7907. },
  7908. bind: {
  7909. events: function() {
  7910. if( module.has.placeholder() ) {
  7911. module.debug('Adding placeholder events');
  7912. $module
  7913. .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
  7914. .on('click' + eventNamespace, selector.icon, module.createAndShow)
  7915. ;
  7916. }
  7917. }
  7918. },
  7919. create: function() {
  7920. var
  7921. placeholder = module.get.placeholder()
  7922. ;
  7923. if(placeholder) {
  7924. module.createPlaceholder();
  7925. }
  7926. else {
  7927. module.createAndShow();
  7928. }
  7929. },
  7930. createPlaceholder: function(placeholder) {
  7931. var
  7932. icon = module.get.icon(),
  7933. url = module.get.url(),
  7934. embed = module.generate.embed(url)
  7935. ;
  7936. placeholder = placeholder || module.get.placeholder();
  7937. $module.html( templates.placeholder(placeholder, icon) );
  7938. module.debug('Creating placeholder for embed', placeholder, icon);
  7939. },
  7940. createEmbed: function(url) {
  7941. module.refresh();
  7942. url = url || module.get.url();
  7943. $embed = $('<div/>')
  7944. .addClass(className.embed)
  7945. .html( module.generate.embed(url) )
  7946. .appendTo($module)
  7947. ;
  7948. settings.onCreate.call(element, url);
  7949. module.debug('Creating embed object', $embed);
  7950. },
  7951. changeEmbed: function(url) {
  7952. $embed
  7953. .html( module.generate.embed(url) )
  7954. ;
  7955. },
  7956. createAndShow: function() {
  7957. module.createEmbed();
  7958. module.show();
  7959. },
  7960. // sets new embed
  7961. change: function(source, id, url) {
  7962. module.debug('Changing video to ', source, id, url);
  7963. $module
  7964. .data(metadata.source, source)
  7965. .data(metadata.id, id)
  7966. ;
  7967. if(url) {
  7968. $module.data(metadata.url, url);
  7969. }
  7970. else {
  7971. $module.removeData(metadata.url);
  7972. }
  7973. if(module.has.embed()) {
  7974. module.changeEmbed();
  7975. }
  7976. else {
  7977. module.create();
  7978. }
  7979. },
  7980. // clears embed
  7981. reset: function() {
  7982. module.debug('Clearing embed and showing placeholder');
  7983. module.remove.active();
  7984. module.remove.embed();
  7985. module.showPlaceholder();
  7986. settings.onReset.call(element);
  7987. },
  7988. // shows current embed
  7989. show: function() {
  7990. module.debug('Showing embed');
  7991. module.set.active();
  7992. settings.onDisplay.call(element);
  7993. },
  7994. hide: function() {
  7995. module.debug('Hiding embed');
  7996. module.showPlaceholder();
  7997. },
  7998. showPlaceholder: function() {
  7999. module.debug('Showing placeholder image');
  8000. module.remove.active();
  8001. settings.onPlaceholderDisplay.call(element);
  8002. },
  8003. get: {
  8004. id: function() {
  8005. return settings.id || $module.data(metadata.id);
  8006. },
  8007. placeholder: function() {
  8008. return settings.placeholder || $module.data(metadata.placeholder);
  8009. },
  8010. icon: function() {
  8011. return (settings.icon)
  8012. ? settings.icon
  8013. : ($module.data(metadata.icon) !== undefined)
  8014. ? $module.data(metadata.icon)
  8015. : module.determine.icon()
  8016. ;
  8017. },
  8018. source: function(url) {
  8019. return (settings.source)
  8020. ? settings.source
  8021. : ($module.data(metadata.source) !== undefined)
  8022. ? $module.data(metadata.source)
  8023. : module.determine.source()
  8024. ;
  8025. },
  8026. type: function() {
  8027. var source = module.get.source();
  8028. return (sources[source] !== undefined)
  8029. ? sources[source].type
  8030. : false
  8031. ;
  8032. },
  8033. url: function() {
  8034. return (settings.url)
  8035. ? settings.url
  8036. : ($module.data(metadata.url) !== undefined)
  8037. ? $module.data(metadata.url)
  8038. : module.determine.url()
  8039. ;
  8040. }
  8041. },
  8042. determine: {
  8043. autoplay: function() {
  8044. if(module.should.autoplay()) {
  8045. settings.autoplay = true;
  8046. }
  8047. },
  8048. source: function(url) {
  8049. var
  8050. matchedSource = false
  8051. ;
  8052. url = url || module.get.url();
  8053. if(url) {
  8054. $.each(sources, function(name, source) {
  8055. if(url.search(source.domain) !== -1) {
  8056. matchedSource = name;
  8057. return false;
  8058. }
  8059. });
  8060. }
  8061. return matchedSource;
  8062. },
  8063. icon: function() {
  8064. var
  8065. source = module.get.source()
  8066. ;
  8067. return (sources[source] !== undefined)
  8068. ? sources[source].icon
  8069. : false
  8070. ;
  8071. },
  8072. url: function() {
  8073. var
  8074. id = settings.id || $module.data(metadata.id),
  8075. source = settings.source || $module.data(metadata.source),
  8076. url
  8077. ;
  8078. url = (sources[source] !== undefined)
  8079. ? sources[source].url.replace('{id}', id)
  8080. : false
  8081. ;
  8082. if(url) {
  8083. $module.data(metadata.url, url);
  8084. }
  8085. return url;
  8086. }
  8087. },
  8088. set: {
  8089. active: function() {
  8090. $module.addClass(className.active);
  8091. }
  8092. },
  8093. remove: {
  8094. active: function() {
  8095. $module.removeClass(className.active);
  8096. },
  8097. embed: function() {
  8098. $embed.empty();
  8099. }
  8100. },
  8101. encode: {
  8102. parameters: function(parameters) {
  8103. var
  8104. urlString = [],
  8105. index
  8106. ;
  8107. for (index in parameters) {
  8108. urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
  8109. }
  8110. return urlString.join('&amp;');
  8111. }
  8112. },
  8113. generate: {
  8114. embed: function(url) {
  8115. module.debug('Generating embed html');
  8116. var
  8117. source = module.get.source(),
  8118. html,
  8119. parameters
  8120. ;
  8121. url = module.get.url(url);
  8122. if(url) {
  8123. parameters = module.generate.parameters(source);
  8124. html = templates.iframe(url, parameters);
  8125. }
  8126. else {
  8127. module.error(error.noURL, $module);
  8128. }
  8129. return html;
  8130. },
  8131. parameters: function(source, extraParameters) {
  8132. var
  8133. parameters = (sources[source] && sources[source].parameters !== undefined)
  8134. ? sources[source].parameters(settings)
  8135. : {}
  8136. ;
  8137. extraParameters = extraParameters || settings.parameters;
  8138. if(extraParameters) {
  8139. parameters = $.extend({}, parameters, extraParameters);
  8140. }
  8141. parameters = settings.onEmbed(parameters);
  8142. return module.encode.parameters(parameters);
  8143. }
  8144. },
  8145. has: {
  8146. embed: function() {
  8147. return ($embed.length > 0);
  8148. },
  8149. placeholder: function() {
  8150. return settings.placeholder || $module.data(metadata.placeholder);
  8151. }
  8152. },
  8153. should: {
  8154. autoplay: function() {
  8155. return (settings.autoplay === 'auto')
  8156. ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
  8157. : settings.autoplay
  8158. ;
  8159. }
  8160. },
  8161. is: {
  8162. video: function() {
  8163. return module.get.type() == 'video';
  8164. }
  8165. },
  8166. setting: function(name, value) {
  8167. module.debug('Changing setting', name, value);
  8168. if( $.isPlainObject(name) ) {
  8169. $.extend(true, settings, name);
  8170. }
  8171. else if(value !== undefined) {
  8172. if($.isPlainObject(settings[name])) {
  8173. $.extend(true, settings[name], value);
  8174. }
  8175. else {
  8176. settings[name] = value;
  8177. }
  8178. }
  8179. else {
  8180. return settings[name];
  8181. }
  8182. },
  8183. internal: function(name, value) {
  8184. if( $.isPlainObject(name) ) {
  8185. $.extend(true, module, name);
  8186. }
  8187. else if(value !== undefined) {
  8188. module[name] = value;
  8189. }
  8190. else {
  8191. return module[name];
  8192. }
  8193. },
  8194. debug: function() {
  8195. if(!settings.silent && settings.debug) {
  8196. if(settings.performance) {
  8197. module.performance.log(arguments);
  8198. }
  8199. else {
  8200. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8201. module.debug.apply(console, arguments);
  8202. }
  8203. }
  8204. },
  8205. verbose: function() {
  8206. if(!settings.silent && settings.verbose && settings.debug) {
  8207. if(settings.performance) {
  8208. module.performance.log(arguments);
  8209. }
  8210. else {
  8211. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8212. module.verbose.apply(console, arguments);
  8213. }
  8214. }
  8215. },
  8216. error: function() {
  8217. if(!settings.silent) {
  8218. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  8219. module.error.apply(console, arguments);
  8220. }
  8221. },
  8222. performance: {
  8223. log: function(message) {
  8224. var
  8225. currentTime,
  8226. executionTime,
  8227. previousTime
  8228. ;
  8229. if(settings.performance) {
  8230. currentTime = new Date().getTime();
  8231. previousTime = time || currentTime;
  8232. executionTime = currentTime - previousTime;
  8233. time = currentTime;
  8234. performance.push({
  8235. 'Name' : message[0],
  8236. 'Arguments' : [].slice.call(message, 1) || '',
  8237. 'Element' : element,
  8238. 'Execution Time' : executionTime
  8239. });
  8240. }
  8241. clearTimeout(module.performance.timer);
  8242. module.performance.timer = setTimeout(module.performance.display, 500);
  8243. },
  8244. display: function() {
  8245. var
  8246. title = settings.name + ':',
  8247. totalTime = 0
  8248. ;
  8249. time = false;
  8250. clearTimeout(module.performance.timer);
  8251. $.each(performance, function(index, data) {
  8252. totalTime += data['Execution Time'];
  8253. });
  8254. title += ' ' + totalTime + 'ms';
  8255. if(moduleSelector) {
  8256. title += ' \'' + moduleSelector + '\'';
  8257. }
  8258. if($allModules.length > 1) {
  8259. title += ' ' + '(' + $allModules.length + ')';
  8260. }
  8261. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  8262. console.groupCollapsed(title);
  8263. if(console.table) {
  8264. console.table(performance);
  8265. }
  8266. else {
  8267. $.each(performance, function(index, data) {
  8268. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  8269. });
  8270. }
  8271. console.groupEnd();
  8272. }
  8273. performance = [];
  8274. }
  8275. },
  8276. invoke: function(query, passedArguments, context) {
  8277. var
  8278. object = instance,
  8279. maxDepth,
  8280. found,
  8281. response
  8282. ;
  8283. passedArguments = passedArguments || queryArguments;
  8284. context = element || context;
  8285. if(typeof query == 'string' && object !== undefined) {
  8286. query = query.split(/[\. ]/);
  8287. maxDepth = query.length - 1;
  8288. $.each(query, function(depth, value) {
  8289. var camelCaseValue = (depth != maxDepth)
  8290. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  8291. : query
  8292. ;
  8293. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  8294. object = object[camelCaseValue];
  8295. }
  8296. else if( object[camelCaseValue] !== undefined ) {
  8297. found = object[camelCaseValue];
  8298. return false;
  8299. }
  8300. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  8301. object = object[value];
  8302. }
  8303. else if( object[value] !== undefined ) {
  8304. found = object[value];
  8305. return false;
  8306. }
  8307. else {
  8308. module.error(error.method, query);
  8309. return false;
  8310. }
  8311. });
  8312. }
  8313. if ( $.isFunction( found ) ) {
  8314. response = found.apply(context, passedArguments);
  8315. }
  8316. else if(found !== undefined) {
  8317. response = found;
  8318. }
  8319. if($.isArray(returnedValue)) {
  8320. returnedValue.push(response);
  8321. }
  8322. else if(returnedValue !== undefined) {
  8323. returnedValue = [returnedValue, response];
  8324. }
  8325. else if(response !== undefined) {
  8326. returnedValue = response;
  8327. }
  8328. return found;
  8329. }
  8330. };
  8331. if(methodInvoked) {
  8332. if(instance === undefined) {
  8333. module.initialize();
  8334. }
  8335. module.invoke(query);
  8336. }
  8337. else {
  8338. if(instance !== undefined) {
  8339. instance.invoke('destroy');
  8340. }
  8341. module.initialize();
  8342. }
  8343. })
  8344. ;
  8345. return (returnedValue !== undefined)
  8346. ? returnedValue
  8347. : this
  8348. ;
  8349. };
  8350. $.fn.embed.settings = {
  8351. name : 'Embed',
  8352. namespace : 'embed',
  8353. silent : false,
  8354. debug : false,
  8355. verbose : false,
  8356. performance : true,
  8357. icon : false,
  8358. source : false,
  8359. url : false,
  8360. id : false,
  8361. // standard video settings
  8362. autoplay : 'auto',
  8363. color : '#444444',
  8364. hd : true,
  8365. brandedUI : false,
  8366. // additional parameters to include with the embed
  8367. parameters: false,
  8368. onDisplay : function() {},
  8369. onPlaceholderDisplay : function() {},
  8370. onReset : function() {},
  8371. onCreate : function(url) {},
  8372. onEmbed : function(parameters) {
  8373. return parameters;
  8374. },
  8375. metadata : {
  8376. id : 'id',
  8377. icon : 'icon',
  8378. placeholder : 'placeholder',
  8379. source : 'source',
  8380. url : 'url'
  8381. },
  8382. error : {
  8383. noURL : 'No URL specified',
  8384. method : 'The method you called is not defined'
  8385. },
  8386. className : {
  8387. active : 'active',
  8388. embed : 'embed'
  8389. },
  8390. selector : {
  8391. embed : '.embed',
  8392. placeholder : '.placeholder',
  8393. icon : '.icon'
  8394. },
  8395. sources: {
  8396. youtube: {
  8397. name : 'youtube',
  8398. type : 'video',
  8399. icon : 'video play',
  8400. domain : 'youtube.com',
  8401. url : '//www.youtube.com/embed/{id}',
  8402. parameters: function(settings) {
  8403. return {
  8404. autohide : !settings.brandedUI,
  8405. autoplay : settings.autoplay,
  8406. color : settings.color || undefined,
  8407. hq : settings.hd,
  8408. jsapi : settings.api,
  8409. modestbranding : !settings.brandedUI
  8410. };
  8411. }
  8412. },
  8413. vimeo: {
  8414. name : 'vimeo',
  8415. type : 'video',
  8416. icon : 'video play',
  8417. domain : 'vimeo.com',
  8418. url : '//player.vimeo.com/video/{id}',
  8419. parameters: function(settings) {
  8420. return {
  8421. api : settings.api,
  8422. autoplay : settings.autoplay,
  8423. byline : settings.brandedUI,
  8424. color : settings.color || undefined,
  8425. portrait : settings.brandedUI,
  8426. title : settings.brandedUI
  8427. };
  8428. }
  8429. }
  8430. },
  8431. templates: {
  8432. iframe : function(url, parameters) {
  8433. var src = url;
  8434. if (parameters) {
  8435. src += '?' + parameters;
  8436. }
  8437. return ''
  8438. + '<iframe src="' + src + '"'
  8439. + ' width="100%" height="100%"'
  8440. + ' frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  8441. ;
  8442. },
  8443. placeholder : function(image, icon) {
  8444. var
  8445. html = ''
  8446. ;
  8447. if(icon) {
  8448. html += '<i class="' + icon + ' icon"></i>';
  8449. }
  8450. if(image) {
  8451. html += '<img class="placeholder" src="' + image + '">';
  8452. }
  8453. return html;
  8454. }
  8455. },
  8456. // NOT YET IMPLEMENTED
  8457. api : false,
  8458. onPause : function() {},
  8459. onPlay : function() {},
  8460. onStop : function() {}
  8461. };
  8462. })( jQuery, window, document );
  8463. /*!
  8464. * # Semantic UI 2.3.0 - Modal
  8465. * http://github.com/semantic-org/semantic-ui/
  8466. *
  8467. *
  8468. * Released under the MIT license
  8469. * http://opensource.org/licenses/MIT
  8470. *
  8471. */
  8472. ;(function ($, window, document, undefined) {
  8473. "use strict";
  8474. window = (typeof window != 'undefined' && window.Math == Math)
  8475. ? window
  8476. : (typeof self != 'undefined' && self.Math == Math)
  8477. ? self
  8478. : Function('return this')()
  8479. ;
  8480. $.fn.modal = function(parameters) {
  8481. var
  8482. $allModules = $(this),
  8483. $window = $(window),
  8484. $document = $(document),
  8485. $body = $('body'),
  8486. moduleSelector = $allModules.selector || '',
  8487. time = new Date().getTime(),
  8488. performance = [],
  8489. query = arguments[0],
  8490. methodInvoked = (typeof query == 'string'),
  8491. queryArguments = [].slice.call(arguments, 1),
  8492. requestAnimationFrame = window.requestAnimationFrame
  8493. || window.mozRequestAnimationFrame
  8494. || window.webkitRequestAnimationFrame
  8495. || window.msRequestAnimationFrame
  8496. || function(callback) { setTimeout(callback, 0); },
  8497. returnedValue
  8498. ;
  8499. $allModules
  8500. .each(function() {
  8501. var
  8502. settings = ( $.isPlainObject(parameters) )
  8503. ? $.extend(true, {}, $.fn.modal.settings, parameters)
  8504. : $.extend({}, $.fn.modal.settings),
  8505. selector = settings.selector,
  8506. className = settings.className,
  8507. namespace = settings.namespace,
  8508. error = settings.error,
  8509. eventNamespace = '.' + namespace,
  8510. moduleNamespace = 'module-' + namespace,
  8511. $module = $(this),
  8512. $context = $(settings.context),
  8513. $close = $module.find(selector.close),
  8514. $allModals,
  8515. $otherModals,
  8516. $focusedElement,
  8517. $dimmable,
  8518. $dimmer,
  8519. element = this,
  8520. instance = $module.data(moduleNamespace),
  8521. ignoreRepeatedEvents = false,
  8522. elementEventNamespace,
  8523. id,
  8524. observer,
  8525. module
  8526. ;
  8527. module = {
  8528. initialize: function() {
  8529. module.verbose('Initializing dimmer', $context);
  8530. module.create.id();
  8531. module.create.dimmer();
  8532. module.refreshModals();
  8533. module.bind.events();
  8534. if(settings.observeChanges) {
  8535. module.observeChanges();
  8536. }
  8537. module.instantiate();
  8538. },
  8539. instantiate: function() {
  8540. module.verbose('Storing instance of modal');
  8541. instance = module;
  8542. $module
  8543. .data(moduleNamespace, instance)
  8544. ;
  8545. },
  8546. create: {
  8547. dimmer: function() {
  8548. var
  8549. defaultSettings = {
  8550. debug : settings.debug,
  8551. variation : settings.centered
  8552. ? false
  8553. : 'top aligned'
  8554. ,
  8555. dimmerName : 'modals'
  8556. },
  8557. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  8558. ;
  8559. if($.fn.dimmer === undefined) {
  8560. module.error(error.dimmer);
  8561. return;
  8562. }
  8563. module.debug('Creating dimmer');
  8564. $dimmable = $context.dimmer(dimmerSettings);
  8565. if(settings.detachable) {
  8566. module.verbose('Modal is detachable, moving content into dimmer');
  8567. $dimmable.dimmer('add content', $module);
  8568. }
  8569. else {
  8570. module.set.undetached();
  8571. }
  8572. $dimmer = $dimmable.dimmer('get dimmer');
  8573. },
  8574. id: function() {
  8575. id = (Math.random().toString(16) + '000000000').substr(2,8);
  8576. elementEventNamespace = '.' + id;
  8577. module.verbose('Creating unique id for element', id);
  8578. }
  8579. },
  8580. destroy: function() {
  8581. module.verbose('Destroying previous modal');
  8582. $module
  8583. .removeData(moduleNamespace)
  8584. .off(eventNamespace)
  8585. ;
  8586. $window.off(elementEventNamespace);
  8587. $dimmer.off(elementEventNamespace);
  8588. $close.off(eventNamespace);
  8589. $context.dimmer('destroy');
  8590. },
  8591. observeChanges: function() {
  8592. if('MutationObserver' in window) {
  8593. observer = new MutationObserver(function(mutations) {
  8594. module.debug('DOM tree modified, refreshing');
  8595. module.refresh();
  8596. });
  8597. observer.observe(element, {
  8598. childList : true,
  8599. subtree : true
  8600. });
  8601. module.debug('Setting up mutation observer', observer);
  8602. }
  8603. },
  8604. refresh: function() {
  8605. module.remove.scrolling();
  8606. module.cacheSizes();
  8607. module.set.screenHeight();
  8608. module.set.type();
  8609. },
  8610. refreshModals: function() {
  8611. $otherModals = $module.siblings(selector.modal);
  8612. $allModals = $otherModals.add($module);
  8613. },
  8614. attachEvents: function(selector, event) {
  8615. var
  8616. $toggle = $(selector)
  8617. ;
  8618. event = $.isFunction(module[event])
  8619. ? module[event]
  8620. : module.toggle
  8621. ;
  8622. if($toggle.length > 0) {
  8623. module.debug('Attaching modal events to element', selector, event);
  8624. $toggle
  8625. .off(eventNamespace)
  8626. .on('click' + eventNamespace, event)
  8627. ;
  8628. }
  8629. else {
  8630. module.error(error.notFound, selector);
  8631. }
  8632. },
  8633. bind: {
  8634. events: function() {
  8635. module.verbose('Attaching events');
  8636. $module
  8637. .on('click' + eventNamespace, selector.close, module.event.close)
  8638. .on('click' + eventNamespace, selector.approve, module.event.approve)
  8639. .on('click' + eventNamespace, selector.deny, module.event.deny)
  8640. ;
  8641. $window
  8642. .on('resize' + elementEventNamespace, module.event.resize)
  8643. ;
  8644. }
  8645. },
  8646. get: {
  8647. id: function() {
  8648. return (Math.random().toString(16) + '000000000').substr(2,8);
  8649. }
  8650. },
  8651. event: {
  8652. approve: function() {
  8653. if(ignoreRepeatedEvents || settings.onApprove.call(element, $(this)) === false) {
  8654. module.verbose('Approve callback returned false cancelling hide');
  8655. return;
  8656. }
  8657. ignoreRepeatedEvents = true;
  8658. module.hide(function() {
  8659. ignoreRepeatedEvents = false;
  8660. });
  8661. },
  8662. deny: function() {
  8663. if(ignoreRepeatedEvents || settings.onDeny.call(element, $(this)) === false) {
  8664. module.verbose('Deny callback returned false cancelling hide');
  8665. return;
  8666. }
  8667. ignoreRepeatedEvents = true;
  8668. module.hide(function() {
  8669. ignoreRepeatedEvents = false;
  8670. });
  8671. },
  8672. close: function() {
  8673. module.hide();
  8674. },
  8675. click: function(event) {
  8676. if(!settings.closable) {
  8677. module.verbose('Dimmer clicked but closable setting is disabled');
  8678. return;
  8679. }
  8680. var
  8681. $target = $(event.target),
  8682. isInModal = ($target.closest(selector.modal).length > 0),
  8683. isInDOM = $.contains(document.documentElement, event.target)
  8684. ;
  8685. if(!isInModal && isInDOM && module.is.active()) {
  8686. module.debug('Dimmer clicked, hiding all modals');
  8687. module.remove.clickaway();
  8688. if(settings.allowMultiple) {
  8689. module.hide();
  8690. }
  8691. else {
  8692. module.hideAll();
  8693. }
  8694. }
  8695. },
  8696. debounce: function(method, delay) {
  8697. clearTimeout(module.timer);
  8698. module.timer = setTimeout(method, delay);
  8699. },
  8700. keyboard: function(event) {
  8701. var
  8702. keyCode = event.which,
  8703. escapeKey = 27
  8704. ;
  8705. if(keyCode == escapeKey) {
  8706. if(settings.closable) {
  8707. module.debug('Escape key pressed hiding modal');
  8708. module.hide();
  8709. }
  8710. else {
  8711. module.debug('Escape key pressed, but closable is set to false');
  8712. }
  8713. event.preventDefault();
  8714. }
  8715. },
  8716. resize: function() {
  8717. if( $dimmable.dimmer('is active') && ( module.is.animating() || module.is.active() ) ) {
  8718. requestAnimationFrame(module.refresh);
  8719. }
  8720. }
  8721. },
  8722. toggle: function() {
  8723. if( module.is.active() || module.is.animating() ) {
  8724. module.hide();
  8725. }
  8726. else {
  8727. module.show();
  8728. }
  8729. },
  8730. show: function(callback) {
  8731. callback = $.isFunction(callback)
  8732. ? callback
  8733. : function(){}
  8734. ;
  8735. module.refreshModals();
  8736. module.set.dimmerSettings();
  8737. module.showModal(callback);
  8738. },
  8739. hide: function(callback) {
  8740. callback = $.isFunction(callback)
  8741. ? callback
  8742. : function(){}
  8743. ;
  8744. module.refreshModals();
  8745. module.hideModal(callback);
  8746. },
  8747. showModal: function(callback) {
  8748. callback = $.isFunction(callback)
  8749. ? callback
  8750. : function(){}
  8751. ;
  8752. if( module.is.animating() || !module.is.active() ) {
  8753. module.showDimmer();
  8754. module.cacheSizes();
  8755. module.set.screenHeight();
  8756. module.set.type();
  8757. module.set.clickaway();
  8758. if( !settings.allowMultiple && module.others.active() ) {
  8759. module.hideOthers(module.showModal);
  8760. }
  8761. else {
  8762. if(settings.allowMultiple && settings.detachable) {
  8763. $module.detach().appendTo($dimmer);
  8764. }
  8765. settings.onShow.call(element);
  8766. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8767. module.debug('Showing modal with css animations');
  8768. $module
  8769. .transition({
  8770. debug : settings.debug,
  8771. animation : settings.transition + ' in',
  8772. queue : settings.queue,
  8773. duration : settings.duration,
  8774. useFailSafe : true,
  8775. onComplete : function() {
  8776. settings.onVisible.apply(element);
  8777. if(settings.keyboardShortcuts) {
  8778. module.add.keyboardShortcuts();
  8779. }
  8780. module.save.focus();
  8781. module.set.active();
  8782. if(settings.autofocus) {
  8783. module.set.autofocus();
  8784. }
  8785. callback();
  8786. }
  8787. })
  8788. ;
  8789. }
  8790. else {
  8791. module.error(error.noTransition);
  8792. }
  8793. }
  8794. }
  8795. else {
  8796. module.debug('Modal is already visible');
  8797. }
  8798. },
  8799. hideModal: function(callback, keepDimmed) {
  8800. callback = $.isFunction(callback)
  8801. ? callback
  8802. : function(){}
  8803. ;
  8804. module.debug('Hiding modal');
  8805. if(settings.onHide.call(element, $(this)) === false) {
  8806. module.verbose('Hide callback returned false cancelling hide');
  8807. return;
  8808. }
  8809. if( module.is.animating() || module.is.active() ) {
  8810. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8811. module.remove.active();
  8812. $module
  8813. .transition({
  8814. debug : settings.debug,
  8815. animation : settings.transition + ' out',
  8816. queue : settings.queue,
  8817. duration : settings.duration,
  8818. useFailSafe : true,
  8819. onStart : function() {
  8820. if(!module.others.active() && !keepDimmed) {
  8821. module.hideDimmer();
  8822. }
  8823. if(settings.keyboardShortcuts) {
  8824. module.remove.keyboardShortcuts();
  8825. }
  8826. },
  8827. onComplete : function() {
  8828. settings.onHidden.call(element);
  8829. module.restore.focus();
  8830. callback();
  8831. }
  8832. })
  8833. ;
  8834. }
  8835. else {
  8836. module.error(error.noTransition);
  8837. }
  8838. }
  8839. },
  8840. showDimmer: function() {
  8841. if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
  8842. module.debug('Showing dimmer');
  8843. $dimmable.dimmer('show');
  8844. }
  8845. else {
  8846. module.debug('Dimmer already visible');
  8847. }
  8848. },
  8849. hideDimmer: function() {
  8850. if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
  8851. $dimmable.dimmer('hide', function() {
  8852. module.remove.clickaway();
  8853. module.remove.screenHeight();
  8854. });
  8855. }
  8856. else {
  8857. module.debug('Dimmer is not visible cannot hide');
  8858. return;
  8859. }
  8860. },
  8861. hideAll: function(callback) {
  8862. var
  8863. $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
  8864. ;
  8865. callback = $.isFunction(callback)
  8866. ? callback
  8867. : function(){}
  8868. ;
  8869. if( $visibleModals.length > 0 ) {
  8870. module.debug('Hiding all visible modals');
  8871. module.hideDimmer();
  8872. $visibleModals
  8873. .modal('hide modal', callback)
  8874. ;
  8875. }
  8876. },
  8877. hideOthers: function(callback) {
  8878. var
  8879. $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
  8880. ;
  8881. callback = $.isFunction(callback)
  8882. ? callback
  8883. : function(){}
  8884. ;
  8885. if( $visibleModals.length > 0 ) {
  8886. module.debug('Hiding other modals', $otherModals);
  8887. $visibleModals
  8888. .modal('hide modal', callback, true)
  8889. ;
  8890. }
  8891. },
  8892. others: {
  8893. active: function() {
  8894. return ($otherModals.filter('.' + className.active).length > 0);
  8895. },
  8896. animating: function() {
  8897. return ($otherModals.filter('.' + className.animating).length > 0);
  8898. }
  8899. },
  8900. add: {
  8901. keyboardShortcuts: function() {
  8902. module.verbose('Adding keyboard shortcuts');
  8903. $document
  8904. .on('keyup' + eventNamespace, module.event.keyboard)
  8905. ;
  8906. }
  8907. },
  8908. save: {
  8909. focus: function() {
  8910. var
  8911. $activeElement = $(document.activeElement),
  8912. inCurrentModal = $activeElement.closest($module).length > 0
  8913. ;
  8914. if(!inCurrentModal) {
  8915. $focusedElement = $(document.activeElement).blur();
  8916. }
  8917. }
  8918. },
  8919. restore: {
  8920. focus: function() {
  8921. if($focusedElement && $focusedElement.length > 0) {
  8922. $focusedElement.focus();
  8923. }
  8924. }
  8925. },
  8926. remove: {
  8927. active: function() {
  8928. $module.removeClass(className.active);
  8929. },
  8930. clickaway: function() {
  8931. $dimmer
  8932. .off('click' + elementEventNamespace)
  8933. ;
  8934. },
  8935. bodyStyle: function() {
  8936. if($body.attr('style') === '') {
  8937. module.verbose('Removing style attribute');
  8938. $body.removeAttr('style');
  8939. }
  8940. },
  8941. screenHeight: function() {
  8942. module.debug('Removing page height');
  8943. $body
  8944. .css('height', '')
  8945. ;
  8946. },
  8947. keyboardShortcuts: function() {
  8948. module.verbose('Removing keyboard shortcuts');
  8949. $document
  8950. .off('keyup' + eventNamespace)
  8951. ;
  8952. },
  8953. scrolling: function() {
  8954. $dimmable.removeClass(className.scrolling);
  8955. $module.removeClass(className.scrolling);
  8956. }
  8957. },
  8958. cacheSizes: function() {
  8959. $module.addClass(className.loading);
  8960. var
  8961. scrollHeight = $module.prop('scrollHeight'),
  8962. modalHeight = $module.outerHeight()
  8963. ;
  8964. if(module.cache === undefined || modalHeight !== 0) {
  8965. module.cache = {
  8966. pageHeight : $(document).outerHeight(),
  8967. height : modalHeight + settings.offset,
  8968. scrollHeight : scrollHeight + settings.offset,
  8969. contextHeight : (settings.context == 'body')
  8970. ? $(window).height()
  8971. : $dimmable.height(),
  8972. };
  8973. module.cache.topOffset = -(module.cache.height / 2);
  8974. }
  8975. $module.removeClass(className.loading);
  8976. module.debug('Caching modal and container sizes', module.cache);
  8977. },
  8978. can: {
  8979. fit: function() {
  8980. var
  8981. contextHeight = module.cache.contextHeight,
  8982. verticalCenter = module.cache.contextHeight / 2,
  8983. topOffset = module.cache.topOffset,
  8984. scrollHeight = module.cache.scrollHeight,
  8985. height = module.cache.height,
  8986. paddingHeight = settings.padding,
  8987. startPosition = (verticalCenter + topOffset)
  8988. ;
  8989. return (scrollHeight > height)
  8990. ? (startPosition + scrollHeight + paddingHeight < contextHeight)
  8991. : (height + (paddingHeight * 2) < contextHeight)
  8992. ;
  8993. }
  8994. },
  8995. is: {
  8996. active: function() {
  8997. return $module.hasClass(className.active);
  8998. },
  8999. animating: function() {
  9000. return $module.transition('is supported')
  9001. ? $module.transition('is animating')
  9002. : $module.is(':visible')
  9003. ;
  9004. },
  9005. scrolling: function() {
  9006. return $dimmable.hasClass(className.scrolling);
  9007. },
  9008. modernBrowser: function() {
  9009. // appName for IE11 reports 'Netscape' can no longer use
  9010. return !(window.ActiveXObject || "ActiveXObject" in window);
  9011. }
  9012. },
  9013. set: {
  9014. autofocus: function() {
  9015. var
  9016. $inputs = $module.find('[tabindex], :input').filter(':visible'),
  9017. $autofocus = $inputs.filter('[autofocus]'),
  9018. $input = ($autofocus.length > 0)
  9019. ? $autofocus.first()
  9020. : $inputs.first()
  9021. ;
  9022. if($input.length > 0) {
  9023. $input.focus();
  9024. }
  9025. },
  9026. clickaway: function() {
  9027. $dimmer
  9028. .on('click' + elementEventNamespace, module.event.click)
  9029. ;
  9030. },
  9031. dimmerSettings: function() {
  9032. if($.fn.dimmer === undefined) {
  9033. module.error(error.dimmer);
  9034. return;
  9035. }
  9036. var
  9037. defaultSettings = {
  9038. debug : settings.debug,
  9039. dimmerName : 'modals',
  9040. closable : 'auto',
  9041. variation : settings.centered
  9042. ? false
  9043. : 'top aligned'
  9044. ,
  9045. duration : {
  9046. show : settings.duration,
  9047. hide : settings.duration
  9048. }
  9049. },
  9050. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  9051. ;
  9052. if(settings.inverted) {
  9053. dimmerSettings.variation = (dimmerSettings.variation !== undefined)
  9054. ? dimmerSettings.variation + ' inverted'
  9055. : 'inverted'
  9056. ;
  9057. $dimmer.addClass(className.inverted);
  9058. }
  9059. else {
  9060. $dimmer.removeClass(className.inverted);
  9061. }
  9062. if(settings.blurring) {
  9063. $dimmable.addClass(className.blurring);
  9064. }
  9065. else {
  9066. $dimmable.removeClass(className.blurring);
  9067. }
  9068. $context.dimmer('setting', dimmerSettings);
  9069. },
  9070. screenHeight: function() {
  9071. if( module.can.fit() ) {
  9072. $body.css('height', '');
  9073. }
  9074. else {
  9075. module.debug('Modal is taller than page content, resizing page height');
  9076. $body
  9077. .css('height', module.cache.height + (settings.padding * 2) )
  9078. ;
  9079. }
  9080. },
  9081. active: function() {
  9082. $module.addClass(className.active);
  9083. },
  9084. scrolling: function() {
  9085. $dimmable.addClass(className.scrolling);
  9086. $module.addClass(className.scrolling);
  9087. },
  9088. type: function() {
  9089. if(module.can.fit()) {
  9090. module.verbose('Modal fits on screen');
  9091. if(!module.others.active() && !module.others.animating()) {
  9092. module.remove.scrolling();
  9093. }
  9094. }
  9095. else {
  9096. module.verbose('Modal cannot fit on screen setting to scrolling');
  9097. module.set.scrolling();
  9098. }
  9099. },
  9100. undetached: function() {
  9101. $dimmable.addClass(className.undetached);
  9102. }
  9103. },
  9104. setting: function(name, value) {
  9105. module.debug('Changing setting', name, value);
  9106. if( $.isPlainObject(name) ) {
  9107. $.extend(true, settings, name);
  9108. }
  9109. else if(value !== undefined) {
  9110. if($.isPlainObject(settings[name])) {
  9111. $.extend(true, settings[name], value);
  9112. }
  9113. else {
  9114. settings[name] = value;
  9115. }
  9116. }
  9117. else {
  9118. return settings[name];
  9119. }
  9120. },
  9121. internal: function(name, value) {
  9122. if( $.isPlainObject(name) ) {
  9123. $.extend(true, module, name);
  9124. }
  9125. else if(value !== undefined) {
  9126. module[name] = value;
  9127. }
  9128. else {
  9129. return module[name];
  9130. }
  9131. },
  9132. debug: function() {
  9133. if(!settings.silent && settings.debug) {
  9134. if(settings.performance) {
  9135. module.performance.log(arguments);
  9136. }
  9137. else {
  9138. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9139. module.debug.apply(console, arguments);
  9140. }
  9141. }
  9142. },
  9143. verbose: function() {
  9144. if(!settings.silent && settings.verbose && settings.debug) {
  9145. if(settings.performance) {
  9146. module.performance.log(arguments);
  9147. }
  9148. else {
  9149. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9150. module.verbose.apply(console, arguments);
  9151. }
  9152. }
  9153. },
  9154. error: function() {
  9155. if(!settings.silent) {
  9156. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9157. module.error.apply(console, arguments);
  9158. }
  9159. },
  9160. performance: {
  9161. log: function(message) {
  9162. var
  9163. currentTime,
  9164. executionTime,
  9165. previousTime
  9166. ;
  9167. if(settings.performance) {
  9168. currentTime = new Date().getTime();
  9169. previousTime = time || currentTime;
  9170. executionTime = currentTime - previousTime;
  9171. time = currentTime;
  9172. performance.push({
  9173. 'Name' : message[0],
  9174. 'Arguments' : [].slice.call(message, 1) || '',
  9175. 'Element' : element,
  9176. 'Execution Time' : executionTime
  9177. });
  9178. }
  9179. clearTimeout(module.performance.timer);
  9180. module.performance.timer = setTimeout(module.performance.display, 500);
  9181. },
  9182. display: function() {
  9183. var
  9184. title = settings.name + ':',
  9185. totalTime = 0
  9186. ;
  9187. time = false;
  9188. clearTimeout(module.performance.timer);
  9189. $.each(performance, function(index, data) {
  9190. totalTime += data['Execution Time'];
  9191. });
  9192. title += ' ' + totalTime + 'ms';
  9193. if(moduleSelector) {
  9194. title += ' \'' + moduleSelector + '\'';
  9195. }
  9196. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9197. console.groupCollapsed(title);
  9198. if(console.table) {
  9199. console.table(performance);
  9200. }
  9201. else {
  9202. $.each(performance, function(index, data) {
  9203. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9204. });
  9205. }
  9206. console.groupEnd();
  9207. }
  9208. performance = [];
  9209. }
  9210. },
  9211. invoke: function(query, passedArguments, context) {
  9212. var
  9213. object = instance,
  9214. maxDepth,
  9215. found,
  9216. response
  9217. ;
  9218. passedArguments = passedArguments || queryArguments;
  9219. context = element || context;
  9220. if(typeof query == 'string' && object !== undefined) {
  9221. query = query.split(/[\. ]/);
  9222. maxDepth = query.length - 1;
  9223. $.each(query, function(depth, value) {
  9224. var camelCaseValue = (depth != maxDepth)
  9225. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9226. : query
  9227. ;
  9228. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9229. object = object[camelCaseValue];
  9230. }
  9231. else if( object[camelCaseValue] !== undefined ) {
  9232. found = object[camelCaseValue];
  9233. return false;
  9234. }
  9235. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9236. object = object[value];
  9237. }
  9238. else if( object[value] !== undefined ) {
  9239. found = object[value];
  9240. return false;
  9241. }
  9242. else {
  9243. return false;
  9244. }
  9245. });
  9246. }
  9247. if ( $.isFunction( found ) ) {
  9248. response = found.apply(context, passedArguments);
  9249. }
  9250. else if(found !== undefined) {
  9251. response = found;
  9252. }
  9253. if($.isArray(returnedValue)) {
  9254. returnedValue.push(response);
  9255. }
  9256. else if(returnedValue !== undefined) {
  9257. returnedValue = [returnedValue, response];
  9258. }
  9259. else if(response !== undefined) {
  9260. returnedValue = response;
  9261. }
  9262. return found;
  9263. }
  9264. };
  9265. if(methodInvoked) {
  9266. if(instance === undefined) {
  9267. module.initialize();
  9268. }
  9269. module.invoke(query);
  9270. }
  9271. else {
  9272. if(instance !== undefined) {
  9273. instance.invoke('destroy');
  9274. }
  9275. module.initialize();
  9276. }
  9277. })
  9278. ;
  9279. return (returnedValue !== undefined)
  9280. ? returnedValue
  9281. : this
  9282. ;
  9283. };
  9284. $.fn.modal.settings = {
  9285. name : 'Modal',
  9286. namespace : 'modal',
  9287. silent : false,
  9288. debug : false,
  9289. verbose : false,
  9290. performance : true,
  9291. observeChanges : false,
  9292. allowMultiple : false,
  9293. detachable : true,
  9294. closable : true,
  9295. autofocus : true,
  9296. inverted : false,
  9297. blurring : false,
  9298. centered : true,
  9299. dimmerSettings : {
  9300. closable : false,
  9301. useCSS : true
  9302. },
  9303. // whether to use keyboard shortcuts
  9304. keyboardShortcuts: true,
  9305. context : 'body',
  9306. queue : false,
  9307. duration : 500,
  9308. offset : 0,
  9309. transition : 'scale',
  9310. // padding with edge of page
  9311. padding : 50,
  9312. // called before show animation
  9313. onShow : function(){},
  9314. // called after show animation
  9315. onVisible : function(){},
  9316. // called before hide animation
  9317. onHide : function(){ return true; },
  9318. // called after hide animation
  9319. onHidden : function(){},
  9320. // called after approve selector match
  9321. onApprove : function(){ return true; },
  9322. // called after deny selector match
  9323. onDeny : function(){ return true; },
  9324. selector : {
  9325. close : '> .close',
  9326. approve : '.actions .positive, .actions .approve, .actions .ok',
  9327. deny : '.actions .negative, .actions .deny, .actions .cancel',
  9328. modal : '.ui.modal'
  9329. },
  9330. error : {
  9331. dimmer : 'UI Dimmer, a required component is not included in this page',
  9332. method : 'The method you called is not defined.',
  9333. notFound : 'The element you specified could not be found'
  9334. },
  9335. className : {
  9336. active : 'active',
  9337. animating : 'animating',
  9338. blurring : 'blurring',
  9339. inverted : 'inverted',
  9340. loading : 'loading',
  9341. scrolling : 'scrolling',
  9342. undetached : 'undetached'
  9343. }
  9344. };
  9345. })( jQuery, window, document );
  9346. /*!
  9347. * # Semantic UI 2.3.0 - Nag
  9348. * http://github.com/semantic-org/semantic-ui/
  9349. *
  9350. *
  9351. * Released under the MIT license
  9352. * http://opensource.org/licenses/MIT
  9353. *
  9354. */
  9355. ;(function ($, window, document, undefined) {
  9356. "use strict";
  9357. window = (typeof window != 'undefined' && window.Math == Math)
  9358. ? window
  9359. : (typeof self != 'undefined' && self.Math == Math)
  9360. ? self
  9361. : Function('return this')()
  9362. ;
  9363. $.fn.nag = function(parameters) {
  9364. var
  9365. $allModules = $(this),
  9366. moduleSelector = $allModules.selector || '',
  9367. time = new Date().getTime(),
  9368. performance = [],
  9369. query = arguments[0],
  9370. methodInvoked = (typeof query == 'string'),
  9371. queryArguments = [].slice.call(arguments, 1),
  9372. returnedValue
  9373. ;
  9374. $allModules
  9375. .each(function() {
  9376. var
  9377. settings = ( $.isPlainObject(parameters) )
  9378. ? $.extend(true, {}, $.fn.nag.settings, parameters)
  9379. : $.extend({}, $.fn.nag.settings),
  9380. className = settings.className,
  9381. selector = settings.selector,
  9382. error = settings.error,
  9383. namespace = settings.namespace,
  9384. eventNamespace = '.' + namespace,
  9385. moduleNamespace = namespace + '-module',
  9386. $module = $(this),
  9387. $close = $module.find(selector.close),
  9388. $context = (settings.context)
  9389. ? $(settings.context)
  9390. : $('body'),
  9391. element = this,
  9392. instance = $module.data(moduleNamespace),
  9393. moduleOffset,
  9394. moduleHeight,
  9395. contextWidth,
  9396. contextHeight,
  9397. contextOffset,
  9398. yOffset,
  9399. yPosition,
  9400. timer,
  9401. module,
  9402. requestAnimationFrame = window.requestAnimationFrame
  9403. || window.mozRequestAnimationFrame
  9404. || window.webkitRequestAnimationFrame
  9405. || window.msRequestAnimationFrame
  9406. || function(callback) { setTimeout(callback, 0); }
  9407. ;
  9408. module = {
  9409. initialize: function() {
  9410. module.verbose('Initializing element');
  9411. $module
  9412. .on('click' + eventNamespace, selector.close, module.dismiss)
  9413. .data(moduleNamespace, module)
  9414. ;
  9415. if(settings.detachable && $module.parent()[0] !== $context[0]) {
  9416. $module
  9417. .detach()
  9418. .prependTo($context)
  9419. ;
  9420. }
  9421. if(settings.displayTime > 0) {
  9422. setTimeout(module.hide, settings.displayTime);
  9423. }
  9424. module.show();
  9425. },
  9426. destroy: function() {
  9427. module.verbose('Destroying instance');
  9428. $module
  9429. .removeData(moduleNamespace)
  9430. .off(eventNamespace)
  9431. ;
  9432. },
  9433. show: function() {
  9434. if( module.should.show() && !$module.is(':visible') ) {
  9435. module.debug('Showing nag', settings.animation.show);
  9436. if(settings.animation.show == 'fade') {
  9437. $module
  9438. .fadeIn(settings.duration, settings.easing)
  9439. ;
  9440. }
  9441. else {
  9442. $module
  9443. .slideDown(settings.duration, settings.easing)
  9444. ;
  9445. }
  9446. }
  9447. },
  9448. hide: function() {
  9449. module.debug('Showing nag', settings.animation.hide);
  9450. if(settings.animation.show == 'fade') {
  9451. $module
  9452. .fadeIn(settings.duration, settings.easing)
  9453. ;
  9454. }
  9455. else {
  9456. $module
  9457. .slideUp(settings.duration, settings.easing)
  9458. ;
  9459. }
  9460. },
  9461. onHide: function() {
  9462. module.debug('Removing nag', settings.animation.hide);
  9463. $module.remove();
  9464. if (settings.onHide) {
  9465. settings.onHide();
  9466. }
  9467. },
  9468. dismiss: function(event) {
  9469. if(settings.storageMethod) {
  9470. module.storage.set(settings.key, settings.value);
  9471. }
  9472. module.hide();
  9473. event.stopImmediatePropagation();
  9474. event.preventDefault();
  9475. },
  9476. should: {
  9477. show: function() {
  9478. if(settings.persist) {
  9479. module.debug('Persistent nag is set, can show nag');
  9480. return true;
  9481. }
  9482. if( module.storage.get(settings.key) != settings.value.toString() ) {
  9483. module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
  9484. return true;
  9485. }
  9486. module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
  9487. return false;
  9488. }
  9489. },
  9490. get: {
  9491. storageOptions: function() {
  9492. var
  9493. options = {}
  9494. ;
  9495. if(settings.expires) {
  9496. options.expires = settings.expires;
  9497. }
  9498. if(settings.domain) {
  9499. options.domain = settings.domain;
  9500. }
  9501. if(settings.path) {
  9502. options.path = settings.path;
  9503. }
  9504. return options;
  9505. }
  9506. },
  9507. clear: function() {
  9508. module.storage.remove(settings.key);
  9509. },
  9510. storage: {
  9511. set: function(key, value) {
  9512. var
  9513. options = module.get.storageOptions()
  9514. ;
  9515. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9516. window.localStorage.setItem(key, value);
  9517. module.debug('Value stored using local storage', key, value);
  9518. }
  9519. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9520. window.sessionStorage.setItem(key, value);
  9521. module.debug('Value stored using session storage', key, value);
  9522. }
  9523. else if($.cookie !== undefined) {
  9524. $.cookie(key, value, options);
  9525. module.debug('Value stored using cookie', key, value, options);
  9526. }
  9527. else {
  9528. module.error(error.noCookieStorage);
  9529. return;
  9530. }
  9531. },
  9532. get: function(key, value) {
  9533. var
  9534. storedValue
  9535. ;
  9536. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9537. storedValue = window.localStorage.getItem(key);
  9538. }
  9539. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9540. storedValue = window.sessionStorage.getItem(key);
  9541. }
  9542. // get by cookie
  9543. else if($.cookie !== undefined) {
  9544. storedValue = $.cookie(key);
  9545. }
  9546. else {
  9547. module.error(error.noCookieStorage);
  9548. }
  9549. if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
  9550. storedValue = undefined;
  9551. }
  9552. return storedValue;
  9553. },
  9554. remove: function(key) {
  9555. var
  9556. options = module.get.storageOptions()
  9557. ;
  9558. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9559. window.localStorage.removeItem(key);
  9560. }
  9561. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9562. window.sessionStorage.removeItem(key);
  9563. }
  9564. // store by cookie
  9565. else if($.cookie !== undefined) {
  9566. $.removeCookie(key, options);
  9567. }
  9568. else {
  9569. module.error(error.noStorage);
  9570. }
  9571. }
  9572. },
  9573. setting: function(name, value) {
  9574. module.debug('Changing setting', name, value);
  9575. if( $.isPlainObject(name) ) {
  9576. $.extend(true, settings, name);
  9577. }
  9578. else if(value !== undefined) {
  9579. if($.isPlainObject(settings[name])) {
  9580. $.extend(true, settings[name], value);
  9581. }
  9582. else {
  9583. settings[name] = value;
  9584. }
  9585. }
  9586. else {
  9587. return settings[name];
  9588. }
  9589. },
  9590. internal: function(name, value) {
  9591. if( $.isPlainObject(name) ) {
  9592. $.extend(true, module, name);
  9593. }
  9594. else if(value !== undefined) {
  9595. module[name] = value;
  9596. }
  9597. else {
  9598. return module[name];
  9599. }
  9600. },
  9601. debug: function() {
  9602. if(!settings.silent && settings.debug) {
  9603. if(settings.performance) {
  9604. module.performance.log(arguments);
  9605. }
  9606. else {
  9607. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9608. module.debug.apply(console, arguments);
  9609. }
  9610. }
  9611. },
  9612. verbose: function() {
  9613. if(!settings.silent && settings.verbose && settings.debug) {
  9614. if(settings.performance) {
  9615. module.performance.log(arguments);
  9616. }
  9617. else {
  9618. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9619. module.verbose.apply(console, arguments);
  9620. }
  9621. }
  9622. },
  9623. error: function() {
  9624. if(!settings.silent) {
  9625. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9626. module.error.apply(console, arguments);
  9627. }
  9628. },
  9629. performance: {
  9630. log: function(message) {
  9631. var
  9632. currentTime,
  9633. executionTime,
  9634. previousTime
  9635. ;
  9636. if(settings.performance) {
  9637. currentTime = new Date().getTime();
  9638. previousTime = time || currentTime;
  9639. executionTime = currentTime - previousTime;
  9640. time = currentTime;
  9641. performance.push({
  9642. 'Name' : message[0],
  9643. 'Arguments' : [].slice.call(message, 1) || '',
  9644. 'Element' : element,
  9645. 'Execution Time' : executionTime
  9646. });
  9647. }
  9648. clearTimeout(module.performance.timer);
  9649. module.performance.timer = setTimeout(module.performance.display, 500);
  9650. },
  9651. display: function() {
  9652. var
  9653. title = settings.name + ':',
  9654. totalTime = 0
  9655. ;
  9656. time = false;
  9657. clearTimeout(module.performance.timer);
  9658. $.each(performance, function(index, data) {
  9659. totalTime += data['Execution Time'];
  9660. });
  9661. title += ' ' + totalTime + 'ms';
  9662. if(moduleSelector) {
  9663. title += ' \'' + moduleSelector + '\'';
  9664. }
  9665. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9666. console.groupCollapsed(title);
  9667. if(console.table) {
  9668. console.table(performance);
  9669. }
  9670. else {
  9671. $.each(performance, function(index, data) {
  9672. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9673. });
  9674. }
  9675. console.groupEnd();
  9676. }
  9677. performance = [];
  9678. }
  9679. },
  9680. invoke: function(query, passedArguments, context) {
  9681. var
  9682. object = instance,
  9683. maxDepth,
  9684. found,
  9685. response
  9686. ;
  9687. passedArguments = passedArguments || queryArguments;
  9688. context = element || context;
  9689. if(typeof query == 'string' && object !== undefined) {
  9690. query = query.split(/[\. ]/);
  9691. maxDepth = query.length - 1;
  9692. $.each(query, function(depth, value) {
  9693. var camelCaseValue = (depth != maxDepth)
  9694. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9695. : query
  9696. ;
  9697. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9698. object = object[camelCaseValue];
  9699. }
  9700. else if( object[camelCaseValue] !== undefined ) {
  9701. found = object[camelCaseValue];
  9702. return false;
  9703. }
  9704. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9705. object = object[value];
  9706. }
  9707. else if( object[value] !== undefined ) {
  9708. found = object[value];
  9709. return false;
  9710. }
  9711. else {
  9712. module.error(error.method, query);
  9713. return false;
  9714. }
  9715. });
  9716. }
  9717. if ( $.isFunction( found ) ) {
  9718. response = found.apply(context, passedArguments);
  9719. }
  9720. else if(found !== undefined) {
  9721. response = found;
  9722. }
  9723. if($.isArray(returnedValue)) {
  9724. returnedValue.push(response);
  9725. }
  9726. else if(returnedValue !== undefined) {
  9727. returnedValue = [returnedValue, response];
  9728. }
  9729. else if(response !== undefined) {
  9730. returnedValue = response;
  9731. }
  9732. return found;
  9733. }
  9734. };
  9735. if(methodInvoked) {
  9736. if(instance === undefined) {
  9737. module.initialize();
  9738. }
  9739. module.invoke(query);
  9740. }
  9741. else {
  9742. if(instance !== undefined) {
  9743. instance.invoke('destroy');
  9744. }
  9745. module.initialize();
  9746. }
  9747. })
  9748. ;
  9749. return (returnedValue !== undefined)
  9750. ? returnedValue
  9751. : this
  9752. ;
  9753. };
  9754. $.fn.nag.settings = {
  9755. name : 'Nag',
  9756. silent : false,
  9757. debug : false,
  9758. verbose : false,
  9759. performance : true,
  9760. namespace : 'Nag',
  9761. // allows cookie to be overridden
  9762. persist : false,
  9763. // set to zero to require manually dismissal, otherwise hides on its own
  9764. displayTime : 0,
  9765. animation : {
  9766. show : 'slide',
  9767. hide : 'slide'
  9768. },
  9769. context : false,
  9770. detachable : false,
  9771. expires : 30,
  9772. domain : false,
  9773. path : '/',
  9774. // type of storage to use
  9775. storageMethod : 'cookie',
  9776. // value to store in dismissed localstorage/cookie
  9777. key : 'nag',
  9778. value : 'dismiss',
  9779. error: {
  9780. noCookieStorage : '$.cookie is not included. A storage solution is required.',
  9781. noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
  9782. method : 'The method you called is not defined.'
  9783. },
  9784. className : {
  9785. bottom : 'bottom',
  9786. fixed : 'fixed'
  9787. },
  9788. selector : {
  9789. close : '.close.icon'
  9790. },
  9791. speed : 500,
  9792. easing : 'easeOutQuad',
  9793. onHide: function() {}
  9794. };
  9795. // Adds easing
  9796. $.extend( $.easing, {
  9797. easeOutQuad: function (x, t, b, c, d) {
  9798. return -c *(t/=d)*(t-2) + b;
  9799. }
  9800. });
  9801. })( jQuery, window, document );
  9802. /*!
  9803. * # Semantic UI 2.3.0 - Popup
  9804. * http://github.com/semantic-org/semantic-ui/
  9805. *
  9806. *
  9807. * Released under the MIT license
  9808. * http://opensource.org/licenses/MIT
  9809. *
  9810. */
  9811. ;(function ($, window, document, undefined) {
  9812. "use strict";
  9813. window = (typeof window != 'undefined' && window.Math == Math)
  9814. ? window
  9815. : (typeof self != 'undefined' && self.Math == Math)
  9816. ? self
  9817. : Function('return this')()
  9818. ;
  9819. $.fn.popup = function(parameters) {
  9820. var
  9821. $allModules = $(this),
  9822. $document = $(document),
  9823. $window = $(window),
  9824. $body = $('body'),
  9825. moduleSelector = $allModules.selector || '',
  9826. hasTouch = (true),
  9827. time = new Date().getTime(),
  9828. performance = [],
  9829. query = arguments[0],
  9830. methodInvoked = (typeof query == 'string'),
  9831. queryArguments = [].slice.call(arguments, 1),
  9832. returnedValue
  9833. ;
  9834. $allModules
  9835. .each(function() {
  9836. var
  9837. settings = ( $.isPlainObject(parameters) )
  9838. ? $.extend(true, {}, $.fn.popup.settings, parameters)
  9839. : $.extend({}, $.fn.popup.settings),
  9840. selector = settings.selector,
  9841. className = settings.className,
  9842. error = settings.error,
  9843. metadata = settings.metadata,
  9844. namespace = settings.namespace,
  9845. eventNamespace = '.' + settings.namespace,
  9846. moduleNamespace = 'module-' + namespace,
  9847. $module = $(this),
  9848. $context = $(settings.context),
  9849. $scrollContext = $(settings.scrollContext),
  9850. $boundary = $(settings.boundary),
  9851. $target = (settings.target)
  9852. ? $(settings.target)
  9853. : $module,
  9854. $popup,
  9855. $offsetParent,
  9856. searchDepth = 0,
  9857. triedPositions = false,
  9858. openedWithTouch = false,
  9859. element = this,
  9860. instance = $module.data(moduleNamespace),
  9861. documentObserver,
  9862. elementNamespace,
  9863. id,
  9864. module
  9865. ;
  9866. module = {
  9867. // binds events
  9868. initialize: function() {
  9869. module.debug('Initializing', $module);
  9870. module.createID();
  9871. module.bind.events();
  9872. if(!module.exists() && settings.preserve) {
  9873. module.create();
  9874. }
  9875. if(settings.observeChanges) {
  9876. module.observeChanges();
  9877. }
  9878. module.instantiate();
  9879. },
  9880. instantiate: function() {
  9881. module.verbose('Storing instance', module);
  9882. instance = module;
  9883. $module
  9884. .data(moduleNamespace, instance)
  9885. ;
  9886. },
  9887. observeChanges: function() {
  9888. if('MutationObserver' in window) {
  9889. documentObserver = new MutationObserver(module.event.documentChanged);
  9890. documentObserver.observe(document, {
  9891. childList : true,
  9892. subtree : true
  9893. });
  9894. module.debug('Setting up mutation observer', documentObserver);
  9895. }
  9896. },
  9897. refresh: function() {
  9898. if(settings.popup) {
  9899. $popup = $(settings.popup).eq(0);
  9900. }
  9901. else {
  9902. if(settings.inline) {
  9903. $popup = $target.nextAll(selector.popup).eq(0);
  9904. settings.popup = $popup;
  9905. }
  9906. }
  9907. if(settings.popup) {
  9908. $popup.addClass(className.loading);
  9909. $offsetParent = module.get.offsetParent();
  9910. $popup.removeClass(className.loading);
  9911. if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
  9912. module.debug('Moving popup to the same offset parent as target');
  9913. $popup
  9914. .detach()
  9915. .appendTo($offsetParent)
  9916. ;
  9917. }
  9918. }
  9919. else {
  9920. $offsetParent = (settings.inline)
  9921. ? module.get.offsetParent($target)
  9922. : module.has.popup()
  9923. ? module.get.offsetParent($popup)
  9924. : $body
  9925. ;
  9926. }
  9927. if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
  9928. module.debug('Setting page as offset parent');
  9929. $offsetParent = $body;
  9930. }
  9931. if( module.get.variation() ) {
  9932. module.set.variation();
  9933. }
  9934. },
  9935. reposition: function() {
  9936. module.refresh();
  9937. module.set.position();
  9938. },
  9939. destroy: function() {
  9940. module.debug('Destroying previous module');
  9941. if(documentObserver) {
  9942. documentObserver.disconnect();
  9943. }
  9944. // remove element only if was created dynamically
  9945. if($popup && !settings.preserve) {
  9946. module.removePopup();
  9947. }
  9948. // clear all timeouts
  9949. clearTimeout(module.hideTimer);
  9950. clearTimeout(module.showTimer);
  9951. // remove events
  9952. module.unbind.close();
  9953. module.unbind.events();
  9954. $module
  9955. .removeData(moduleNamespace)
  9956. ;
  9957. },
  9958. event: {
  9959. start: function(event) {
  9960. var
  9961. delay = ($.isPlainObject(settings.delay))
  9962. ? settings.delay.show
  9963. : settings.delay
  9964. ;
  9965. clearTimeout(module.hideTimer);
  9966. if(!openedWithTouch) {
  9967. module.showTimer = setTimeout(module.show, delay);
  9968. }
  9969. },
  9970. end: function() {
  9971. var
  9972. delay = ($.isPlainObject(settings.delay))
  9973. ? settings.delay.hide
  9974. : settings.delay
  9975. ;
  9976. clearTimeout(module.showTimer);
  9977. module.hideTimer = setTimeout(module.hide, delay);
  9978. },
  9979. touchstart: function(event) {
  9980. openedWithTouch = true;
  9981. module.show();
  9982. },
  9983. resize: function() {
  9984. if( module.is.visible() ) {
  9985. module.set.position();
  9986. }
  9987. },
  9988. documentChanged: function(mutations) {
  9989. [].forEach.call(mutations, function(mutation) {
  9990. if(mutation.removedNodes) {
  9991. [].forEach.call(mutation.removedNodes, function(node) {
  9992. if(node == element || $(node).find(element).length > 0) {
  9993. module.debug('Element removed from DOM, tearing down events');
  9994. module.destroy();
  9995. }
  9996. });
  9997. }
  9998. });
  9999. },
  10000. hideGracefully: function(event) {
  10001. var
  10002. $target = $(event.target),
  10003. isInDOM = $.contains(document.documentElement, event.target),
  10004. inPopup = ($target.closest(selector.popup).length > 0)
  10005. ;
  10006. // don't close on clicks inside popup
  10007. if(event && !inPopup && isInDOM) {
  10008. module.debug('Click occurred outside popup hiding popup');
  10009. module.hide();
  10010. }
  10011. else {
  10012. module.debug('Click was inside popup, keeping popup open');
  10013. }
  10014. }
  10015. },
  10016. // generates popup html from metadata
  10017. create: function() {
  10018. var
  10019. html = module.get.html(),
  10020. title = module.get.title(),
  10021. content = module.get.content()
  10022. ;
  10023. if(html || content || title) {
  10024. module.debug('Creating pop-up html');
  10025. if(!html) {
  10026. html = settings.templates.popup({
  10027. title : title,
  10028. content : content
  10029. });
  10030. }
  10031. $popup = $('<div/>')
  10032. .addClass(className.popup)
  10033. .data(metadata.activator, $module)
  10034. .html(html)
  10035. ;
  10036. if(settings.inline) {
  10037. module.verbose('Inserting popup element inline', $popup);
  10038. $popup
  10039. .insertAfter($module)
  10040. ;
  10041. }
  10042. else {
  10043. module.verbose('Appending popup element to body', $popup);
  10044. $popup
  10045. .appendTo( $context )
  10046. ;
  10047. }
  10048. module.refresh();
  10049. module.set.variation();
  10050. if(settings.hoverable) {
  10051. module.bind.popup();
  10052. }
  10053. settings.onCreate.call($popup, element);
  10054. }
  10055. else if($target.next(selector.popup).length !== 0) {
  10056. module.verbose('Pre-existing popup found');
  10057. settings.inline = true;
  10058. settings.popup = $target.next(selector.popup).data(metadata.activator, $module);
  10059. module.refresh();
  10060. if(settings.hoverable) {
  10061. module.bind.popup();
  10062. }
  10063. }
  10064. else if(settings.popup) {
  10065. $(settings.popup).data(metadata.activator, $module);
  10066. module.verbose('Used popup specified in settings');
  10067. module.refresh();
  10068. if(settings.hoverable) {
  10069. module.bind.popup();
  10070. }
  10071. }
  10072. else {
  10073. module.debug('No content specified skipping display', element);
  10074. }
  10075. },
  10076. createID: function() {
  10077. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  10078. elementNamespace = '.' + id;
  10079. module.verbose('Creating unique id for element', id);
  10080. },
  10081. // determines popup state
  10082. toggle: function() {
  10083. module.debug('Toggling pop-up');
  10084. if( module.is.hidden() ) {
  10085. module.debug('Popup is hidden, showing pop-up');
  10086. module.unbind.close();
  10087. module.show();
  10088. }
  10089. else {
  10090. module.debug('Popup is visible, hiding pop-up');
  10091. module.hide();
  10092. }
  10093. },
  10094. show: function(callback) {
  10095. callback = callback || function(){};
  10096. module.debug('Showing pop-up', settings.transition);
  10097. if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
  10098. if( !module.exists() ) {
  10099. module.create();
  10100. }
  10101. if(settings.onShow.call($popup, element) === false) {
  10102. module.debug('onShow callback returned false, cancelling popup animation');
  10103. return;
  10104. }
  10105. else if(!settings.preserve && !settings.popup) {
  10106. module.refresh();
  10107. }
  10108. if( $popup && module.set.position() ) {
  10109. module.save.conditions();
  10110. if(settings.exclusive) {
  10111. module.hideAll();
  10112. }
  10113. module.animate.show(callback);
  10114. }
  10115. }
  10116. },
  10117. hide: function(callback) {
  10118. callback = callback || function(){};
  10119. if( module.is.visible() || module.is.animating() ) {
  10120. if(settings.onHide.call($popup, element) === false) {
  10121. module.debug('onHide callback returned false, cancelling popup animation');
  10122. return;
  10123. }
  10124. module.remove.visible();
  10125. module.unbind.close();
  10126. module.restore.conditions();
  10127. module.animate.hide(callback);
  10128. }
  10129. },
  10130. hideAll: function() {
  10131. $(selector.popup)
  10132. .filter('.' + className.popupVisible)
  10133. .each(function() {
  10134. $(this)
  10135. .data(metadata.activator)
  10136. .popup('hide')
  10137. ;
  10138. })
  10139. ;
  10140. },
  10141. exists: function() {
  10142. if(!$popup) {
  10143. return false;
  10144. }
  10145. if(settings.inline || settings.popup) {
  10146. return ( module.has.popup() );
  10147. }
  10148. else {
  10149. return ( $popup.closest($context).length >= 1 )
  10150. ? true
  10151. : false
  10152. ;
  10153. }
  10154. },
  10155. removePopup: function() {
  10156. if( module.has.popup() && !settings.popup) {
  10157. module.debug('Removing popup', $popup);
  10158. $popup.remove();
  10159. $popup = undefined;
  10160. settings.onRemove.call($popup, element);
  10161. }
  10162. },
  10163. save: {
  10164. conditions: function() {
  10165. module.cache = {
  10166. title: $module.attr('title')
  10167. };
  10168. if (module.cache.title) {
  10169. $module.removeAttr('title');
  10170. }
  10171. module.verbose('Saving original attributes', module.cache.title);
  10172. }
  10173. },
  10174. restore: {
  10175. conditions: function() {
  10176. if(module.cache && module.cache.title) {
  10177. $module.attr('title', module.cache.title);
  10178. module.verbose('Restoring original attributes', module.cache.title);
  10179. }
  10180. return true;
  10181. }
  10182. },
  10183. supports: {
  10184. svg: function() {
  10185. return (typeof SVGGraphicsElement === 'undefined');
  10186. }
  10187. },
  10188. animate: {
  10189. show: function(callback) {
  10190. callback = $.isFunction(callback) ? callback : function(){};
  10191. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  10192. module.set.visible();
  10193. $popup
  10194. .transition({
  10195. animation : settings.transition + ' in',
  10196. queue : false,
  10197. debug : settings.debug,
  10198. verbose : settings.verbose,
  10199. duration : settings.duration,
  10200. onComplete : function() {
  10201. module.bind.close();
  10202. callback.call($popup, element);
  10203. settings.onVisible.call($popup, element);
  10204. }
  10205. })
  10206. ;
  10207. }
  10208. else {
  10209. module.error(error.noTransition);
  10210. }
  10211. },
  10212. hide: function(callback) {
  10213. callback = $.isFunction(callback) ? callback : function(){};
  10214. module.debug('Hiding pop-up');
  10215. if(settings.onHide.call($popup, element) === false) {
  10216. module.debug('onHide callback returned false, cancelling popup animation');
  10217. return;
  10218. }
  10219. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  10220. $popup
  10221. .transition({
  10222. animation : settings.transition + ' out',
  10223. queue : false,
  10224. duration : settings.duration,
  10225. debug : settings.debug,
  10226. verbose : settings.verbose,
  10227. onComplete : function() {
  10228. module.reset();
  10229. callback.call($popup, element);
  10230. settings.onHidden.call($popup, element);
  10231. }
  10232. })
  10233. ;
  10234. }
  10235. else {
  10236. module.error(error.noTransition);
  10237. }
  10238. }
  10239. },
  10240. change: {
  10241. content: function(html) {
  10242. $popup.html(html);
  10243. }
  10244. },
  10245. get: {
  10246. html: function() {
  10247. $module.removeData(metadata.html);
  10248. return $module.data(metadata.html) || settings.html;
  10249. },
  10250. title: function() {
  10251. $module.removeData(metadata.title);
  10252. return $module.data(metadata.title) || settings.title;
  10253. },
  10254. content: function() {
  10255. $module.removeData(metadata.content);
  10256. return $module.data(metadata.content) || settings.content || $module.attr('title');
  10257. },
  10258. variation: function() {
  10259. $module.removeData(metadata.variation);
  10260. return $module.data(metadata.variation) || settings.variation;
  10261. },
  10262. popup: function() {
  10263. return $popup;
  10264. },
  10265. popupOffset: function() {
  10266. return $popup.offset();
  10267. },
  10268. calculations: function() {
  10269. var
  10270. $popupOffsetParent = module.get.offsetParent($popup),
  10271. targetElement = $target[0],
  10272. isWindow = ($boundary[0] == window),
  10273. targetPosition = (settings.inline || (settings.popup && settings.movePopup))
  10274. ? $target.position()
  10275. : $target.offset(),
  10276. screenPosition = (isWindow)
  10277. ? { top: 0, left: 0 }
  10278. : $boundary.offset(),
  10279. calculations = {},
  10280. scroll = (isWindow)
  10281. ? { top: $window.scrollTop(), left: $window.scrollLeft() }
  10282. : { top: 0, left: 0},
  10283. screen
  10284. ;
  10285. calculations = {
  10286. // element which is launching popup
  10287. target : {
  10288. element : $target[0],
  10289. width : $target.outerWidth(),
  10290. height : $target.outerHeight(),
  10291. top : targetPosition.top,
  10292. left : targetPosition.left,
  10293. margin : {}
  10294. },
  10295. // popup itself
  10296. popup : {
  10297. width : $popup.outerWidth(),
  10298. height : $popup.outerHeight()
  10299. },
  10300. // offset container (or 3d context)
  10301. parent : {
  10302. width : $offsetParent.outerWidth(),
  10303. height : $offsetParent.outerHeight()
  10304. },
  10305. // screen boundaries
  10306. screen : {
  10307. top : screenPosition.top,
  10308. left : screenPosition.left,
  10309. scroll: {
  10310. top : scroll.top,
  10311. left : scroll.left
  10312. },
  10313. width : $boundary.width(),
  10314. height : $boundary.height()
  10315. }
  10316. };
  10317. // if popup offset context is not same as target, then adjust calculations
  10318. if($popupOffsetParent.get(0) !== $offsetParent.get(0)) {
  10319. var
  10320. popupOffset = $popupOffsetParent.offset()
  10321. ;
  10322. calculations.target.top -= popupOffset.top;
  10323. calculations.target.left -= popupOffset.left;
  10324. calculations.parent.width = $popupOffsetParent.outerWidth();
  10325. calculations.parent.height = $popupOffsetParent.outerHeight();
  10326. }
  10327. // add in container calcs if fluid
  10328. if( settings.setFluidWidth && module.is.fluid() ) {
  10329. calculations.container = {
  10330. width: $popup.parent().outerWidth()
  10331. };
  10332. calculations.popup.width = calculations.container.width;
  10333. }
  10334. // add in margins if inline
  10335. calculations.target.margin.top = (settings.inline)
  10336. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
  10337. : 0
  10338. ;
  10339. calculations.target.margin.left = (settings.inline)
  10340. ? module.is.rtl()
  10341. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
  10342. : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
  10343. : 0
  10344. ;
  10345. // calculate screen boundaries
  10346. screen = calculations.screen;
  10347. calculations.boundary = {
  10348. top : screen.top + screen.scroll.top,
  10349. bottom : screen.top + screen.scroll.top + screen.height,
  10350. left : screen.left + screen.scroll.left,
  10351. right : screen.left + screen.scroll.left + screen.width
  10352. };
  10353. return calculations;
  10354. },
  10355. id: function() {
  10356. return id;
  10357. },
  10358. startEvent: function() {
  10359. if(settings.on == 'hover') {
  10360. return 'mouseenter';
  10361. }
  10362. else if(settings.on == 'focus') {
  10363. return 'focus';
  10364. }
  10365. return false;
  10366. },
  10367. scrollEvent: function() {
  10368. return 'scroll';
  10369. },
  10370. endEvent: function() {
  10371. if(settings.on == 'hover') {
  10372. return 'mouseleave';
  10373. }
  10374. else if(settings.on == 'focus') {
  10375. return 'blur';
  10376. }
  10377. return false;
  10378. },
  10379. distanceFromBoundary: function(offset, calculations) {
  10380. var
  10381. distanceFromBoundary = {},
  10382. popup,
  10383. boundary
  10384. ;
  10385. calculations = calculations || module.get.calculations();
  10386. // shorthand
  10387. popup = calculations.popup;
  10388. boundary = calculations.boundary;
  10389. if(offset) {
  10390. distanceFromBoundary = {
  10391. top : (offset.top - boundary.top),
  10392. left : (offset.left - boundary.left),
  10393. right : (boundary.right - (offset.left + popup.width) ),
  10394. bottom : (boundary.bottom - (offset.top + popup.height) )
  10395. };
  10396. module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
  10397. }
  10398. return distanceFromBoundary;
  10399. },
  10400. offsetParent: function($element) {
  10401. var
  10402. element = ($element !== undefined)
  10403. ? $element[0]
  10404. : $target[0],
  10405. parentNode = element.parentNode,
  10406. $node = $(parentNode)
  10407. ;
  10408. if(parentNode) {
  10409. var
  10410. is2D = ($node.css('transform') === 'none'),
  10411. isStatic = ($node.css('position') === 'static'),
  10412. isBody = $node.is('body')
  10413. ;
  10414. while(parentNode && !isBody && isStatic && is2D) {
  10415. parentNode = parentNode.parentNode;
  10416. $node = $(parentNode);
  10417. is2D = ($node.css('transform') === 'none');
  10418. isStatic = ($node.css('position') === 'static');
  10419. isBody = $node.is('body');
  10420. }
  10421. }
  10422. return ($node && $node.length > 0)
  10423. ? $node
  10424. : $()
  10425. ;
  10426. },
  10427. positions: function() {
  10428. return {
  10429. 'top left' : false,
  10430. 'top center' : false,
  10431. 'top right' : false,
  10432. 'bottom left' : false,
  10433. 'bottom center' : false,
  10434. 'bottom right' : false,
  10435. 'left center' : false,
  10436. 'right center' : false
  10437. };
  10438. },
  10439. nextPosition: function(position) {
  10440. var
  10441. positions = position.split(' '),
  10442. verticalPosition = positions[0],
  10443. horizontalPosition = positions[1],
  10444. opposite = {
  10445. top : 'bottom',
  10446. bottom : 'top',
  10447. left : 'right',
  10448. right : 'left'
  10449. },
  10450. adjacent = {
  10451. left : 'center',
  10452. center : 'right',
  10453. right : 'left'
  10454. },
  10455. backup = {
  10456. 'top left' : 'top center',
  10457. 'top center' : 'top right',
  10458. 'top right' : 'right center',
  10459. 'right center' : 'bottom right',
  10460. 'bottom right' : 'bottom center',
  10461. 'bottom center' : 'bottom left',
  10462. 'bottom left' : 'left center',
  10463. 'left center' : 'top left'
  10464. },
  10465. adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
  10466. oppositeTried = false,
  10467. adjacentTried = false,
  10468. nextPosition = false
  10469. ;
  10470. if(!triedPositions) {
  10471. module.verbose('All available positions available');
  10472. triedPositions = module.get.positions();
  10473. }
  10474. module.debug('Recording last position tried', position);
  10475. triedPositions[position] = true;
  10476. if(settings.prefer === 'opposite') {
  10477. nextPosition = [opposite[verticalPosition], horizontalPosition];
  10478. nextPosition = nextPosition.join(' ');
  10479. oppositeTried = (triedPositions[nextPosition] === true);
  10480. module.debug('Trying opposite strategy', nextPosition);
  10481. }
  10482. if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
  10483. nextPosition = [verticalPosition, adjacent[horizontalPosition]];
  10484. nextPosition = nextPosition.join(' ');
  10485. adjacentTried = (triedPositions[nextPosition] === true);
  10486. module.debug('Trying adjacent strategy', nextPosition);
  10487. }
  10488. if(adjacentTried || oppositeTried) {
  10489. module.debug('Using backup position', nextPosition);
  10490. nextPosition = backup[position];
  10491. }
  10492. return nextPosition;
  10493. }
  10494. },
  10495. set: {
  10496. position: function(position, calculations) {
  10497. // exit conditions
  10498. if($target.length === 0 || $popup.length === 0) {
  10499. module.error(error.notFound);
  10500. return;
  10501. }
  10502. var
  10503. offset,
  10504. distanceAway,
  10505. target,
  10506. popup,
  10507. parent,
  10508. positioning,
  10509. popupOffset,
  10510. distanceFromBoundary
  10511. ;
  10512. calculations = calculations || module.get.calculations();
  10513. position = position || $module.data(metadata.position) || settings.position;
  10514. offset = $module.data(metadata.offset) || settings.offset;
  10515. distanceAway = settings.distanceAway;
  10516. // shorthand
  10517. target = calculations.target;
  10518. popup = calculations.popup;
  10519. parent = calculations.parent;
  10520. if(module.should.centerArrow(calculations)) {
  10521. module.verbose('Adjusting offset to center arrow on small target element');
  10522. if(position == 'top left' || position == 'bottom left') {
  10523. offset += (target.width / 2)
  10524. offset -= settings.arrowPixelsFromEdge;
  10525. }
  10526. if(position == 'top right' || position == 'bottom right') {
  10527. offset -= (target.width / 2)
  10528. offset += settings.arrowPixelsFromEdge;
  10529. }
  10530. }
  10531. if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) {
  10532. module.debug('Popup target is hidden, no action taken');
  10533. return false;
  10534. }
  10535. if(settings.inline) {
  10536. module.debug('Adding margin to calculation', target.margin);
  10537. if(position == 'left center' || position == 'right center') {
  10538. offset += target.margin.top;
  10539. distanceAway += -target.margin.left;
  10540. }
  10541. else if (position == 'top left' || position == 'top center' || position == 'top right') {
  10542. offset += target.margin.left;
  10543. distanceAway -= target.margin.top;
  10544. }
  10545. else {
  10546. offset += target.margin.left;
  10547. distanceAway += target.margin.top;
  10548. }
  10549. }
  10550. module.debug('Determining popup position from calculations', position, calculations);
  10551. if (module.is.rtl()) {
  10552. position = position.replace(/left|right/g, function (match) {
  10553. return (match == 'left')
  10554. ? 'right'
  10555. : 'left'
  10556. ;
  10557. });
  10558. module.debug('RTL: Popup position updated', position);
  10559. }
  10560. // if last attempt use specified last resort position
  10561. if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
  10562. position = settings.lastResort;
  10563. }
  10564. switch (position) {
  10565. case 'top left':
  10566. positioning = {
  10567. top : 'auto',
  10568. bottom : parent.height - target.top + distanceAway,
  10569. left : target.left + offset,
  10570. right : 'auto'
  10571. };
  10572. break;
  10573. case 'top center':
  10574. positioning = {
  10575. bottom : parent.height - target.top + distanceAway,
  10576. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  10577. top : 'auto',
  10578. right : 'auto'
  10579. };
  10580. break;
  10581. case 'top right':
  10582. positioning = {
  10583. bottom : parent.height - target.top + distanceAway,
  10584. right : parent.width - target.left - target.width - offset,
  10585. top : 'auto',
  10586. left : 'auto'
  10587. };
  10588. break;
  10589. case 'left center':
  10590. positioning = {
  10591. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  10592. right : parent.width - target.left + distanceAway,
  10593. left : 'auto',
  10594. bottom : 'auto'
  10595. };
  10596. break;
  10597. case 'right center':
  10598. positioning = {
  10599. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  10600. left : target.left + target.width + distanceAway,
  10601. bottom : 'auto',
  10602. right : 'auto'
  10603. };
  10604. break;
  10605. case 'bottom left':
  10606. positioning = {
  10607. top : target.top + target.height + distanceAway,
  10608. left : target.left + offset,
  10609. bottom : 'auto',
  10610. right : 'auto'
  10611. };
  10612. break;
  10613. case 'bottom center':
  10614. positioning = {
  10615. top : target.top + target.height + distanceAway,
  10616. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  10617. bottom : 'auto',
  10618. right : 'auto'
  10619. };
  10620. break;
  10621. case 'bottom right':
  10622. positioning = {
  10623. top : target.top + target.height + distanceAway,
  10624. right : parent.width - target.left - target.width - offset,
  10625. left : 'auto',
  10626. bottom : 'auto'
  10627. };
  10628. break;
  10629. }
  10630. if(positioning === undefined) {
  10631. module.error(error.invalidPosition, position);
  10632. }
  10633. module.debug('Calculated popup positioning values', positioning);
  10634. // tentatively place on stage
  10635. $popup
  10636. .css(positioning)
  10637. .removeClass(className.position)
  10638. .addClass(position)
  10639. .addClass(className.loading)
  10640. ;
  10641. popupOffset = module.get.popupOffset();
  10642. // see if any boundaries are surpassed with this tentative position
  10643. distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
  10644. if( module.is.offstage(distanceFromBoundary, position) ) {
  10645. module.debug('Position is outside viewport', position);
  10646. if(searchDepth < settings.maxSearchDepth) {
  10647. searchDepth++;
  10648. position = module.get.nextPosition(position);
  10649. module.debug('Trying new position', position);
  10650. return ($popup)
  10651. ? module.set.position(position, calculations)
  10652. : false
  10653. ;
  10654. }
  10655. else {
  10656. if(settings.lastResort) {
  10657. module.debug('No position found, showing with last position');
  10658. }
  10659. else {
  10660. module.debug('Popup could not find a position to display', $popup);
  10661. module.error(error.cannotPlace, element);
  10662. module.remove.attempts();
  10663. module.remove.loading();
  10664. module.reset();
  10665. settings.onUnplaceable.call($popup, element);
  10666. return false;
  10667. }
  10668. }
  10669. }
  10670. module.debug('Position is on stage', position);
  10671. module.remove.attempts();
  10672. module.remove.loading();
  10673. if( settings.setFluidWidth && module.is.fluid() ) {
  10674. module.set.fluidWidth(calculations);
  10675. }
  10676. return true;
  10677. },
  10678. fluidWidth: function(calculations) {
  10679. calculations = calculations || module.get.calculations();
  10680. module.debug('Automatically setting element width to parent width', calculations.parent.width);
  10681. $popup.css('width', calculations.container.width);
  10682. },
  10683. variation: function(variation) {
  10684. variation = variation || module.get.variation();
  10685. if(variation && module.has.popup() ) {
  10686. module.verbose('Adding variation to popup', variation);
  10687. $popup.addClass(variation);
  10688. }
  10689. },
  10690. visible: function() {
  10691. $module.addClass(className.visible);
  10692. }
  10693. },
  10694. remove: {
  10695. loading: function() {
  10696. $popup.removeClass(className.loading);
  10697. },
  10698. variation: function(variation) {
  10699. variation = variation || module.get.variation();
  10700. if(variation) {
  10701. module.verbose('Removing variation', variation);
  10702. $popup.removeClass(variation);
  10703. }
  10704. },
  10705. visible: function() {
  10706. $module.removeClass(className.visible);
  10707. },
  10708. attempts: function() {
  10709. module.verbose('Resetting all searched positions');
  10710. searchDepth = 0;
  10711. triedPositions = false;
  10712. }
  10713. },
  10714. bind: {
  10715. events: function() {
  10716. module.debug('Binding popup events to module');
  10717. if(settings.on == 'click') {
  10718. $module
  10719. .on('click' + eventNamespace, module.toggle)
  10720. ;
  10721. }
  10722. if(settings.on == 'hover' && hasTouch) {
  10723. $module
  10724. .on('touchstart' + eventNamespace, module.event.touchstart)
  10725. ;
  10726. }
  10727. if( module.get.startEvent() ) {
  10728. $module
  10729. .on(module.get.startEvent() + eventNamespace, module.event.start)
  10730. .on(module.get.endEvent() + eventNamespace, module.event.end)
  10731. ;
  10732. }
  10733. if(settings.target) {
  10734. module.debug('Target set to element', $target);
  10735. }
  10736. $window.on('resize' + elementNamespace, module.event.resize);
  10737. },
  10738. popup: function() {
  10739. module.verbose('Allowing hover events on popup to prevent closing');
  10740. if( $popup && module.has.popup() ) {
  10741. $popup
  10742. .on('mouseenter' + eventNamespace, module.event.start)
  10743. .on('mouseleave' + eventNamespace, module.event.end)
  10744. ;
  10745. }
  10746. },
  10747. close: function() {
  10748. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  10749. module.bind.closeOnScroll();
  10750. }
  10751. if(settings.on == 'hover' && openedWithTouch) {
  10752. module.bind.touchClose();
  10753. }
  10754. if(settings.on == 'click' && settings.closable) {
  10755. module.bind.clickaway();
  10756. }
  10757. },
  10758. closeOnScroll: function() {
  10759. module.verbose('Binding scroll close event to document');
  10760. $scrollContext
  10761. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  10762. ;
  10763. },
  10764. touchClose: function() {
  10765. module.verbose('Binding popup touchclose event to document');
  10766. $document
  10767. .on('touchstart' + elementNamespace, function(event) {
  10768. module.verbose('Touched away from popup');
  10769. module.event.hideGracefully.call(element, event);
  10770. })
  10771. ;
  10772. },
  10773. clickaway: function() {
  10774. module.verbose('Binding popup close event to document');
  10775. $document
  10776. .on('click' + elementNamespace, function(event) {
  10777. module.verbose('Clicked away from popup');
  10778. module.event.hideGracefully.call(element, event);
  10779. })
  10780. ;
  10781. }
  10782. },
  10783. unbind: {
  10784. events: function() {
  10785. $window
  10786. .off(elementNamespace)
  10787. ;
  10788. $module
  10789. .off(eventNamespace)
  10790. ;
  10791. },
  10792. close: function() {
  10793. $document
  10794. .off(elementNamespace)
  10795. ;
  10796. $scrollContext
  10797. .off(elementNamespace)
  10798. ;
  10799. },
  10800. },
  10801. has: {
  10802. popup: function() {
  10803. return ($popup && $popup.length > 0);
  10804. }
  10805. },
  10806. should: {
  10807. centerArrow: function(calculations) {
  10808. return !module.is.basic() && calculations.target.width <= (settings.arrowPixelsFromEdge * 2);
  10809. }
  10810. },
  10811. is: {
  10812. offstage: function(distanceFromBoundary, position) {
  10813. var
  10814. offstage = []
  10815. ;
  10816. // return boundaries that have been surpassed
  10817. $.each(distanceFromBoundary, function(direction, distance) {
  10818. if(distance < -settings.jitter) {
  10819. module.debug('Position exceeds allowable distance from edge', direction, distance, position);
  10820. offstage.push(direction);
  10821. }
  10822. });
  10823. if(offstage.length > 0) {
  10824. return true;
  10825. }
  10826. else {
  10827. return false;
  10828. }
  10829. },
  10830. svg: function(element) {
  10831. return module.supports.svg() && (element instanceof SVGGraphicsElement);
  10832. },
  10833. basic: function() {
  10834. return $module.hasClass(className.basic);
  10835. },
  10836. active: function() {
  10837. return $module.hasClass(className.active);
  10838. },
  10839. animating: function() {
  10840. return ($popup !== undefined && $popup.hasClass(className.animating) );
  10841. },
  10842. fluid: function() {
  10843. return ($popup !== undefined && $popup.hasClass(className.fluid));
  10844. },
  10845. visible: function() {
  10846. return ($popup !== undefined && $popup.hasClass(className.popupVisible));
  10847. },
  10848. dropdown: function() {
  10849. return $module.hasClass(className.dropdown);
  10850. },
  10851. hidden: function() {
  10852. return !module.is.visible();
  10853. },
  10854. rtl: function () {
  10855. return $module.css('direction') == 'rtl';
  10856. }
  10857. },
  10858. reset: function() {
  10859. module.remove.visible();
  10860. if(settings.preserve) {
  10861. if($.fn.transition !== undefined) {
  10862. $popup
  10863. .transition('remove transition')
  10864. ;
  10865. }
  10866. }
  10867. else {
  10868. module.removePopup();
  10869. }
  10870. },
  10871. setting: function(name, value) {
  10872. if( $.isPlainObject(name) ) {
  10873. $.extend(true, settings, name);
  10874. }
  10875. else if(value !== undefined) {
  10876. settings[name] = value;
  10877. }
  10878. else {
  10879. return settings[name];
  10880. }
  10881. },
  10882. internal: function(name, value) {
  10883. if( $.isPlainObject(name) ) {
  10884. $.extend(true, module, name);
  10885. }
  10886. else if(value !== undefined) {
  10887. module[name] = value;
  10888. }
  10889. else {
  10890. return module[name];
  10891. }
  10892. },
  10893. debug: function() {
  10894. if(!settings.silent && settings.debug) {
  10895. if(settings.performance) {
  10896. module.performance.log(arguments);
  10897. }
  10898. else {
  10899. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10900. module.debug.apply(console, arguments);
  10901. }
  10902. }
  10903. },
  10904. verbose: function() {
  10905. if(!settings.silent && settings.verbose && settings.debug) {
  10906. if(settings.performance) {
  10907. module.performance.log(arguments);
  10908. }
  10909. else {
  10910. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10911. module.verbose.apply(console, arguments);
  10912. }
  10913. }
  10914. },
  10915. error: function() {
  10916. if(!settings.silent) {
  10917. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  10918. module.error.apply(console, arguments);
  10919. }
  10920. },
  10921. performance: {
  10922. log: function(message) {
  10923. var
  10924. currentTime,
  10925. executionTime,
  10926. previousTime
  10927. ;
  10928. if(settings.performance) {
  10929. currentTime = new Date().getTime();
  10930. previousTime = time || currentTime;
  10931. executionTime = currentTime - previousTime;
  10932. time = currentTime;
  10933. performance.push({
  10934. 'Name' : message[0],
  10935. 'Arguments' : [].slice.call(message, 1) || '',
  10936. 'Element' : element,
  10937. 'Execution Time' : executionTime
  10938. });
  10939. }
  10940. clearTimeout(module.performance.timer);
  10941. module.performance.timer = setTimeout(module.performance.display, 500);
  10942. },
  10943. display: function() {
  10944. var
  10945. title = settings.name + ':',
  10946. totalTime = 0
  10947. ;
  10948. time = false;
  10949. clearTimeout(module.performance.timer);
  10950. $.each(performance, function(index, data) {
  10951. totalTime += data['Execution Time'];
  10952. });
  10953. title += ' ' + totalTime + 'ms';
  10954. if(moduleSelector) {
  10955. title += ' \'' + moduleSelector + '\'';
  10956. }
  10957. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  10958. console.groupCollapsed(title);
  10959. if(console.table) {
  10960. console.table(performance);
  10961. }
  10962. else {
  10963. $.each(performance, function(index, data) {
  10964. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  10965. });
  10966. }
  10967. console.groupEnd();
  10968. }
  10969. performance = [];
  10970. }
  10971. },
  10972. invoke: function(query, passedArguments, context) {
  10973. var
  10974. object = instance,
  10975. maxDepth,
  10976. found,
  10977. response
  10978. ;
  10979. passedArguments = passedArguments || queryArguments;
  10980. context = element || context;
  10981. if(typeof query == 'string' && object !== undefined) {
  10982. query = query.split(/[\. ]/);
  10983. maxDepth = query.length - 1;
  10984. $.each(query, function(depth, value) {
  10985. var camelCaseValue = (depth != maxDepth)
  10986. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  10987. : query
  10988. ;
  10989. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  10990. object = object[camelCaseValue];
  10991. }
  10992. else if( object[camelCaseValue] !== undefined ) {
  10993. found = object[camelCaseValue];
  10994. return false;
  10995. }
  10996. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  10997. object = object[value];
  10998. }
  10999. else if( object[value] !== undefined ) {
  11000. found = object[value];
  11001. return false;
  11002. }
  11003. else {
  11004. return false;
  11005. }
  11006. });
  11007. }
  11008. if ( $.isFunction( found ) ) {
  11009. response = found.apply(context, passedArguments);
  11010. }
  11011. else if(found !== undefined) {
  11012. response = found;
  11013. }
  11014. if($.isArray(returnedValue)) {
  11015. returnedValue.push(response);
  11016. }
  11017. else if(returnedValue !== undefined) {
  11018. returnedValue = [returnedValue, response];
  11019. }
  11020. else if(response !== undefined) {
  11021. returnedValue = response;
  11022. }
  11023. return found;
  11024. }
  11025. };
  11026. if(methodInvoked) {
  11027. if(instance === undefined) {
  11028. module.initialize();
  11029. }
  11030. module.invoke(query);
  11031. }
  11032. else {
  11033. if(instance !== undefined) {
  11034. instance.invoke('destroy');
  11035. }
  11036. module.initialize();
  11037. }
  11038. })
  11039. ;
  11040. return (returnedValue !== undefined)
  11041. ? returnedValue
  11042. : this
  11043. ;
  11044. };
  11045. $.fn.popup.settings = {
  11046. name : 'Popup',
  11047. // module settings
  11048. silent : false,
  11049. debug : false,
  11050. verbose : false,
  11051. performance : true,
  11052. namespace : 'popup',
  11053. // whether it should use dom mutation observers
  11054. observeChanges : true,
  11055. // callback only when element added to dom
  11056. onCreate : function(){},
  11057. // callback before element removed from dom
  11058. onRemove : function(){},
  11059. // callback before show animation
  11060. onShow : function(){},
  11061. // callback after show animation
  11062. onVisible : function(){},
  11063. // callback before hide animation
  11064. onHide : function(){},
  11065. // callback when popup cannot be positioned in visible screen
  11066. onUnplaceable : function(){},
  11067. // callback after hide animation
  11068. onHidden : function(){},
  11069. // when to show popup
  11070. on : 'hover',
  11071. // element to use to determine if popup is out of boundary
  11072. boundary : window,
  11073. // whether to add touchstart events when using hover
  11074. addTouchEvents : true,
  11075. // default position relative to element
  11076. position : 'top left',
  11077. // name of variation to use
  11078. variation : '',
  11079. // whether popup should be moved to context
  11080. movePopup : true,
  11081. // element which popup should be relative to
  11082. target : false,
  11083. // jq selector or element that should be used as popup
  11084. popup : false,
  11085. // popup should remain inline next to activator
  11086. inline : false,
  11087. // popup should be removed from page on hide
  11088. preserve : false,
  11089. // popup should not close when being hovered on
  11090. hoverable : false,
  11091. // explicitly set content
  11092. content : false,
  11093. // explicitly set html
  11094. html : false,
  11095. // explicitly set title
  11096. title : false,
  11097. // whether automatically close on clickaway when on click
  11098. closable : true,
  11099. // automatically hide on scroll
  11100. hideOnScroll : 'auto',
  11101. // hide other popups on show
  11102. exclusive : false,
  11103. // context to attach popups
  11104. context : 'body',
  11105. // context for binding scroll events
  11106. scrollContext : window,
  11107. // position to prefer when calculating new position
  11108. prefer : 'opposite',
  11109. // specify position to appear even if it doesn't fit
  11110. lastResort : false,
  11111. // number of pixels from edge of popup to pointing arrow center (used from centering)
  11112. arrowPixelsFromEdge: 20,
  11113. // delay used to prevent accidental refiring of animations due to user error
  11114. delay : {
  11115. show : 50,
  11116. hide : 70
  11117. },
  11118. // whether fluid variation should assign width explicitly
  11119. setFluidWidth : true,
  11120. // transition settings
  11121. duration : 200,
  11122. transition : 'scale',
  11123. // distance away from activating element in px
  11124. distanceAway : 0,
  11125. // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
  11126. jitter : 2,
  11127. // offset on aligning axis from calculated position
  11128. offset : 0,
  11129. // maximum times to look for a position before failing (9 positions total)
  11130. maxSearchDepth : 15,
  11131. error: {
  11132. invalidPosition : 'The position you specified is not a valid position',
  11133. cannotPlace : 'Popup does not fit within the boundaries of the viewport',
  11134. method : 'The method you called is not defined.',
  11135. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  11136. notFound : 'The target or popup you specified does not exist on the page'
  11137. },
  11138. metadata: {
  11139. activator : 'activator',
  11140. content : 'content',
  11141. html : 'html',
  11142. offset : 'offset',
  11143. position : 'position',
  11144. title : 'title',
  11145. variation : 'variation'
  11146. },
  11147. className : {
  11148. active : 'active',
  11149. basic : 'basic',
  11150. animating : 'animating',
  11151. dropdown : 'dropdown',
  11152. fluid : 'fluid',
  11153. loading : 'loading',
  11154. popup : 'ui popup',
  11155. position : 'top left center bottom right',
  11156. visible : 'visible',
  11157. popupVisible : 'visible'
  11158. },
  11159. selector : {
  11160. popup : '.ui.popup'
  11161. },
  11162. templates: {
  11163. escape: function(string) {
  11164. var
  11165. badChars = /[&<>"'`]/g,
  11166. shouldEscape = /[&<>"'`]/,
  11167. escape = {
  11168. "&": "&amp;",
  11169. "<": "&lt;",
  11170. ">": "&gt;",
  11171. '"': "&quot;",
  11172. "'": "&#x27;",
  11173. "`": "&#x60;"
  11174. },
  11175. escapedChar = function(chr) {
  11176. return escape[chr];
  11177. }
  11178. ;
  11179. if(shouldEscape.test(string)) {
  11180. return string.replace(badChars, escapedChar);
  11181. }
  11182. return string;
  11183. },
  11184. popup: function(text) {
  11185. var
  11186. html = '',
  11187. escape = $.fn.popup.settings.templates.escape
  11188. ;
  11189. if(typeof text !== undefined) {
  11190. if(typeof text.title !== undefined && text.title) {
  11191. text.title = escape(text.title);
  11192. html += '<div class="header">' + text.title + '</div>';
  11193. }
  11194. if(typeof text.content !== undefined && text.content) {
  11195. text.content = escape(text.content);
  11196. html += '<div class="content">' + text.content + '</div>';
  11197. }
  11198. }
  11199. return html;
  11200. }
  11201. }
  11202. };
  11203. })( jQuery, window, document );
  11204. /*!
  11205. * # Semantic UI 2.3.0 - Progress
  11206. * http://github.com/semantic-org/semantic-ui/
  11207. *
  11208. *
  11209. * Released under the MIT license
  11210. * http://opensource.org/licenses/MIT
  11211. *
  11212. */
  11213. ;(function ($, window, document, undefined) {
  11214. "use strict";
  11215. window = (typeof window != 'undefined' && window.Math == Math)
  11216. ? window
  11217. : (typeof self != 'undefined' && self.Math == Math)
  11218. ? self
  11219. : Function('return this')()
  11220. ;
  11221. var
  11222. global = (typeof window != 'undefined' && window.Math == Math)
  11223. ? window
  11224. : (typeof self != 'undefined' && self.Math == Math)
  11225. ? self
  11226. : Function('return this')()
  11227. ;
  11228. $.fn.progress = function(parameters) {
  11229. var
  11230. $allModules = $(this),
  11231. moduleSelector = $allModules.selector || '',
  11232. time = new Date().getTime(),
  11233. performance = [],
  11234. query = arguments[0],
  11235. methodInvoked = (typeof query == 'string'),
  11236. queryArguments = [].slice.call(arguments, 1),
  11237. returnedValue
  11238. ;
  11239. $allModules
  11240. .each(function() {
  11241. var
  11242. settings = ( $.isPlainObject(parameters) )
  11243. ? $.extend(true, {}, $.fn.progress.settings, parameters)
  11244. : $.extend({}, $.fn.progress.settings),
  11245. className = settings.className,
  11246. metadata = settings.metadata,
  11247. namespace = settings.namespace,
  11248. selector = settings.selector,
  11249. error = settings.error,
  11250. eventNamespace = '.' + namespace,
  11251. moduleNamespace = 'module-' + namespace,
  11252. $module = $(this),
  11253. $bar = $(this).find(selector.bar),
  11254. $progress = $(this).find(selector.progress),
  11255. $label = $(this).find(selector.label),
  11256. element = this,
  11257. instance = $module.data(moduleNamespace),
  11258. animating = false,
  11259. transitionEnd,
  11260. module
  11261. ;
  11262. module = {
  11263. initialize: function() {
  11264. module.debug('Initializing progress bar', settings);
  11265. module.set.duration();
  11266. module.set.transitionEvent();
  11267. module.read.metadata();
  11268. module.read.settings();
  11269. module.instantiate();
  11270. },
  11271. instantiate: function() {
  11272. module.verbose('Storing instance of progress', module);
  11273. instance = module;
  11274. $module
  11275. .data(moduleNamespace, module)
  11276. ;
  11277. },
  11278. destroy: function() {
  11279. module.verbose('Destroying previous progress for', $module);
  11280. clearInterval(instance.interval);
  11281. module.remove.state();
  11282. $module.removeData(moduleNamespace);
  11283. instance = undefined;
  11284. },
  11285. reset: function() {
  11286. module.remove.nextValue();
  11287. module.update.progress(0);
  11288. },
  11289. complete: function() {
  11290. if(module.percent === undefined || module.percent < 100) {
  11291. module.remove.progressPoll();
  11292. module.set.percent(100);
  11293. }
  11294. },
  11295. read: {
  11296. metadata: function() {
  11297. var
  11298. data = {
  11299. percent : $module.data(metadata.percent),
  11300. total : $module.data(metadata.total),
  11301. value : $module.data(metadata.value)
  11302. }
  11303. ;
  11304. if(data.percent) {
  11305. module.debug('Current percent value set from metadata', data.percent);
  11306. module.set.percent(data.percent);
  11307. }
  11308. if(data.total) {
  11309. module.debug('Total value set from metadata', data.total);
  11310. module.set.total(data.total);
  11311. }
  11312. if(data.value) {
  11313. module.debug('Current value set from metadata', data.value);
  11314. module.set.value(data.value);
  11315. module.set.progress(data.value);
  11316. }
  11317. },
  11318. settings: function() {
  11319. if(settings.total !== false) {
  11320. module.debug('Current total set in settings', settings.total);
  11321. module.set.total(settings.total);
  11322. }
  11323. if(settings.value !== false) {
  11324. module.debug('Current value set in settings', settings.value);
  11325. module.set.value(settings.value);
  11326. module.set.progress(module.value);
  11327. }
  11328. if(settings.percent !== false) {
  11329. module.debug('Current percent set in settings', settings.percent);
  11330. module.set.percent(settings.percent);
  11331. }
  11332. }
  11333. },
  11334. bind: {
  11335. transitionEnd: function(callback) {
  11336. var
  11337. transitionEnd = module.get.transitionEnd()
  11338. ;
  11339. $bar
  11340. .one(transitionEnd + eventNamespace, function(event) {
  11341. clearTimeout(module.failSafeTimer);
  11342. callback.call(this, event);
  11343. })
  11344. ;
  11345. module.failSafeTimer = setTimeout(function() {
  11346. $bar.triggerHandler(transitionEnd);
  11347. }, settings.duration + settings.failSafeDelay);
  11348. module.verbose('Adding fail safe timer', module.timer);
  11349. }
  11350. },
  11351. increment: function(incrementValue) {
  11352. var
  11353. maxValue,
  11354. startValue,
  11355. newValue
  11356. ;
  11357. if( module.has.total() ) {
  11358. startValue = module.get.value();
  11359. incrementValue = incrementValue || 1;
  11360. newValue = startValue + incrementValue;
  11361. }
  11362. else {
  11363. startValue = module.get.percent();
  11364. incrementValue = incrementValue || module.get.randomValue();
  11365. newValue = startValue + incrementValue;
  11366. maxValue = 100;
  11367. module.debug('Incrementing percentage by', startValue, newValue);
  11368. }
  11369. newValue = module.get.normalizedValue(newValue);
  11370. module.set.progress(newValue);
  11371. },
  11372. decrement: function(decrementValue) {
  11373. var
  11374. total = module.get.total(),
  11375. startValue,
  11376. newValue
  11377. ;
  11378. if(total) {
  11379. startValue = module.get.value();
  11380. decrementValue = decrementValue || 1;
  11381. newValue = startValue - decrementValue;
  11382. module.debug('Decrementing value by', decrementValue, startValue);
  11383. }
  11384. else {
  11385. startValue = module.get.percent();
  11386. decrementValue = decrementValue || module.get.randomValue();
  11387. newValue = startValue - decrementValue;
  11388. module.debug('Decrementing percentage by', decrementValue, startValue);
  11389. }
  11390. newValue = module.get.normalizedValue(newValue);
  11391. module.set.progress(newValue);
  11392. },
  11393. has: {
  11394. progressPoll: function() {
  11395. return module.progressPoll;
  11396. },
  11397. total: function() {
  11398. return (module.get.total() !== false);
  11399. }
  11400. },
  11401. get: {
  11402. text: function(templateText) {
  11403. var
  11404. value = module.value || 0,
  11405. total = module.total || 0,
  11406. percent = (animating)
  11407. ? module.get.displayPercent()
  11408. : module.percent || 0,
  11409. left = (module.total > 0)
  11410. ? (total - value)
  11411. : (100 - percent)
  11412. ;
  11413. templateText = templateText || '';
  11414. templateText = templateText
  11415. .replace('{value}', value)
  11416. .replace('{total}', total)
  11417. .replace('{left}', left)
  11418. .replace('{percent}', percent)
  11419. ;
  11420. module.verbose('Adding variables to progress bar text', templateText);
  11421. return templateText;
  11422. },
  11423. normalizedValue: function(value) {
  11424. if(value < 0) {
  11425. module.debug('Value cannot decrement below 0');
  11426. return 0;
  11427. }
  11428. if(module.has.total()) {
  11429. if(value > module.total) {
  11430. module.debug('Value cannot increment above total', module.total);
  11431. return module.total;
  11432. }
  11433. }
  11434. else if(value > 100 ) {
  11435. module.debug('Value cannot increment above 100 percent');
  11436. return 100;
  11437. }
  11438. return value;
  11439. },
  11440. updateInterval: function() {
  11441. if(settings.updateInterval == 'auto') {
  11442. return settings.duration;
  11443. }
  11444. return settings.updateInterval;
  11445. },
  11446. randomValue: function() {
  11447. module.debug('Generating random increment percentage');
  11448. return Math.floor((Math.random() * settings.random.max) + settings.random.min);
  11449. },
  11450. numericValue: function(value) {
  11451. return (typeof value === 'string')
  11452. ? (value.replace(/[^\d.]/g, '') !== '')
  11453. ? +(value.replace(/[^\d.]/g, ''))
  11454. : false
  11455. : value
  11456. ;
  11457. },
  11458. transitionEnd: function() {
  11459. var
  11460. element = document.createElement('element'),
  11461. transitions = {
  11462. 'transition' :'transitionend',
  11463. 'OTransition' :'oTransitionEnd',
  11464. 'MozTransition' :'transitionend',
  11465. 'WebkitTransition' :'webkitTransitionEnd'
  11466. },
  11467. transition
  11468. ;
  11469. for(transition in transitions){
  11470. if( element.style[transition] !== undefined ){
  11471. return transitions[transition];
  11472. }
  11473. }
  11474. },
  11475. // gets current displayed percentage (if animating values this is the intermediary value)
  11476. displayPercent: function() {
  11477. var
  11478. barWidth = $bar.width(),
  11479. totalWidth = $module.width(),
  11480. minDisplay = parseInt($bar.css('min-width'), 10),
  11481. displayPercent = (barWidth > minDisplay)
  11482. ? (barWidth / totalWidth * 100)
  11483. : module.percent
  11484. ;
  11485. return (settings.precision > 0)
  11486. ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
  11487. : Math.round(displayPercent)
  11488. ;
  11489. },
  11490. percent: function() {
  11491. return module.percent || 0;
  11492. },
  11493. value: function() {
  11494. return module.nextValue || module.value || 0;
  11495. },
  11496. total: function() {
  11497. return module.total || false;
  11498. }
  11499. },
  11500. create: {
  11501. progressPoll: function() {
  11502. module.progressPoll = setTimeout(function() {
  11503. module.update.toNextValue();
  11504. module.remove.progressPoll();
  11505. }, module.get.updateInterval());
  11506. },
  11507. },
  11508. is: {
  11509. complete: function() {
  11510. return module.is.success() || module.is.warning() || module.is.error();
  11511. },
  11512. success: function() {
  11513. return $module.hasClass(className.success);
  11514. },
  11515. warning: function() {
  11516. return $module.hasClass(className.warning);
  11517. },
  11518. error: function() {
  11519. return $module.hasClass(className.error);
  11520. },
  11521. active: function() {
  11522. return $module.hasClass(className.active);
  11523. },
  11524. visible: function() {
  11525. return $module.is(':visible');
  11526. }
  11527. },
  11528. remove: {
  11529. progressPoll: function() {
  11530. module.verbose('Removing progress poll timer');
  11531. if(module.progressPoll) {
  11532. clearTimeout(module.progressPoll);
  11533. delete module.progressPoll;
  11534. }
  11535. },
  11536. nextValue: function() {
  11537. module.verbose('Removing progress value stored for next update');
  11538. delete module.nextValue;
  11539. },
  11540. state: function() {
  11541. module.verbose('Removing stored state');
  11542. delete module.total;
  11543. delete module.percent;
  11544. delete module.value;
  11545. },
  11546. active: function() {
  11547. module.verbose('Removing active state');
  11548. $module.removeClass(className.active);
  11549. },
  11550. success: function() {
  11551. module.verbose('Removing success state');
  11552. $module.removeClass(className.success);
  11553. },
  11554. warning: function() {
  11555. module.verbose('Removing warning state');
  11556. $module.removeClass(className.warning);
  11557. },
  11558. error: function() {
  11559. module.verbose('Removing error state');
  11560. $module.removeClass(className.error);
  11561. }
  11562. },
  11563. set: {
  11564. barWidth: function(value) {
  11565. if(value > 100) {
  11566. module.error(error.tooHigh, value);
  11567. }
  11568. else if (value < 0) {
  11569. module.error(error.tooLow, value);
  11570. }
  11571. else {
  11572. $bar
  11573. .css('width', value + '%')
  11574. ;
  11575. $module
  11576. .attr('data-percent', parseInt(value, 10))
  11577. ;
  11578. }
  11579. },
  11580. duration: function(duration) {
  11581. duration = duration || settings.duration;
  11582. duration = (typeof duration == 'number')
  11583. ? duration + 'ms'
  11584. : duration
  11585. ;
  11586. module.verbose('Setting progress bar transition duration', duration);
  11587. $bar
  11588. .css({
  11589. 'transition-duration': duration
  11590. })
  11591. ;
  11592. },
  11593. percent: function(percent) {
  11594. percent = (typeof percent == 'string')
  11595. ? +(percent.replace('%', ''))
  11596. : percent
  11597. ;
  11598. // round display percentage
  11599. percent = (settings.precision > 0)
  11600. ? Math.round(percent * (10 * settings.precision)) / (10 * settings.precision)
  11601. : Math.round(percent)
  11602. ;
  11603. module.percent = percent;
  11604. if( !module.has.total() ) {
  11605. module.value = (settings.precision > 0)
  11606. ? Math.round( (percent / 100) * module.total * (10 * settings.precision)) / (10 * settings.precision)
  11607. : Math.round( (percent / 100) * module.total * 10) / 10
  11608. ;
  11609. if(settings.limitValues) {
  11610. module.value = (module.value > 100)
  11611. ? 100
  11612. : (module.value < 0)
  11613. ? 0
  11614. : module.value
  11615. ;
  11616. }
  11617. }
  11618. module.set.barWidth(percent);
  11619. module.set.labelInterval();
  11620. module.set.labels();
  11621. settings.onChange.call(element, percent, module.value, module.total);
  11622. },
  11623. labelInterval: function() {
  11624. var
  11625. animationCallback = function() {
  11626. module.verbose('Bar finished animating, removing continuous label updates');
  11627. clearInterval(module.interval);
  11628. animating = false;
  11629. module.set.labels();
  11630. }
  11631. ;
  11632. clearInterval(module.interval);
  11633. module.bind.transitionEnd(animationCallback);
  11634. animating = true;
  11635. module.interval = setInterval(function() {
  11636. var
  11637. isInDOM = $.contains(document.documentElement, element)
  11638. ;
  11639. if(!isInDOM) {
  11640. clearInterval(module.interval);
  11641. animating = false;
  11642. }
  11643. module.set.labels();
  11644. }, settings.framerate);
  11645. },
  11646. labels: function() {
  11647. module.verbose('Setting both bar progress and outer label text');
  11648. module.set.barLabel();
  11649. module.set.state();
  11650. },
  11651. label: function(text) {
  11652. text = text || '';
  11653. if(text) {
  11654. text = module.get.text(text);
  11655. module.verbose('Setting label to text', text);
  11656. $label.text(text);
  11657. }
  11658. },
  11659. state: function(percent) {
  11660. percent = (percent !== undefined)
  11661. ? percent
  11662. : module.percent
  11663. ;
  11664. if(percent === 100) {
  11665. if(settings.autoSuccess && !(module.is.warning() || module.is.error() || module.is.success())) {
  11666. module.set.success();
  11667. module.debug('Automatically triggering success at 100%');
  11668. }
  11669. else {
  11670. module.verbose('Reached 100% removing active state');
  11671. module.remove.active();
  11672. module.remove.progressPoll();
  11673. }
  11674. }
  11675. else if(percent > 0) {
  11676. module.verbose('Adjusting active progress bar label', percent);
  11677. module.set.active();
  11678. }
  11679. else {
  11680. module.remove.active();
  11681. module.set.label(settings.text.active);
  11682. }
  11683. },
  11684. barLabel: function(text) {
  11685. if(text !== undefined) {
  11686. $progress.text( module.get.text(text) );
  11687. }
  11688. else if(settings.label == 'ratio' && module.total) {
  11689. module.verbose('Adding ratio to bar label');
  11690. $progress.text( module.get.text(settings.text.ratio) );
  11691. }
  11692. else if(settings.label == 'percent') {
  11693. module.verbose('Adding percentage to bar label');
  11694. $progress.text( module.get.text(settings.text.percent) );
  11695. }
  11696. },
  11697. active: function(text) {
  11698. text = text || settings.text.active;
  11699. module.debug('Setting active state');
  11700. if(settings.showActivity && !module.is.active() ) {
  11701. $module.addClass(className.active);
  11702. }
  11703. module.remove.warning();
  11704. module.remove.error();
  11705. module.remove.success();
  11706. text = settings.onLabelUpdate('active', text, module.value, module.total);
  11707. if(text) {
  11708. module.set.label(text);
  11709. }
  11710. module.bind.transitionEnd(function() {
  11711. settings.onActive.call(element, module.value, module.total);
  11712. });
  11713. },
  11714. success : function(text) {
  11715. text = text || settings.text.success || settings.text.active;
  11716. module.debug('Setting success state');
  11717. $module.addClass(className.success);
  11718. module.remove.active();
  11719. module.remove.warning();
  11720. module.remove.error();
  11721. module.complete();
  11722. if(settings.text.success) {
  11723. text = settings.onLabelUpdate('success', text, module.value, module.total);
  11724. module.set.label(text);
  11725. }
  11726. else {
  11727. text = settings.onLabelUpdate('active', text, module.value, module.total);
  11728. module.set.label(text);
  11729. }
  11730. module.bind.transitionEnd(function() {
  11731. settings.onSuccess.call(element, module.total);
  11732. });
  11733. },
  11734. warning : function(text) {
  11735. text = text || settings.text.warning;
  11736. module.debug('Setting warning state');
  11737. $module.addClass(className.warning);
  11738. module.remove.active();
  11739. module.remove.success();
  11740. module.remove.error();
  11741. module.complete();
  11742. text = settings.onLabelUpdate('warning', text, module.value, module.total);
  11743. if(text) {
  11744. module.set.label(text);
  11745. }
  11746. module.bind.transitionEnd(function() {
  11747. settings.onWarning.call(element, module.value, module.total);
  11748. });
  11749. },
  11750. error : function(text) {
  11751. text = text || settings.text.error;
  11752. module.debug('Setting error state');
  11753. $module.addClass(className.error);
  11754. module.remove.active();
  11755. module.remove.success();
  11756. module.remove.warning();
  11757. module.complete();
  11758. text = settings.onLabelUpdate('error', text, module.value, module.total);
  11759. if(text) {
  11760. module.set.label(text);
  11761. }
  11762. module.bind.transitionEnd(function() {
  11763. settings.onError.call(element, module.value, module.total);
  11764. });
  11765. },
  11766. transitionEvent: function() {
  11767. transitionEnd = module.get.transitionEnd();
  11768. },
  11769. total: function(totalValue) {
  11770. module.total = totalValue;
  11771. },
  11772. value: function(value) {
  11773. module.value = value;
  11774. },
  11775. progress: function(value) {
  11776. if(!module.has.progressPoll()) {
  11777. module.debug('First update in progress update interval, immediately updating', value);
  11778. module.update.progress(value);
  11779. module.create.progressPoll();
  11780. }
  11781. else {
  11782. module.debug('Updated within interval, setting next update to use new value', value);
  11783. module.set.nextValue(value);
  11784. }
  11785. },
  11786. nextValue: function(value) {
  11787. module.nextValue = value;
  11788. }
  11789. },
  11790. update: {
  11791. toNextValue: function() {
  11792. var
  11793. nextValue = module.nextValue
  11794. ;
  11795. if(nextValue) {
  11796. module.debug('Update interval complete using last updated value', nextValue);
  11797. module.update.progress(nextValue);
  11798. module.remove.nextValue();
  11799. }
  11800. },
  11801. progress: function(value) {
  11802. var
  11803. percentComplete
  11804. ;
  11805. value = module.get.numericValue(value);
  11806. if(value === false) {
  11807. module.error(error.nonNumeric, value);
  11808. }
  11809. value = module.get.normalizedValue(value);
  11810. if( module.has.total() ) {
  11811. module.set.value(value);
  11812. percentComplete = (value / module.total) * 100;
  11813. module.debug('Calculating percent complete from total', percentComplete);
  11814. module.set.percent( percentComplete );
  11815. }
  11816. else {
  11817. percentComplete = value;
  11818. module.debug('Setting value to exact percentage value', percentComplete);
  11819. module.set.percent( percentComplete );
  11820. }
  11821. }
  11822. },
  11823. setting: function(name, value) {
  11824. module.debug('Changing setting', name, value);
  11825. if( $.isPlainObject(name) ) {
  11826. $.extend(true, settings, name);
  11827. }
  11828. else if(value !== undefined) {
  11829. if($.isPlainObject(settings[name])) {
  11830. $.extend(true, settings[name], value);
  11831. }
  11832. else {
  11833. settings[name] = value;
  11834. }
  11835. }
  11836. else {
  11837. return settings[name];
  11838. }
  11839. },
  11840. internal: function(name, value) {
  11841. if( $.isPlainObject(name) ) {
  11842. $.extend(true, module, name);
  11843. }
  11844. else if(value !== undefined) {
  11845. module[name] = value;
  11846. }
  11847. else {
  11848. return module[name];
  11849. }
  11850. },
  11851. debug: function() {
  11852. if(!settings.silent && settings.debug) {
  11853. if(settings.performance) {
  11854. module.performance.log(arguments);
  11855. }
  11856. else {
  11857. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11858. module.debug.apply(console, arguments);
  11859. }
  11860. }
  11861. },
  11862. verbose: function() {
  11863. if(!settings.silent && settings.verbose && settings.debug) {
  11864. if(settings.performance) {
  11865. module.performance.log(arguments);
  11866. }
  11867. else {
  11868. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11869. module.verbose.apply(console, arguments);
  11870. }
  11871. }
  11872. },
  11873. error: function() {
  11874. if(!settings.silent) {
  11875. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  11876. module.error.apply(console, arguments);
  11877. }
  11878. },
  11879. performance: {
  11880. log: function(message) {
  11881. var
  11882. currentTime,
  11883. executionTime,
  11884. previousTime
  11885. ;
  11886. if(settings.performance) {
  11887. currentTime = new Date().getTime();
  11888. previousTime = time || currentTime;
  11889. executionTime = currentTime - previousTime;
  11890. time = currentTime;
  11891. performance.push({
  11892. 'Name' : message[0],
  11893. 'Arguments' : [].slice.call(message, 1) || '',
  11894. 'Element' : element,
  11895. 'Execution Time' : executionTime
  11896. });
  11897. }
  11898. clearTimeout(module.performance.timer);
  11899. module.performance.timer = setTimeout(module.performance.display, 500);
  11900. },
  11901. display: function() {
  11902. var
  11903. title = settings.name + ':',
  11904. totalTime = 0
  11905. ;
  11906. time = false;
  11907. clearTimeout(module.performance.timer);
  11908. $.each(performance, function(index, data) {
  11909. totalTime += data['Execution Time'];
  11910. });
  11911. title += ' ' + totalTime + 'ms';
  11912. if(moduleSelector) {
  11913. title += ' \'' + moduleSelector + '\'';
  11914. }
  11915. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  11916. console.groupCollapsed(title);
  11917. if(console.table) {
  11918. console.table(performance);
  11919. }
  11920. else {
  11921. $.each(performance, function(index, data) {
  11922. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  11923. });
  11924. }
  11925. console.groupEnd();
  11926. }
  11927. performance = [];
  11928. }
  11929. },
  11930. invoke: function(query, passedArguments, context) {
  11931. var
  11932. object = instance,
  11933. maxDepth,
  11934. found,
  11935. response
  11936. ;
  11937. passedArguments = passedArguments || queryArguments;
  11938. context = element || context;
  11939. if(typeof query == 'string' && object !== undefined) {
  11940. query = query.split(/[\. ]/);
  11941. maxDepth = query.length - 1;
  11942. $.each(query, function(depth, value) {
  11943. var camelCaseValue = (depth != maxDepth)
  11944. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  11945. : query
  11946. ;
  11947. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  11948. object = object[camelCaseValue];
  11949. }
  11950. else if( object[camelCaseValue] !== undefined ) {
  11951. found = object[camelCaseValue];
  11952. return false;
  11953. }
  11954. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  11955. object = object[value];
  11956. }
  11957. else if( object[value] !== undefined ) {
  11958. found = object[value];
  11959. return false;
  11960. }
  11961. else {
  11962. module.error(error.method, query);
  11963. return false;
  11964. }
  11965. });
  11966. }
  11967. if ( $.isFunction( found ) ) {
  11968. response = found.apply(context, passedArguments);
  11969. }
  11970. else if(found !== undefined) {
  11971. response = found;
  11972. }
  11973. if($.isArray(returnedValue)) {
  11974. returnedValue.push(response);
  11975. }
  11976. else if(returnedValue !== undefined) {
  11977. returnedValue = [returnedValue, response];
  11978. }
  11979. else if(response !== undefined) {
  11980. returnedValue = response;
  11981. }
  11982. return found;
  11983. }
  11984. };
  11985. if(methodInvoked) {
  11986. if(instance === undefined) {
  11987. module.initialize();
  11988. }
  11989. module.invoke(query);
  11990. }
  11991. else {
  11992. if(instance !== undefined) {
  11993. instance.invoke('destroy');
  11994. }
  11995. module.initialize();
  11996. }
  11997. })
  11998. ;
  11999. return (returnedValue !== undefined)
  12000. ? returnedValue
  12001. : this
  12002. ;
  12003. };
  12004. $.fn.progress.settings = {
  12005. name : 'Progress',
  12006. namespace : 'progress',
  12007. silent : false,
  12008. debug : false,
  12009. verbose : false,
  12010. performance : true,
  12011. random : {
  12012. min : 2,
  12013. max : 5
  12014. },
  12015. duration : 300,
  12016. updateInterval : 'auto',
  12017. autoSuccess : true,
  12018. showActivity : true,
  12019. limitValues : true,
  12020. label : 'percent',
  12021. precision : 0,
  12022. framerate : (1000 / 30), /// 30 fps
  12023. percent : false,
  12024. total : false,
  12025. value : false,
  12026. // delay in ms for fail safe animation callback
  12027. failSafeDelay : 100,
  12028. onLabelUpdate : function(state, text, value, total){
  12029. return text;
  12030. },
  12031. onChange : function(percent, value, total){},
  12032. onSuccess : function(total){},
  12033. onActive : function(value, total){},
  12034. onError : function(value, total){},
  12035. onWarning : function(value, total){},
  12036. error : {
  12037. method : 'The method you called is not defined.',
  12038. nonNumeric : 'Progress value is non numeric',
  12039. tooHigh : 'Value specified is above 100%',
  12040. tooLow : 'Value specified is below 0%'
  12041. },
  12042. regExp: {
  12043. variable: /\{\$*[A-z0-9]+\}/g
  12044. },
  12045. metadata: {
  12046. percent : 'percent',
  12047. total : 'total',
  12048. value : 'value'
  12049. },
  12050. selector : {
  12051. bar : '> .bar',
  12052. label : '> .label',
  12053. progress : '.bar > .progress'
  12054. },
  12055. text : {
  12056. active : false,
  12057. error : false,
  12058. success : false,
  12059. warning : false,
  12060. percent : '{percent}%',
  12061. ratio : '{value} of {total}'
  12062. },
  12063. className : {
  12064. active : 'active',
  12065. error : 'error',
  12066. success : 'success',
  12067. warning : 'warning'
  12068. }
  12069. };
  12070. })( jQuery, window, document );
  12071. /*!
  12072. * # Semantic UI 2.3.0 - Rating
  12073. * http://github.com/semantic-org/semantic-ui/
  12074. *
  12075. *
  12076. * Released under the MIT license
  12077. * http://opensource.org/licenses/MIT
  12078. *
  12079. */
  12080. ;(function ($, window, document, undefined) {
  12081. "use strict";
  12082. window = (typeof window != 'undefined' && window.Math == Math)
  12083. ? window
  12084. : (typeof self != 'undefined' && self.Math == Math)
  12085. ? self
  12086. : Function('return this')()
  12087. ;
  12088. $.fn.rating = function(parameters) {
  12089. var
  12090. $allModules = $(this),
  12091. moduleSelector = $allModules.selector || '',
  12092. time = new Date().getTime(),
  12093. performance = [],
  12094. query = arguments[0],
  12095. methodInvoked = (typeof query == 'string'),
  12096. queryArguments = [].slice.call(arguments, 1),
  12097. returnedValue
  12098. ;
  12099. $allModules
  12100. .each(function() {
  12101. var
  12102. settings = ( $.isPlainObject(parameters) )
  12103. ? $.extend(true, {}, $.fn.rating.settings, parameters)
  12104. : $.extend({}, $.fn.rating.settings),
  12105. namespace = settings.namespace,
  12106. className = settings.className,
  12107. metadata = settings.metadata,
  12108. selector = settings.selector,
  12109. error = settings.error,
  12110. eventNamespace = '.' + namespace,
  12111. moduleNamespace = 'module-' + namespace,
  12112. element = this,
  12113. instance = $(this).data(moduleNamespace),
  12114. $module = $(this),
  12115. $icon = $module.find(selector.icon),
  12116. initialLoad,
  12117. module
  12118. ;
  12119. module = {
  12120. initialize: function() {
  12121. module.verbose('Initializing rating module', settings);
  12122. if($icon.length === 0) {
  12123. module.setup.layout();
  12124. }
  12125. if(settings.interactive) {
  12126. module.enable();
  12127. }
  12128. else {
  12129. module.disable();
  12130. }
  12131. module.set.initialLoad();
  12132. module.set.rating( module.get.initialRating() );
  12133. module.remove.initialLoad();
  12134. module.instantiate();
  12135. },
  12136. instantiate: function() {
  12137. module.verbose('Instantiating module', settings);
  12138. instance = module;
  12139. $module
  12140. .data(moduleNamespace, module)
  12141. ;
  12142. },
  12143. destroy: function() {
  12144. module.verbose('Destroying previous instance', instance);
  12145. module.remove.events();
  12146. $module
  12147. .removeData(moduleNamespace)
  12148. ;
  12149. },
  12150. refresh: function() {
  12151. $icon = $module.find(selector.icon);
  12152. },
  12153. setup: {
  12154. layout: function() {
  12155. var
  12156. maxRating = module.get.maxRating(),
  12157. html = $.fn.rating.settings.templates.icon(maxRating)
  12158. ;
  12159. module.debug('Generating icon html dynamically');
  12160. $module
  12161. .html(html)
  12162. ;
  12163. module.refresh();
  12164. }
  12165. },
  12166. event: {
  12167. mouseenter: function() {
  12168. var
  12169. $activeIcon = $(this)
  12170. ;
  12171. $activeIcon
  12172. .nextAll()
  12173. .removeClass(className.selected)
  12174. ;
  12175. $module
  12176. .addClass(className.selected)
  12177. ;
  12178. $activeIcon
  12179. .addClass(className.selected)
  12180. .prevAll()
  12181. .addClass(className.selected)
  12182. ;
  12183. },
  12184. mouseleave: function() {
  12185. $module
  12186. .removeClass(className.selected)
  12187. ;
  12188. $icon
  12189. .removeClass(className.selected)
  12190. ;
  12191. },
  12192. click: function() {
  12193. var
  12194. $activeIcon = $(this),
  12195. currentRating = module.get.rating(),
  12196. rating = $icon.index($activeIcon) + 1,
  12197. canClear = (settings.clearable == 'auto')
  12198. ? ($icon.length === 1)
  12199. : settings.clearable
  12200. ;
  12201. if(canClear && currentRating == rating) {
  12202. module.clearRating();
  12203. }
  12204. else {
  12205. module.set.rating( rating );
  12206. }
  12207. }
  12208. },
  12209. clearRating: function() {
  12210. module.debug('Clearing current rating');
  12211. module.set.rating(0);
  12212. },
  12213. bind: {
  12214. events: function() {
  12215. module.verbose('Binding events');
  12216. $module
  12217. .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
  12218. .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
  12219. .on('click' + eventNamespace, selector.icon, module.event.click)
  12220. ;
  12221. }
  12222. },
  12223. remove: {
  12224. events: function() {
  12225. module.verbose('Removing events');
  12226. $module
  12227. .off(eventNamespace)
  12228. ;
  12229. },
  12230. initialLoad: function() {
  12231. initialLoad = false;
  12232. }
  12233. },
  12234. enable: function() {
  12235. module.debug('Setting rating to interactive mode');
  12236. module.bind.events();
  12237. $module
  12238. .removeClass(className.disabled)
  12239. ;
  12240. },
  12241. disable: function() {
  12242. module.debug('Setting rating to read-only mode');
  12243. module.remove.events();
  12244. $module
  12245. .addClass(className.disabled)
  12246. ;
  12247. },
  12248. is: {
  12249. initialLoad: function() {
  12250. return initialLoad;
  12251. }
  12252. },
  12253. get: {
  12254. initialRating: function() {
  12255. if($module.data(metadata.rating) !== undefined) {
  12256. $module.removeData(metadata.rating);
  12257. return $module.data(metadata.rating);
  12258. }
  12259. return settings.initialRating;
  12260. },
  12261. maxRating: function() {
  12262. if($module.data(metadata.maxRating) !== undefined) {
  12263. $module.removeData(metadata.maxRating);
  12264. return $module.data(metadata.maxRating);
  12265. }
  12266. return settings.maxRating;
  12267. },
  12268. rating: function() {
  12269. var
  12270. currentRating = $icon.filter('.' + className.active).length
  12271. ;
  12272. module.verbose('Current rating retrieved', currentRating);
  12273. return currentRating;
  12274. }
  12275. },
  12276. set: {
  12277. rating: function(rating) {
  12278. var
  12279. ratingIndex = (rating - 1 >= 0)
  12280. ? (rating - 1)
  12281. : 0,
  12282. $activeIcon = $icon.eq(ratingIndex)
  12283. ;
  12284. $module
  12285. .removeClass(className.selected)
  12286. ;
  12287. $icon
  12288. .removeClass(className.selected)
  12289. .removeClass(className.active)
  12290. ;
  12291. if(rating > 0) {
  12292. module.verbose('Setting current rating to', rating);
  12293. $activeIcon
  12294. .prevAll()
  12295. .addBack()
  12296. .addClass(className.active)
  12297. ;
  12298. }
  12299. if(!module.is.initialLoad()) {
  12300. settings.onRate.call(element, rating);
  12301. }
  12302. },
  12303. initialLoad: function() {
  12304. initialLoad = true;
  12305. }
  12306. },
  12307. setting: function(name, value) {
  12308. module.debug('Changing setting', name, value);
  12309. if( $.isPlainObject(name) ) {
  12310. $.extend(true, settings, name);
  12311. }
  12312. else if(value !== undefined) {
  12313. if($.isPlainObject(settings[name])) {
  12314. $.extend(true, settings[name], value);
  12315. }
  12316. else {
  12317. settings[name] = value;
  12318. }
  12319. }
  12320. else {
  12321. return settings[name];
  12322. }
  12323. },
  12324. internal: function(name, value) {
  12325. if( $.isPlainObject(name) ) {
  12326. $.extend(true, module, name);
  12327. }
  12328. else if(value !== undefined) {
  12329. module[name] = value;
  12330. }
  12331. else {
  12332. return module[name];
  12333. }
  12334. },
  12335. debug: function() {
  12336. if(!settings.silent && settings.debug) {
  12337. if(settings.performance) {
  12338. module.performance.log(arguments);
  12339. }
  12340. else {
  12341. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12342. module.debug.apply(console, arguments);
  12343. }
  12344. }
  12345. },
  12346. verbose: function() {
  12347. if(!settings.silent && settings.verbose && settings.debug) {
  12348. if(settings.performance) {
  12349. module.performance.log(arguments);
  12350. }
  12351. else {
  12352. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12353. module.verbose.apply(console, arguments);
  12354. }
  12355. }
  12356. },
  12357. error: function() {
  12358. if(!settings.silent) {
  12359. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  12360. module.error.apply(console, arguments);
  12361. }
  12362. },
  12363. performance: {
  12364. log: function(message) {
  12365. var
  12366. currentTime,
  12367. executionTime,
  12368. previousTime
  12369. ;
  12370. if(settings.performance) {
  12371. currentTime = new Date().getTime();
  12372. previousTime = time || currentTime;
  12373. executionTime = currentTime - previousTime;
  12374. time = currentTime;
  12375. performance.push({
  12376. 'Name' : message[0],
  12377. 'Arguments' : [].slice.call(message, 1) || '',
  12378. 'Element' : element,
  12379. 'Execution Time' : executionTime
  12380. });
  12381. }
  12382. clearTimeout(module.performance.timer);
  12383. module.performance.timer = setTimeout(module.performance.display, 500);
  12384. },
  12385. display: function() {
  12386. var
  12387. title = settings.name + ':',
  12388. totalTime = 0
  12389. ;
  12390. time = false;
  12391. clearTimeout(module.performance.timer);
  12392. $.each(performance, function(index, data) {
  12393. totalTime += data['Execution Time'];
  12394. });
  12395. title += ' ' + totalTime + 'ms';
  12396. if(moduleSelector) {
  12397. title += ' \'' + moduleSelector + '\'';
  12398. }
  12399. if($allModules.length > 1) {
  12400. title += ' ' + '(' + $allModules.length + ')';
  12401. }
  12402. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  12403. console.groupCollapsed(title);
  12404. if(console.table) {
  12405. console.table(performance);
  12406. }
  12407. else {
  12408. $.each(performance, function(index, data) {
  12409. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  12410. });
  12411. }
  12412. console.groupEnd();
  12413. }
  12414. performance = [];
  12415. }
  12416. },
  12417. invoke: function(query, passedArguments, context) {
  12418. var
  12419. object = instance,
  12420. maxDepth,
  12421. found,
  12422. response
  12423. ;
  12424. passedArguments = passedArguments || queryArguments;
  12425. context = element || context;
  12426. if(typeof query == 'string' && object !== undefined) {
  12427. query = query.split(/[\. ]/);
  12428. maxDepth = query.length - 1;
  12429. $.each(query, function(depth, value) {
  12430. var camelCaseValue = (depth != maxDepth)
  12431. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  12432. : query
  12433. ;
  12434. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  12435. object = object[camelCaseValue];
  12436. }
  12437. else if( object[camelCaseValue] !== undefined ) {
  12438. found = object[camelCaseValue];
  12439. return false;
  12440. }
  12441. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  12442. object = object[value];
  12443. }
  12444. else if( object[value] !== undefined ) {
  12445. found = object[value];
  12446. return false;
  12447. }
  12448. else {
  12449. return false;
  12450. }
  12451. });
  12452. }
  12453. if ( $.isFunction( found ) ) {
  12454. response = found.apply(context, passedArguments);
  12455. }
  12456. else if(found !== undefined) {
  12457. response = found;
  12458. }
  12459. if($.isArray(returnedValue)) {
  12460. returnedValue.push(response);
  12461. }
  12462. else if(returnedValue !== undefined) {
  12463. returnedValue = [returnedValue, response];
  12464. }
  12465. else if(response !== undefined) {
  12466. returnedValue = response;
  12467. }
  12468. return found;
  12469. }
  12470. };
  12471. if(methodInvoked) {
  12472. if(instance === undefined) {
  12473. module.initialize();
  12474. }
  12475. module.invoke(query);
  12476. }
  12477. else {
  12478. if(instance !== undefined) {
  12479. instance.invoke('destroy');
  12480. }
  12481. module.initialize();
  12482. }
  12483. })
  12484. ;
  12485. return (returnedValue !== undefined)
  12486. ? returnedValue
  12487. : this
  12488. ;
  12489. };
  12490. $.fn.rating.settings = {
  12491. name : 'Rating',
  12492. namespace : 'rating',
  12493. slent : false,
  12494. debug : false,
  12495. verbose : false,
  12496. performance : true,
  12497. initialRating : 0,
  12498. interactive : true,
  12499. maxRating : 4,
  12500. clearable : 'auto',
  12501. fireOnInit : false,
  12502. onRate : function(rating){},
  12503. error : {
  12504. method : 'The method you called is not defined',
  12505. noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
  12506. },
  12507. metadata: {
  12508. rating : 'rating',
  12509. maxRating : 'maxRating'
  12510. },
  12511. className : {
  12512. active : 'active',
  12513. disabled : 'disabled',
  12514. selected : 'selected',
  12515. loading : 'loading'
  12516. },
  12517. selector : {
  12518. icon : '.icon'
  12519. },
  12520. templates: {
  12521. icon: function(maxRating) {
  12522. var
  12523. icon = 1,
  12524. html = ''
  12525. ;
  12526. while(icon <= maxRating) {
  12527. html += '<i class="icon"></i>';
  12528. icon++;
  12529. }
  12530. return html;
  12531. }
  12532. }
  12533. };
  12534. })( jQuery, window, document );
  12535. /*!
  12536. * # Semantic UI 2.3.0 - Search
  12537. * http://github.com/semantic-org/semantic-ui/
  12538. *
  12539. *
  12540. * Released under the MIT license
  12541. * http://opensource.org/licenses/MIT
  12542. *
  12543. */
  12544. ;(function ($, window, document, undefined) {
  12545. "use strict";
  12546. window = (typeof window != 'undefined' && window.Math == Math)
  12547. ? window
  12548. : (typeof self != 'undefined' && self.Math == Math)
  12549. ? self
  12550. : Function('return this')()
  12551. ;
  12552. $.fn.search = function(parameters) {
  12553. var
  12554. $allModules = $(this),
  12555. moduleSelector = $allModules.selector || '',
  12556. time = new Date().getTime(),
  12557. performance = [],
  12558. query = arguments[0],
  12559. methodInvoked = (typeof query == 'string'),
  12560. queryArguments = [].slice.call(arguments, 1),
  12561. returnedValue
  12562. ;
  12563. $(this)
  12564. .each(function() {
  12565. var
  12566. settings = ( $.isPlainObject(parameters) )
  12567. ? $.extend(true, {}, $.fn.search.settings, parameters)
  12568. : $.extend({}, $.fn.search.settings),
  12569. className = settings.className,
  12570. metadata = settings.metadata,
  12571. regExp = settings.regExp,
  12572. fields = settings.fields,
  12573. selector = settings.selector,
  12574. error = settings.error,
  12575. namespace = settings.namespace,
  12576. eventNamespace = '.' + namespace,
  12577. moduleNamespace = namespace + '-module',
  12578. $module = $(this),
  12579. $prompt = $module.find(selector.prompt),
  12580. $searchButton = $module.find(selector.searchButton),
  12581. $results = $module.find(selector.results),
  12582. $result = $module.find(selector.result),
  12583. $category = $module.find(selector.category),
  12584. element = this,
  12585. instance = $module.data(moduleNamespace),
  12586. disabledBubbled = false,
  12587. resultsDismissed = false,
  12588. module
  12589. ;
  12590. module = {
  12591. initialize: function() {
  12592. module.verbose('Initializing module');
  12593. module.get.settings();
  12594. module.determine.searchFields();
  12595. module.bind.events();
  12596. module.set.type();
  12597. module.create.results();
  12598. module.instantiate();
  12599. },
  12600. instantiate: function() {
  12601. module.verbose('Storing instance of module', module);
  12602. instance = module;
  12603. $module
  12604. .data(moduleNamespace, module)
  12605. ;
  12606. },
  12607. destroy: function() {
  12608. module.verbose('Destroying instance');
  12609. $module
  12610. .off(eventNamespace)
  12611. .removeData(moduleNamespace)
  12612. ;
  12613. },
  12614. refresh: function() {
  12615. module.debug('Refreshing selector cache');
  12616. $prompt = $module.find(selector.prompt);
  12617. $searchButton = $module.find(selector.searchButton);
  12618. $category = $module.find(selector.category);
  12619. $results = $module.find(selector.results);
  12620. $result = $module.find(selector.result);
  12621. },
  12622. refreshResults: function() {
  12623. $results = $module.find(selector.results);
  12624. $result = $module.find(selector.result);
  12625. },
  12626. bind: {
  12627. events: function() {
  12628. module.verbose('Binding events to search');
  12629. if(settings.automatic) {
  12630. $module
  12631. .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
  12632. ;
  12633. $prompt
  12634. .attr('autocomplete', 'off')
  12635. ;
  12636. }
  12637. $module
  12638. // prompt
  12639. .on('focus' + eventNamespace, selector.prompt, module.event.focus)
  12640. .on('blur' + eventNamespace, selector.prompt, module.event.blur)
  12641. .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
  12642. // search button
  12643. .on('click' + eventNamespace, selector.searchButton, module.query)
  12644. // results
  12645. .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
  12646. .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
  12647. .on('click' + eventNamespace, selector.result, module.event.result.click)
  12648. ;
  12649. }
  12650. },
  12651. determine: {
  12652. searchFields: function() {
  12653. // this makes sure $.extend does not add specified search fields to default fields
  12654. // this is the only setting which should not extend defaults
  12655. if(parameters && parameters.searchFields !== undefined) {
  12656. settings.searchFields = parameters.searchFields;
  12657. }
  12658. }
  12659. },
  12660. event: {
  12661. input: function() {
  12662. if(settings.searchDelay) {
  12663. clearTimeout(module.timer);
  12664. module.timer = setTimeout(function() {
  12665. if(module.is.focused()) {
  12666. module.query();
  12667. }
  12668. }, settings.searchDelay);
  12669. }
  12670. else {
  12671. module.query();
  12672. }
  12673. },
  12674. focus: function() {
  12675. module.set.focus();
  12676. if(settings.searchOnFocus && module.has.minimumCharacters() ) {
  12677. module.query(function() {
  12678. if(module.can.show() ) {
  12679. module.showResults();
  12680. }
  12681. });
  12682. }
  12683. },
  12684. blur: function(event) {
  12685. var
  12686. pageLostFocus = (document.activeElement === this),
  12687. callback = function() {
  12688. module.cancel.query();
  12689. module.remove.focus();
  12690. module.timer = setTimeout(module.hideResults, settings.hideDelay);
  12691. }
  12692. ;
  12693. if(pageLostFocus) {
  12694. return;
  12695. }
  12696. resultsDismissed = false;
  12697. if(module.resultsClicked) {
  12698. module.debug('Determining if user action caused search to close');
  12699. $module
  12700. .one('click.close' + eventNamespace, selector.results, function(event) {
  12701. if(module.is.inMessage(event) || disabledBubbled) {
  12702. $prompt.focus();
  12703. return;
  12704. }
  12705. disabledBubbled = false;
  12706. if( !module.is.animating() && !module.is.hidden()) {
  12707. callback();
  12708. }
  12709. })
  12710. ;
  12711. }
  12712. else {
  12713. module.debug('Input blurred without user action, closing results');
  12714. callback();
  12715. }
  12716. },
  12717. result: {
  12718. mousedown: function() {
  12719. module.resultsClicked = true;
  12720. },
  12721. mouseup: function() {
  12722. module.resultsClicked = false;
  12723. },
  12724. click: function(event) {
  12725. module.debug('Search result selected');
  12726. var
  12727. $result = $(this),
  12728. $title = $result.find(selector.title).eq(0),
  12729. $link = $result.is('a[href]')
  12730. ? $result
  12731. : $result.find('a[href]').eq(0),
  12732. href = $link.attr('href') || false,
  12733. target = $link.attr('target') || false,
  12734. title = $title.html(),
  12735. // title is used for result lookup
  12736. value = ($title.length > 0)
  12737. ? $title.text()
  12738. : false,
  12739. results = module.get.results(),
  12740. result = $result.data(metadata.result) || module.get.result(value, results),
  12741. returnedValue
  12742. ;
  12743. if( $.isFunction(settings.onSelect) ) {
  12744. if(settings.onSelect.call(element, result, results) === false) {
  12745. module.debug('Custom onSelect callback cancelled default select action');
  12746. disabledBubbled = true;
  12747. return;
  12748. }
  12749. }
  12750. module.hideResults();
  12751. if(value) {
  12752. module.set.value(value);
  12753. }
  12754. if(href) {
  12755. module.verbose('Opening search link found in result', $link);
  12756. if(target == '_blank' || event.ctrlKey) {
  12757. window.open(href);
  12758. }
  12759. else {
  12760. window.location.href = (href);
  12761. }
  12762. }
  12763. }
  12764. }
  12765. },
  12766. handleKeyboard: function(event) {
  12767. var
  12768. // force selector refresh
  12769. $result = $module.find(selector.result),
  12770. $category = $module.find(selector.category),
  12771. $activeResult = $result.filter('.' + className.active),
  12772. currentIndex = $result.index( $activeResult ),
  12773. resultSize = $result.length,
  12774. hasActiveResult = $activeResult.length > 0,
  12775. keyCode = event.which,
  12776. keys = {
  12777. backspace : 8,
  12778. enter : 13,
  12779. escape : 27,
  12780. upArrow : 38,
  12781. downArrow : 40
  12782. },
  12783. newIndex
  12784. ;
  12785. // search shortcuts
  12786. if(keyCode == keys.escape) {
  12787. module.verbose('Escape key pressed, blurring search field');
  12788. module.hideResults();
  12789. resultsDismissed = true;
  12790. }
  12791. if( module.is.visible() ) {
  12792. if(keyCode == keys.enter) {
  12793. module.verbose('Enter key pressed, selecting active result');
  12794. if( $result.filter('.' + className.active).length > 0 ) {
  12795. module.event.result.click.call($result.filter('.' + className.active), event);
  12796. event.preventDefault();
  12797. return false;
  12798. }
  12799. }
  12800. else if(keyCode == keys.upArrow && hasActiveResult) {
  12801. module.verbose('Up key pressed, changing active result');
  12802. newIndex = (currentIndex - 1 < 0)
  12803. ? currentIndex
  12804. : currentIndex - 1
  12805. ;
  12806. $category
  12807. .removeClass(className.active)
  12808. ;
  12809. $result
  12810. .removeClass(className.active)
  12811. .eq(newIndex)
  12812. .addClass(className.active)
  12813. .closest($category)
  12814. .addClass(className.active)
  12815. ;
  12816. event.preventDefault();
  12817. }
  12818. else if(keyCode == keys.downArrow) {
  12819. module.verbose('Down key pressed, changing active result');
  12820. newIndex = (currentIndex + 1 >= resultSize)
  12821. ? currentIndex
  12822. : currentIndex + 1
  12823. ;
  12824. $category
  12825. .removeClass(className.active)
  12826. ;
  12827. $result
  12828. .removeClass(className.active)
  12829. .eq(newIndex)
  12830. .addClass(className.active)
  12831. .closest($category)
  12832. .addClass(className.active)
  12833. ;
  12834. event.preventDefault();
  12835. }
  12836. }
  12837. else {
  12838. // query shortcuts
  12839. if(keyCode == keys.enter) {
  12840. module.verbose('Enter key pressed, executing query');
  12841. module.query();
  12842. module.set.buttonPressed();
  12843. $prompt.one('keyup', module.remove.buttonFocus);
  12844. }
  12845. }
  12846. },
  12847. setup: {
  12848. api: function(searchTerm, callback) {
  12849. var
  12850. apiSettings = {
  12851. debug : settings.debug,
  12852. on : false,
  12853. cache : true,
  12854. action : 'search',
  12855. urlData : {
  12856. query : searchTerm
  12857. },
  12858. onSuccess : function(response) {
  12859. module.parse.response.call(element, response, searchTerm);
  12860. callback();
  12861. },
  12862. onFailure : function() {
  12863. module.displayMessage(error.serverError);
  12864. callback();
  12865. },
  12866. onAbort : function(response) {
  12867. },
  12868. onError : module.error
  12869. },
  12870. searchHTML
  12871. ;
  12872. $.extend(true, apiSettings, settings.apiSettings);
  12873. module.verbose('Setting up API request', apiSettings);
  12874. $module.api(apiSettings);
  12875. }
  12876. },
  12877. can: {
  12878. useAPI: function() {
  12879. return $.fn.api !== undefined;
  12880. },
  12881. show: function() {
  12882. return module.is.focused() && !module.is.visible() && !module.is.empty();
  12883. },
  12884. transition: function() {
  12885. return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
  12886. }
  12887. },
  12888. is: {
  12889. animating: function() {
  12890. return $results.hasClass(className.animating);
  12891. },
  12892. hidden: function() {
  12893. return $results.hasClass(className.hidden);
  12894. },
  12895. inMessage: function(event) {
  12896. if(!event.target) {
  12897. return;
  12898. }
  12899. var
  12900. $target = $(event.target),
  12901. isInDOM = $.contains(document.documentElement, event.target)
  12902. ;
  12903. return (isInDOM && $target.closest(selector.message).length > 0);
  12904. },
  12905. empty: function() {
  12906. return ($results.html() === '');
  12907. },
  12908. visible: function() {
  12909. return ($results.filter(':visible').length > 0);
  12910. },
  12911. focused: function() {
  12912. return ($prompt.filter(':focus').length > 0);
  12913. }
  12914. },
  12915. get: {
  12916. settings: function() {
  12917. if($.isPlainObject(parameters) && parameters.searchFullText) {
  12918. settings.fullTextSearch = parameters.searchFullText;
  12919. module.error(settings.error.oldSearchSyntax, element);
  12920. }
  12921. },
  12922. inputEvent: function() {
  12923. var
  12924. prompt = $prompt[0],
  12925. inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
  12926. ? 'input'
  12927. : (prompt !== undefined && prompt.onpropertychange !== undefined)
  12928. ? 'propertychange'
  12929. : 'keyup'
  12930. ;
  12931. return inputEvent;
  12932. },
  12933. value: function() {
  12934. return $prompt.val();
  12935. },
  12936. results: function() {
  12937. var
  12938. results = $module.data(metadata.results)
  12939. ;
  12940. return results;
  12941. },
  12942. result: function(value, results) {
  12943. var
  12944. lookupFields = ['title', 'id'],
  12945. result = false
  12946. ;
  12947. value = (value !== undefined)
  12948. ? value
  12949. : module.get.value()
  12950. ;
  12951. results = (results !== undefined)
  12952. ? results
  12953. : module.get.results()
  12954. ;
  12955. if(settings.type === 'category') {
  12956. module.debug('Finding result that matches', value);
  12957. $.each(results, function(index, category) {
  12958. if($.isArray(category.results)) {
  12959. result = module.search.object(value, category.results, lookupFields)[0];
  12960. // don't continue searching if a result is found
  12961. if(result) {
  12962. return false;
  12963. }
  12964. }
  12965. });
  12966. }
  12967. else {
  12968. module.debug('Finding result in results object', value);
  12969. result = module.search.object(value, results, lookupFields)[0];
  12970. }
  12971. return result || false;
  12972. },
  12973. },
  12974. select: {
  12975. firstResult: function() {
  12976. module.verbose('Selecting first result');
  12977. $result.first().addClass(className.active);
  12978. }
  12979. },
  12980. set: {
  12981. focus: function() {
  12982. $module.addClass(className.focus);
  12983. },
  12984. loading: function() {
  12985. $module.addClass(className.loading);
  12986. },
  12987. value: function(value) {
  12988. module.verbose('Setting search input value', value);
  12989. $prompt
  12990. .val(value)
  12991. ;
  12992. },
  12993. type: function(type) {
  12994. type = type || settings.type;
  12995. if(settings.type == 'category') {
  12996. $module.addClass(settings.type);
  12997. }
  12998. },
  12999. buttonPressed: function() {
  13000. $searchButton.addClass(className.pressed);
  13001. }
  13002. },
  13003. remove: {
  13004. loading: function() {
  13005. $module.removeClass(className.loading);
  13006. },
  13007. focus: function() {
  13008. $module.removeClass(className.focus);
  13009. },
  13010. buttonPressed: function() {
  13011. $searchButton.removeClass(className.pressed);
  13012. }
  13013. },
  13014. query: function(callback) {
  13015. callback = $.isFunction(callback)
  13016. ? callback
  13017. : function(){}
  13018. ;
  13019. var
  13020. searchTerm = module.get.value(),
  13021. cache = module.read.cache(searchTerm)
  13022. ;
  13023. callback = callback || function() {};
  13024. if( module.has.minimumCharacters() ) {
  13025. if(cache) {
  13026. module.debug('Reading result from cache', searchTerm);
  13027. module.save.results(cache.results);
  13028. module.addResults(cache.html);
  13029. module.inject.id(cache.results);
  13030. callback();
  13031. }
  13032. else {
  13033. module.debug('Querying for', searchTerm);
  13034. if($.isPlainObject(settings.source) || $.isArray(settings.source)) {
  13035. module.search.local(searchTerm);
  13036. callback();
  13037. }
  13038. else if( module.can.useAPI() ) {
  13039. module.search.remote(searchTerm, callback);
  13040. }
  13041. else {
  13042. module.error(error.source);
  13043. callback();
  13044. }
  13045. }
  13046. settings.onSearchQuery.call(element, searchTerm);
  13047. }
  13048. else {
  13049. module.hideResults();
  13050. }
  13051. },
  13052. search: {
  13053. local: function(searchTerm) {
  13054. var
  13055. results = module.search.object(searchTerm, settings.content),
  13056. searchHTML
  13057. ;
  13058. module.set.loading();
  13059. module.save.results(results);
  13060. module.debug('Returned full local search results', results);
  13061. if(settings.maxResults > 0) {
  13062. module.debug('Using specified max results', results);
  13063. results = results.slice(0, settings.maxResults);
  13064. }
  13065. if(settings.type == 'category') {
  13066. results = module.create.categoryResults(results);
  13067. }
  13068. searchHTML = module.generateResults({
  13069. results: results
  13070. });
  13071. module.remove.loading();
  13072. module.addResults(searchHTML);
  13073. module.inject.id(results);
  13074. module.write.cache(searchTerm, {
  13075. html : searchHTML,
  13076. results : results
  13077. });
  13078. },
  13079. remote: function(searchTerm, callback) {
  13080. callback = $.isFunction(callback)
  13081. ? callback
  13082. : function(){}
  13083. ;
  13084. if($module.api('is loading')) {
  13085. $module.api('abort');
  13086. }
  13087. module.setup.api(searchTerm, callback);
  13088. $module
  13089. .api('query')
  13090. ;
  13091. },
  13092. object: function(searchTerm, source, searchFields) {
  13093. var
  13094. results = [],
  13095. exactResults = [],
  13096. fuzzyResults = [],
  13097. searchExp = searchTerm.toString().replace(regExp.escape, '\\$&'),
  13098. matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
  13099. // avoid duplicates when pushing results
  13100. addResult = function(array, result) {
  13101. var
  13102. notResult = ($.inArray(result, results) == -1),
  13103. notFuzzyResult = ($.inArray(result, fuzzyResults) == -1)
  13104. ;
  13105. if(notResult && notFuzzyResult) {
  13106. array.push(result);
  13107. }
  13108. }
  13109. ;
  13110. source = source || settings.source;
  13111. searchFields = (searchFields !== undefined)
  13112. ? searchFields
  13113. : settings.searchFields
  13114. ;
  13115. // search fields should be array to loop correctly
  13116. if(!$.isArray(searchFields)) {
  13117. searchFields = [searchFields];
  13118. }
  13119. // exit conditions if no source
  13120. if(source === undefined || source === false) {
  13121. module.error(error.source);
  13122. return [];
  13123. }
  13124. // iterate through search fields looking for matches
  13125. $.each(searchFields, function(index, field) {
  13126. $.each(source, function(label, content) {
  13127. var
  13128. fieldExists = (typeof content[field] == 'string')
  13129. ;
  13130. if(fieldExists) {
  13131. if( content[field].search(matchRegExp) !== -1) {
  13132. // content starts with value (first in results)
  13133. addResult(results, content);
  13134. }
  13135. else if(settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, content[field]) ) {
  13136. // content fuzzy matches (last in results)
  13137. addResult(exactResults, content);
  13138. }
  13139. else if(settings.fullTextSearch == true && module.fuzzySearch(searchTerm, content[field]) ) {
  13140. // content fuzzy matches (last in results)
  13141. addResult(fuzzyResults, content);
  13142. }
  13143. }
  13144. });
  13145. });
  13146. $.merge(exactResults, fuzzyResults)
  13147. $.merge(results, exactResults);
  13148. return results;
  13149. }
  13150. },
  13151. exactSearch: function (query, term) {
  13152. query = query.toLowerCase();
  13153. term = term.toLowerCase();
  13154. if(term.indexOf(query) > -1) {
  13155. return true;
  13156. }
  13157. return false;
  13158. },
  13159. fuzzySearch: function(query, term) {
  13160. var
  13161. termLength = term.length,
  13162. queryLength = query.length
  13163. ;
  13164. if(typeof query !== 'string') {
  13165. return false;
  13166. }
  13167. query = query.toLowerCase();
  13168. term = term.toLowerCase();
  13169. if(queryLength > termLength) {
  13170. return false;
  13171. }
  13172. if(queryLength === termLength) {
  13173. return (query === term);
  13174. }
  13175. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  13176. var
  13177. queryCharacter = query.charCodeAt(characterIndex)
  13178. ;
  13179. while(nextCharacterIndex < termLength) {
  13180. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  13181. continue search;
  13182. }
  13183. }
  13184. return false;
  13185. }
  13186. return true;
  13187. },
  13188. parse: {
  13189. response: function(response, searchTerm) {
  13190. var
  13191. searchHTML = module.generateResults(response)
  13192. ;
  13193. module.verbose('Parsing server response', response);
  13194. if(response !== undefined) {
  13195. if(searchTerm !== undefined && response[fields.results] !== undefined) {
  13196. module.addResults(searchHTML);
  13197. module.inject.id(response[fields.results]);
  13198. module.write.cache(searchTerm, {
  13199. html : searchHTML,
  13200. results : response[fields.results]
  13201. });
  13202. module.save.results(response[fields.results]);
  13203. }
  13204. }
  13205. }
  13206. },
  13207. cancel: {
  13208. query: function() {
  13209. if( module.can.useAPI() ) {
  13210. $module.api('abort');
  13211. }
  13212. }
  13213. },
  13214. has: {
  13215. minimumCharacters: function() {
  13216. var
  13217. searchTerm = module.get.value(),
  13218. numCharacters = searchTerm.length
  13219. ;
  13220. return (numCharacters >= settings.minCharacters);
  13221. },
  13222. results: function() {
  13223. if($results.length === 0) {
  13224. return false;
  13225. }
  13226. var
  13227. html = $results.html()
  13228. ;
  13229. return html != '';
  13230. }
  13231. },
  13232. clear: {
  13233. cache: function(value) {
  13234. var
  13235. cache = $module.data(metadata.cache)
  13236. ;
  13237. if(!value) {
  13238. module.debug('Clearing cache', value);
  13239. $module.removeData(metadata.cache);
  13240. }
  13241. else if(value && cache && cache[value]) {
  13242. module.debug('Removing value from cache', value);
  13243. delete cache[value];
  13244. $module.data(metadata.cache, cache);
  13245. }
  13246. }
  13247. },
  13248. read: {
  13249. cache: function(name) {
  13250. var
  13251. cache = $module.data(metadata.cache)
  13252. ;
  13253. if(settings.cache) {
  13254. module.verbose('Checking cache for generated html for query', name);
  13255. return (typeof cache == 'object') && (cache[name] !== undefined)
  13256. ? cache[name]
  13257. : false
  13258. ;
  13259. }
  13260. return false;
  13261. }
  13262. },
  13263. create: {
  13264. categoryResults: function(results) {
  13265. var
  13266. categoryResults = {}
  13267. ;
  13268. $.each(results, function(index, result) {
  13269. if(!result.category) {
  13270. return;
  13271. }
  13272. if(categoryResults[result.category] === undefined) {
  13273. module.verbose('Creating new category of results', result.category);
  13274. categoryResults[result.category] = {
  13275. name : result.category,
  13276. results : [result]
  13277. }
  13278. }
  13279. else {
  13280. categoryResults[result.category].results.push(result);
  13281. }
  13282. });
  13283. return categoryResults;
  13284. },
  13285. id: function(resultIndex, categoryIndex) {
  13286. var
  13287. resultID = (resultIndex + 1), // not zero indexed
  13288. categoryID = (categoryIndex + 1),
  13289. firstCharCode,
  13290. letterID,
  13291. id
  13292. ;
  13293. if(categoryIndex !== undefined) {
  13294. // start char code for "A"
  13295. letterID = String.fromCharCode(97 + categoryIndex);
  13296. id = letterID + resultID;
  13297. module.verbose('Creating category result id', id);
  13298. }
  13299. else {
  13300. id = resultID;
  13301. module.verbose('Creating result id', id);
  13302. }
  13303. return id;
  13304. },
  13305. results: function() {
  13306. if($results.length === 0) {
  13307. $results = $('<div />')
  13308. .addClass(className.results)
  13309. .appendTo($module)
  13310. ;
  13311. }
  13312. }
  13313. },
  13314. inject: {
  13315. result: function(result, resultIndex, categoryIndex) {
  13316. module.verbose('Injecting result into results');
  13317. var
  13318. $selectedResult = (categoryIndex !== undefined)
  13319. ? $results
  13320. .children().eq(categoryIndex)
  13321. .children(selector.results)
  13322. .first()
  13323. .children(selector.result)
  13324. .eq(resultIndex)
  13325. : $results
  13326. .children(selector.result).eq(resultIndex)
  13327. ;
  13328. module.verbose('Injecting results metadata', $selectedResult);
  13329. $selectedResult
  13330. .data(metadata.result, result)
  13331. ;
  13332. },
  13333. id: function(results) {
  13334. module.debug('Injecting unique ids into results');
  13335. var
  13336. // since results may be object, we must use counters
  13337. categoryIndex = 0,
  13338. resultIndex = 0
  13339. ;
  13340. if(settings.type === 'category') {
  13341. // iterate through each category result
  13342. $.each(results, function(index, category) {
  13343. resultIndex = 0;
  13344. $.each(category.results, function(index, value) {
  13345. var
  13346. result = category.results[index]
  13347. ;
  13348. if(result.id === undefined) {
  13349. result.id = module.create.id(resultIndex, categoryIndex);
  13350. }
  13351. module.inject.result(result, resultIndex, categoryIndex);
  13352. resultIndex++;
  13353. });
  13354. categoryIndex++;
  13355. });
  13356. }
  13357. else {
  13358. // top level
  13359. $.each(results, function(index, value) {
  13360. var
  13361. result = results[index]
  13362. ;
  13363. if(result.id === undefined) {
  13364. result.id = module.create.id(resultIndex);
  13365. }
  13366. module.inject.result(result, resultIndex);
  13367. resultIndex++;
  13368. });
  13369. }
  13370. return results;
  13371. }
  13372. },
  13373. save: {
  13374. results: function(results) {
  13375. module.verbose('Saving current search results to metadata', results);
  13376. $module.data(metadata.results, results);
  13377. }
  13378. },
  13379. write: {
  13380. cache: function(name, value) {
  13381. var
  13382. cache = ($module.data(metadata.cache) !== undefined)
  13383. ? $module.data(metadata.cache)
  13384. : {}
  13385. ;
  13386. if(settings.cache) {
  13387. module.verbose('Writing generated html to cache', name, value);
  13388. cache[name] = value;
  13389. $module
  13390. .data(metadata.cache, cache)
  13391. ;
  13392. }
  13393. }
  13394. },
  13395. addResults: function(html) {
  13396. if( $.isFunction(settings.onResultsAdd) ) {
  13397. if( settings.onResultsAdd.call($results, html) === false ) {
  13398. module.debug('onResultsAdd callback cancelled default action');
  13399. return false;
  13400. }
  13401. }
  13402. if(html) {
  13403. $results
  13404. .html(html)
  13405. ;
  13406. module.refreshResults();
  13407. if(settings.selectFirstResult) {
  13408. module.select.firstResult();
  13409. }
  13410. module.showResults();
  13411. }
  13412. else {
  13413. module.hideResults(function() {
  13414. $results.empty();
  13415. });
  13416. }
  13417. },
  13418. showResults: function(callback) {
  13419. callback = $.isFunction(callback)
  13420. ? callback
  13421. : function(){}
  13422. ;
  13423. if(resultsDismissed) {
  13424. return;
  13425. }
  13426. if(!module.is.visible() && module.has.results()) {
  13427. if( module.can.transition() ) {
  13428. module.debug('Showing results with css animations');
  13429. $results
  13430. .transition({
  13431. animation : settings.transition + ' in',
  13432. debug : settings.debug,
  13433. verbose : settings.verbose,
  13434. duration : settings.duration,
  13435. onComplete : function() {
  13436. callback();
  13437. },
  13438. queue : true
  13439. })
  13440. ;
  13441. }
  13442. else {
  13443. module.debug('Showing results with javascript');
  13444. $results
  13445. .stop()
  13446. .fadeIn(settings.duration, settings.easing)
  13447. ;
  13448. }
  13449. settings.onResultsOpen.call($results);
  13450. }
  13451. },
  13452. hideResults: function(callback) {
  13453. callback = $.isFunction(callback)
  13454. ? callback
  13455. : function(){}
  13456. ;
  13457. if( module.is.visible() ) {
  13458. if( module.can.transition() ) {
  13459. module.debug('Hiding results with css animations');
  13460. $results
  13461. .transition({
  13462. animation : settings.transition + ' out',
  13463. debug : settings.debug,
  13464. verbose : settings.verbose,
  13465. duration : settings.duration,
  13466. onComplete : function() {
  13467. callback();
  13468. },
  13469. queue : true
  13470. })
  13471. ;
  13472. }
  13473. else {
  13474. module.debug('Hiding results with javascript');
  13475. $results
  13476. .stop()
  13477. .fadeOut(settings.duration, settings.easing)
  13478. ;
  13479. }
  13480. settings.onResultsClose.call($results);
  13481. }
  13482. },
  13483. generateResults: function(response) {
  13484. module.debug('Generating html from response', response);
  13485. var
  13486. template = settings.templates[settings.type],
  13487. isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])),
  13488. isProperArray = ($.isArray(response[fields.results]) && response[fields.results].length > 0),
  13489. html = ''
  13490. ;
  13491. if(isProperObject || isProperArray ) {
  13492. if(settings.maxResults > 0) {
  13493. if(isProperObject) {
  13494. if(settings.type == 'standard') {
  13495. module.error(error.maxResults);
  13496. }
  13497. }
  13498. else {
  13499. response[fields.results] = response[fields.results].slice(0, settings.maxResults);
  13500. }
  13501. }
  13502. if($.isFunction(template)) {
  13503. html = template(response, fields);
  13504. }
  13505. else {
  13506. module.error(error.noTemplate, false);
  13507. }
  13508. }
  13509. else if(settings.showNoResults) {
  13510. html = module.displayMessage(error.noResults, 'empty');
  13511. }
  13512. settings.onResults.call(element, response);
  13513. return html;
  13514. },
  13515. displayMessage: function(text, type) {
  13516. type = type || 'standard';
  13517. module.debug('Displaying message', text, type);
  13518. module.addResults( settings.templates.message(text, type) );
  13519. return settings.templates.message(text, type);
  13520. },
  13521. setting: function(name, value) {
  13522. if( $.isPlainObject(name) ) {
  13523. $.extend(true, settings, name);
  13524. }
  13525. else if(value !== undefined) {
  13526. settings[name] = value;
  13527. }
  13528. else {
  13529. return settings[name];
  13530. }
  13531. },
  13532. internal: function(name, value) {
  13533. if( $.isPlainObject(name) ) {
  13534. $.extend(true, module, name);
  13535. }
  13536. else if(value !== undefined) {
  13537. module[name] = value;
  13538. }
  13539. else {
  13540. return module[name];
  13541. }
  13542. },
  13543. debug: function() {
  13544. if(!settings.silent && settings.debug) {
  13545. if(settings.performance) {
  13546. module.performance.log(arguments);
  13547. }
  13548. else {
  13549. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13550. module.debug.apply(console, arguments);
  13551. }
  13552. }
  13553. },
  13554. verbose: function() {
  13555. if(!settings.silent && settings.verbose && settings.debug) {
  13556. if(settings.performance) {
  13557. module.performance.log(arguments);
  13558. }
  13559. else {
  13560. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13561. module.verbose.apply(console, arguments);
  13562. }
  13563. }
  13564. },
  13565. error: function() {
  13566. if(!settings.silent) {
  13567. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  13568. module.error.apply(console, arguments);
  13569. }
  13570. },
  13571. performance: {
  13572. log: function(message) {
  13573. var
  13574. currentTime,
  13575. executionTime,
  13576. previousTime
  13577. ;
  13578. if(settings.performance) {
  13579. currentTime = new Date().getTime();
  13580. previousTime = time || currentTime;
  13581. executionTime = currentTime - previousTime;
  13582. time = currentTime;
  13583. performance.push({
  13584. 'Name' : message[0],
  13585. 'Arguments' : [].slice.call(message, 1) || '',
  13586. 'Element' : element,
  13587. 'Execution Time' : executionTime
  13588. });
  13589. }
  13590. clearTimeout(module.performance.timer);
  13591. module.performance.timer = setTimeout(module.performance.display, 500);
  13592. },
  13593. display: function() {
  13594. var
  13595. title = settings.name + ':',
  13596. totalTime = 0
  13597. ;
  13598. time = false;
  13599. clearTimeout(module.performance.timer);
  13600. $.each(performance, function(index, data) {
  13601. totalTime += data['Execution Time'];
  13602. });
  13603. title += ' ' + totalTime + 'ms';
  13604. if(moduleSelector) {
  13605. title += ' \'' + moduleSelector + '\'';
  13606. }
  13607. if($allModules.length > 1) {
  13608. title += ' ' + '(' + $allModules.length + ')';
  13609. }
  13610. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  13611. console.groupCollapsed(title);
  13612. if(console.table) {
  13613. console.table(performance);
  13614. }
  13615. else {
  13616. $.each(performance, function(index, data) {
  13617. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  13618. });
  13619. }
  13620. console.groupEnd();
  13621. }
  13622. performance = [];
  13623. }
  13624. },
  13625. invoke: function(query, passedArguments, context) {
  13626. var
  13627. object = instance,
  13628. maxDepth,
  13629. found,
  13630. response
  13631. ;
  13632. passedArguments = passedArguments || queryArguments;
  13633. context = element || context;
  13634. if(typeof query == 'string' && object !== undefined) {
  13635. query = query.split(/[\. ]/);
  13636. maxDepth = query.length - 1;
  13637. $.each(query, function(depth, value) {
  13638. var camelCaseValue = (depth != maxDepth)
  13639. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  13640. : query
  13641. ;
  13642. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  13643. object = object[camelCaseValue];
  13644. }
  13645. else if( object[camelCaseValue] !== undefined ) {
  13646. found = object[camelCaseValue];
  13647. return false;
  13648. }
  13649. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  13650. object = object[value];
  13651. }
  13652. else if( object[value] !== undefined ) {
  13653. found = object[value];
  13654. return false;
  13655. }
  13656. else {
  13657. return false;
  13658. }
  13659. });
  13660. }
  13661. if( $.isFunction( found ) ) {
  13662. response = found.apply(context, passedArguments);
  13663. }
  13664. else if(found !== undefined) {
  13665. response = found;
  13666. }
  13667. if($.isArray(returnedValue)) {
  13668. returnedValue.push(response);
  13669. }
  13670. else if(returnedValue !== undefined) {
  13671. returnedValue = [returnedValue, response];
  13672. }
  13673. else if(response !== undefined) {
  13674. returnedValue = response;
  13675. }
  13676. return found;
  13677. }
  13678. };
  13679. if(methodInvoked) {
  13680. if(instance === undefined) {
  13681. module.initialize();
  13682. }
  13683. module.invoke(query);
  13684. }
  13685. else {
  13686. if(instance !== undefined) {
  13687. instance.invoke('destroy');
  13688. }
  13689. module.initialize();
  13690. }
  13691. })
  13692. ;
  13693. return (returnedValue !== undefined)
  13694. ? returnedValue
  13695. : this
  13696. ;
  13697. };
  13698. $.fn.search.settings = {
  13699. name : 'Search',
  13700. namespace : 'search',
  13701. silent : false,
  13702. debug : false,
  13703. verbose : false,
  13704. performance : true,
  13705. // template to use (specified in settings.templates)
  13706. type : 'standard',
  13707. // minimum characters required to search
  13708. minCharacters : 1,
  13709. // whether to select first result after searching automatically
  13710. selectFirstResult : false,
  13711. // API config
  13712. apiSettings : false,
  13713. // object to search
  13714. source : false,
  13715. // Whether search should query current term on focus
  13716. searchOnFocus : true,
  13717. // fields to search
  13718. searchFields : [
  13719. 'title',
  13720. 'description'
  13721. ],
  13722. // field to display in standard results template
  13723. displayField : '',
  13724. // search anywhere in value (set to 'exact' to require exact matches
  13725. fullTextSearch : 'exact',
  13726. // whether to add events to prompt automatically
  13727. automatic : true,
  13728. // delay before hiding menu after blur
  13729. hideDelay : 0,
  13730. // delay before searching
  13731. searchDelay : 200,
  13732. // maximum results returned from search
  13733. maxResults : 7,
  13734. // whether to store lookups in local cache
  13735. cache : true,
  13736. // whether no results errors should be shown
  13737. showNoResults : true,
  13738. // transition settings
  13739. transition : 'scale',
  13740. duration : 200,
  13741. easing : 'easeOutExpo',
  13742. // callbacks
  13743. onSelect : false,
  13744. onResultsAdd : false,
  13745. onSearchQuery : function(query){},
  13746. onResults : function(response){},
  13747. onResultsOpen : function(){},
  13748. onResultsClose : function(){},
  13749. className: {
  13750. animating : 'animating',
  13751. active : 'active',
  13752. empty : 'empty',
  13753. focus : 'focus',
  13754. hidden : 'hidden',
  13755. loading : 'loading',
  13756. results : 'results',
  13757. pressed : 'down'
  13758. },
  13759. error : {
  13760. source : 'Cannot search. No source used, and Semantic API module was not included',
  13761. noResults : 'Your search returned no results',
  13762. logging : 'Error in debug logging, exiting.',
  13763. noEndpoint : 'No search endpoint was specified',
  13764. noTemplate : 'A valid template name was not specified.',
  13765. oldSearchSyntax : 'searchFullText setting has been renamed fullTextSearch for consistency, please adjust your settings.',
  13766. serverError : 'There was an issue querying the server.',
  13767. maxResults : 'Results must be an array to use maxResults setting',
  13768. method : 'The method you called is not defined.'
  13769. },
  13770. metadata: {
  13771. cache : 'cache',
  13772. results : 'results',
  13773. result : 'result'
  13774. },
  13775. regExp: {
  13776. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  13777. beginsWith : '(?:\s|^)'
  13778. },
  13779. // maps api response attributes to internal representation
  13780. fields: {
  13781. categories : 'results', // array of categories (category view)
  13782. categoryName : 'name', // name of category (category view)
  13783. categoryResults : 'results', // array of results (category view)
  13784. description : 'description', // result description
  13785. image : 'image', // result image
  13786. price : 'price', // result price
  13787. results : 'results', // array of results (standard)
  13788. title : 'title', // result title
  13789. url : 'url', // result url
  13790. action : 'action', // "view more" object name
  13791. actionText : 'text', // "view more" text
  13792. actionURL : 'url' // "view more" url
  13793. },
  13794. selector : {
  13795. prompt : '.prompt',
  13796. searchButton : '.search.button',
  13797. results : '.results',
  13798. message : '.results > .message',
  13799. category : '.category',
  13800. result : '.result',
  13801. title : '.title, .name'
  13802. },
  13803. templates: {
  13804. escape: function(string) {
  13805. var
  13806. badChars = /[&<>"'`]/g,
  13807. shouldEscape = /[&<>"'`]/,
  13808. escape = {
  13809. "&": "&amp;",
  13810. "<": "&lt;",
  13811. ">": "&gt;",
  13812. '"': "&quot;",
  13813. "'": "&#x27;",
  13814. "`": "&#x60;"
  13815. },
  13816. escapedChar = function(chr) {
  13817. return escape[chr];
  13818. }
  13819. ;
  13820. if(shouldEscape.test(string)) {
  13821. return string.replace(badChars, escapedChar);
  13822. }
  13823. return string;
  13824. },
  13825. message: function(message, type) {
  13826. var
  13827. html = ''
  13828. ;
  13829. if(message !== undefined && type !== undefined) {
  13830. html += ''
  13831. + '<div class="message ' + type + '">'
  13832. ;
  13833. // message type
  13834. if(type == 'empty') {
  13835. html += ''
  13836. + '<div class="header">No Results</div class="header">'
  13837. + '<div class="description">' + message + '</div class="description">'
  13838. ;
  13839. }
  13840. else {
  13841. html += ' <div class="description">' + message + '</div>';
  13842. }
  13843. html += '</div>';
  13844. }
  13845. return html;
  13846. },
  13847. category: function(response, fields) {
  13848. var
  13849. html = '',
  13850. escape = $.fn.search.settings.templates.escape
  13851. ;
  13852. if(response[fields.categoryResults] !== undefined) {
  13853. // each category
  13854. $.each(response[fields.categoryResults], function(index, category) {
  13855. if(category[fields.results] !== undefined && category.results.length > 0) {
  13856. html += '<div class="category">';
  13857. if(category[fields.categoryName] !== undefined) {
  13858. html += '<div class="name">' + category[fields.categoryName] + '</div>';
  13859. }
  13860. // each item inside category
  13861. html += '<div class="results">';
  13862. $.each(category.results, function(index, result) {
  13863. if(result[fields.url]) {
  13864. html += '<a class="result" href="' + result[fields.url] + '">';
  13865. }
  13866. else {
  13867. html += '<a class="result">';
  13868. }
  13869. if(result[fields.image] !== undefined) {
  13870. html += ''
  13871. + '<div class="image">'
  13872. + ' <img src="' + result[fields.image] + '">'
  13873. + '</div>'
  13874. ;
  13875. }
  13876. html += '<div class="content">';
  13877. if(result[fields.price] !== undefined) {
  13878. html += '<div class="price">' + result[fields.price] + '</div>';
  13879. }
  13880. if(result[fields.title] !== undefined) {
  13881. html += '<div class="title">' + result[fields.title] + '</div>';
  13882. }
  13883. if(result[fields.description] !== undefined) {
  13884. html += '<div class="description">' + result[fields.description] + '</div>';
  13885. }
  13886. html += ''
  13887. + '</div>'
  13888. ;
  13889. html += '</a>';
  13890. });
  13891. html += '</div>';
  13892. html += ''
  13893. + '</div>'
  13894. ;
  13895. }
  13896. });
  13897. if(response[fields.action]) {
  13898. html += ''
  13899. + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">'
  13900. + response[fields.action][fields.actionText]
  13901. + '</a>';
  13902. }
  13903. return html;
  13904. }
  13905. return false;
  13906. },
  13907. standard: function(response, fields) {
  13908. var
  13909. html = ''
  13910. ;
  13911. if(response[fields.results] !== undefined) {
  13912. // each result
  13913. $.each(response[fields.results], function(index, result) {
  13914. if(result[fields.url]) {
  13915. html += '<a class="result" href="' + result[fields.url] + '">';
  13916. }
  13917. else {
  13918. html += '<a class="result">';
  13919. }
  13920. if(result[fields.image] !== undefined) {
  13921. html += ''
  13922. + '<div class="image">'
  13923. + ' <img src="' + result[fields.image] + '">'
  13924. + '</div>'
  13925. ;
  13926. }
  13927. html += '<div class="content">';
  13928. if(result[fields.price] !== undefined) {
  13929. html += '<div class="price">' + result[fields.price] + '</div>';
  13930. }
  13931. if(result[fields.title] !== undefined) {
  13932. html += '<div class="title">' + result[fields.title] + '</div>';
  13933. }
  13934. if(result[fields.description] !== undefined) {
  13935. html += '<div class="description">' + result[fields.description] + '</div>';
  13936. }
  13937. html += ''
  13938. + '</div>'
  13939. ;
  13940. html += '</a>';
  13941. });
  13942. if(response[fields.action]) {
  13943. html += ''
  13944. + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">'
  13945. + response[fields.action][fields.actionText]
  13946. + '</a>';
  13947. }
  13948. return html;
  13949. }
  13950. return false;
  13951. }
  13952. }
  13953. };
  13954. })( jQuery, window, document );
  13955. /*!
  13956. * # Semantic UI 2.3.0 - Shape
  13957. * http://github.com/semantic-org/semantic-ui/
  13958. *
  13959. *
  13960. * Released under the MIT license
  13961. * http://opensource.org/licenses/MIT
  13962. *
  13963. */
  13964. ;(function ($, window, document, undefined) {
  13965. "use strict";
  13966. window = (typeof window != 'undefined' && window.Math == Math)
  13967. ? window
  13968. : (typeof self != 'undefined' && self.Math == Math)
  13969. ? self
  13970. : Function('return this')()
  13971. ;
  13972. $.fn.shape = function(parameters) {
  13973. var
  13974. $allModules = $(this),
  13975. $body = $('body'),
  13976. time = new Date().getTime(),
  13977. performance = [],
  13978. query = arguments[0],
  13979. methodInvoked = (typeof query == 'string'),
  13980. queryArguments = [].slice.call(arguments, 1),
  13981. requestAnimationFrame = window.requestAnimationFrame
  13982. || window.mozRequestAnimationFrame
  13983. || window.webkitRequestAnimationFrame
  13984. || window.msRequestAnimationFrame
  13985. || function(callback) { setTimeout(callback, 0); },
  13986. returnedValue
  13987. ;
  13988. $allModules
  13989. .each(function() {
  13990. var
  13991. moduleSelector = $allModules.selector || '',
  13992. settings = ( $.isPlainObject(parameters) )
  13993. ? $.extend(true, {}, $.fn.shape.settings, parameters)
  13994. : $.extend({}, $.fn.shape.settings),
  13995. // internal aliases
  13996. namespace = settings.namespace,
  13997. selector = settings.selector,
  13998. error = settings.error,
  13999. className = settings.className,
  14000. // define namespaces for modules
  14001. eventNamespace = '.' + namespace,
  14002. moduleNamespace = 'module-' + namespace,
  14003. // selector cache
  14004. $module = $(this),
  14005. $sides = $module.find(selector.sides),
  14006. $side = $module.find(selector.side),
  14007. // private variables
  14008. nextIndex = false,
  14009. $activeSide,
  14010. $nextSide,
  14011. // standard module
  14012. element = this,
  14013. instance = $module.data(moduleNamespace),
  14014. module
  14015. ;
  14016. module = {
  14017. initialize: function() {
  14018. module.verbose('Initializing module for', element);
  14019. module.set.defaultSide();
  14020. module.instantiate();
  14021. },
  14022. instantiate: function() {
  14023. module.verbose('Storing instance of module', module);
  14024. instance = module;
  14025. $module
  14026. .data(moduleNamespace, instance)
  14027. ;
  14028. },
  14029. destroy: function() {
  14030. module.verbose('Destroying previous module for', element);
  14031. $module
  14032. .removeData(moduleNamespace)
  14033. .off(eventNamespace)
  14034. ;
  14035. },
  14036. refresh: function() {
  14037. module.verbose('Refreshing selector cache for', element);
  14038. $module = $(element);
  14039. $sides = $(this).find(selector.shape);
  14040. $side = $(this).find(selector.side);
  14041. },
  14042. repaint: function() {
  14043. module.verbose('Forcing repaint event');
  14044. var
  14045. shape = $sides[0] || document.createElement('div'),
  14046. fakeAssignment = shape.offsetWidth
  14047. ;
  14048. },
  14049. animate: function(propertyObject, callback) {
  14050. module.verbose('Animating box with properties', propertyObject);
  14051. callback = callback || function(event) {
  14052. module.verbose('Executing animation callback');
  14053. if(event !== undefined) {
  14054. event.stopPropagation();
  14055. }
  14056. module.reset();
  14057. module.set.active();
  14058. };
  14059. settings.beforeChange.call($nextSide[0]);
  14060. if(module.get.transitionEvent()) {
  14061. module.verbose('Starting CSS animation');
  14062. $module
  14063. .addClass(className.animating)
  14064. ;
  14065. $sides
  14066. .css(propertyObject)
  14067. .one(module.get.transitionEvent(), callback)
  14068. ;
  14069. module.set.duration(settings.duration);
  14070. requestAnimationFrame(function() {
  14071. $module
  14072. .addClass(className.animating)
  14073. ;
  14074. $activeSide
  14075. .addClass(className.hidden)
  14076. ;
  14077. });
  14078. }
  14079. else {
  14080. callback();
  14081. }
  14082. },
  14083. queue: function(method) {
  14084. module.debug('Queueing animation of', method);
  14085. $sides
  14086. .one(module.get.transitionEvent(), function() {
  14087. module.debug('Executing queued animation');
  14088. setTimeout(function(){
  14089. $module.shape(method);
  14090. }, 0);
  14091. })
  14092. ;
  14093. },
  14094. reset: function() {
  14095. module.verbose('Animating states reset');
  14096. $module
  14097. .removeClass(className.animating)
  14098. .attr('style', '')
  14099. .removeAttr('style')
  14100. ;
  14101. // removeAttr style does not consistently work in safari
  14102. $sides
  14103. .attr('style', '')
  14104. .removeAttr('style')
  14105. ;
  14106. $side
  14107. .attr('style', '')
  14108. .removeAttr('style')
  14109. .removeClass(className.hidden)
  14110. ;
  14111. $nextSide
  14112. .removeClass(className.animating)
  14113. .attr('style', '')
  14114. .removeAttr('style')
  14115. ;
  14116. },
  14117. is: {
  14118. complete: function() {
  14119. return ($side.filter('.' + className.active)[0] == $nextSide[0]);
  14120. },
  14121. animating: function() {
  14122. return $module.hasClass(className.animating);
  14123. }
  14124. },
  14125. set: {
  14126. defaultSide: function() {
  14127. $activeSide = $module.find('.' + settings.className.active);
  14128. $nextSide = ( $activeSide.next(selector.side).length > 0 )
  14129. ? $activeSide.next(selector.side)
  14130. : $module.find(selector.side).first()
  14131. ;
  14132. nextIndex = false;
  14133. module.verbose('Active side set to', $activeSide);
  14134. module.verbose('Next side set to', $nextSide);
  14135. },
  14136. duration: function(duration) {
  14137. duration = duration || settings.duration;
  14138. duration = (typeof duration == 'number')
  14139. ? duration + 'ms'
  14140. : duration
  14141. ;
  14142. module.verbose('Setting animation duration', duration);
  14143. if(settings.duration || settings.duration === 0) {
  14144. $sides.add($side)
  14145. .css({
  14146. '-webkit-transition-duration': duration,
  14147. '-moz-transition-duration': duration,
  14148. '-ms-transition-duration': duration,
  14149. '-o-transition-duration': duration,
  14150. 'transition-duration': duration
  14151. })
  14152. ;
  14153. }
  14154. },
  14155. currentStageSize: function() {
  14156. var
  14157. $activeSide = $module.find('.' + settings.className.active),
  14158. width = $activeSide.outerWidth(true),
  14159. height = $activeSide.outerHeight(true)
  14160. ;
  14161. $module
  14162. .css({
  14163. width: width,
  14164. height: height
  14165. })
  14166. ;
  14167. },
  14168. stageSize: function() {
  14169. var
  14170. $clone = $module.clone().addClass(className.loading),
  14171. $activeSide = $clone.find('.' + settings.className.active),
  14172. $nextSide = (nextIndex)
  14173. ? $clone.find(selector.side).eq(nextIndex)
  14174. : ( $activeSide.next(selector.side).length > 0 )
  14175. ? $activeSide.next(selector.side)
  14176. : $clone.find(selector.side).first(),
  14177. newWidth = (settings.width == 'next')
  14178. ? $nextSide.outerWidth(true)
  14179. : (settings.width == 'initial')
  14180. ? $module.width()
  14181. : settings.width,
  14182. newHeight = (settings.height == 'next')
  14183. ? $nextSide.outerHeight(true)
  14184. : (settings.height == 'initial')
  14185. ? $module.height()
  14186. : settings.height
  14187. ;
  14188. $activeSide.removeClass(className.active);
  14189. $nextSide.addClass(className.active);
  14190. $clone.insertAfter($module);
  14191. $clone.remove();
  14192. if(settings.width != 'auto') {
  14193. $module.css('width', newWidth + settings.jitter);
  14194. module.verbose('Specifying width during animation', newWidth);
  14195. }
  14196. if(settings.height != 'auto') {
  14197. $module.css('height', newHeight + settings.jitter);
  14198. module.verbose('Specifying height during animation', newHeight);
  14199. }
  14200. },
  14201. nextSide: function(selector) {
  14202. nextIndex = selector;
  14203. $nextSide = $side.filter(selector);
  14204. nextIndex = $side.index($nextSide);
  14205. if($nextSide.length === 0) {
  14206. module.set.defaultSide();
  14207. module.error(error.side);
  14208. }
  14209. module.verbose('Next side manually set to', $nextSide);
  14210. },
  14211. active: function() {
  14212. module.verbose('Setting new side to active', $nextSide);
  14213. $side
  14214. .removeClass(className.active)
  14215. ;
  14216. $nextSide
  14217. .addClass(className.active)
  14218. ;
  14219. settings.onChange.call($nextSide[0]);
  14220. module.set.defaultSide();
  14221. }
  14222. },
  14223. flip: {
  14224. up: function() {
  14225. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14226. module.debug('Side already visible', $nextSide);
  14227. return;
  14228. }
  14229. if( !module.is.animating()) {
  14230. module.debug('Flipping up', $nextSide);
  14231. var
  14232. transform = module.get.transform.up()
  14233. ;
  14234. module.set.stageSize();
  14235. module.stage.above();
  14236. module.animate(transform);
  14237. }
  14238. else {
  14239. module.queue('flip up');
  14240. }
  14241. },
  14242. down: function() {
  14243. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14244. module.debug('Side already visible', $nextSide);
  14245. return;
  14246. }
  14247. if( !module.is.animating()) {
  14248. module.debug('Flipping down', $nextSide);
  14249. var
  14250. transform = module.get.transform.down()
  14251. ;
  14252. module.set.stageSize();
  14253. module.stage.below();
  14254. module.animate(transform);
  14255. }
  14256. else {
  14257. module.queue('flip down');
  14258. }
  14259. },
  14260. left: function() {
  14261. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14262. module.debug('Side already visible', $nextSide);
  14263. return;
  14264. }
  14265. if( !module.is.animating()) {
  14266. module.debug('Flipping left', $nextSide);
  14267. var
  14268. transform = module.get.transform.left()
  14269. ;
  14270. module.set.stageSize();
  14271. module.stage.left();
  14272. module.animate(transform);
  14273. }
  14274. else {
  14275. module.queue('flip left');
  14276. }
  14277. },
  14278. right: function() {
  14279. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14280. module.debug('Side already visible', $nextSide);
  14281. return;
  14282. }
  14283. if( !module.is.animating()) {
  14284. module.debug('Flipping right', $nextSide);
  14285. var
  14286. transform = module.get.transform.right()
  14287. ;
  14288. module.set.stageSize();
  14289. module.stage.right();
  14290. module.animate(transform);
  14291. }
  14292. else {
  14293. module.queue('flip right');
  14294. }
  14295. },
  14296. over: function() {
  14297. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14298. module.debug('Side already visible', $nextSide);
  14299. return;
  14300. }
  14301. if( !module.is.animating()) {
  14302. module.debug('Flipping over', $nextSide);
  14303. module.set.stageSize();
  14304. module.stage.behind();
  14305. module.animate(module.get.transform.over() );
  14306. }
  14307. else {
  14308. module.queue('flip over');
  14309. }
  14310. },
  14311. back: function() {
  14312. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14313. module.debug('Side already visible', $nextSide);
  14314. return;
  14315. }
  14316. if( !module.is.animating()) {
  14317. module.debug('Flipping back', $nextSide);
  14318. module.set.stageSize();
  14319. module.stage.behind();
  14320. module.animate(module.get.transform.back() );
  14321. }
  14322. else {
  14323. module.queue('flip back');
  14324. }
  14325. }
  14326. },
  14327. get: {
  14328. transform: {
  14329. up: function() {
  14330. var
  14331. translate = {
  14332. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14333. z: -($activeSide.outerHeight(true) / 2)
  14334. }
  14335. ;
  14336. return {
  14337. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)'
  14338. };
  14339. },
  14340. down: function() {
  14341. var
  14342. translate = {
  14343. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14344. z: -($activeSide.outerHeight(true) / 2)
  14345. }
  14346. ;
  14347. return {
  14348. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)'
  14349. };
  14350. },
  14351. left: function() {
  14352. var
  14353. translate = {
  14354. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  14355. z : -($activeSide.outerWidth(true) / 2)
  14356. }
  14357. ;
  14358. return {
  14359. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)'
  14360. };
  14361. },
  14362. right: function() {
  14363. var
  14364. translate = {
  14365. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  14366. z : -($activeSide.outerWidth(true) / 2)
  14367. }
  14368. ;
  14369. return {
  14370. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)'
  14371. };
  14372. },
  14373. over: function() {
  14374. var
  14375. translate = {
  14376. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  14377. }
  14378. ;
  14379. return {
  14380. transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
  14381. };
  14382. },
  14383. back: function() {
  14384. var
  14385. translate = {
  14386. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  14387. }
  14388. ;
  14389. return {
  14390. transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
  14391. };
  14392. }
  14393. },
  14394. transitionEvent: function() {
  14395. var
  14396. element = document.createElement('element'),
  14397. transitions = {
  14398. 'transition' :'transitionend',
  14399. 'OTransition' :'oTransitionEnd',
  14400. 'MozTransition' :'transitionend',
  14401. 'WebkitTransition' :'webkitTransitionEnd'
  14402. },
  14403. transition
  14404. ;
  14405. for(transition in transitions){
  14406. if( element.style[transition] !== undefined ){
  14407. return transitions[transition];
  14408. }
  14409. }
  14410. },
  14411. nextSide: function() {
  14412. return ( $activeSide.next(selector.side).length > 0 )
  14413. ? $activeSide.next(selector.side)
  14414. : $module.find(selector.side).first()
  14415. ;
  14416. }
  14417. },
  14418. stage: {
  14419. above: function() {
  14420. var
  14421. box = {
  14422. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14423. depth : {
  14424. active : ($nextSide.outerHeight(true) / 2),
  14425. next : ($activeSide.outerHeight(true) / 2)
  14426. }
  14427. }
  14428. ;
  14429. module.verbose('Setting the initial animation position as above', $nextSide, box);
  14430. $sides
  14431. .css({
  14432. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14433. })
  14434. ;
  14435. $activeSide
  14436. .css({
  14437. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14438. })
  14439. ;
  14440. $nextSide
  14441. .addClass(className.animating)
  14442. .css({
  14443. 'top' : box.origin + 'px',
  14444. 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)'
  14445. })
  14446. ;
  14447. },
  14448. below: function() {
  14449. var
  14450. box = {
  14451. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14452. depth : {
  14453. active : ($nextSide.outerHeight(true) / 2),
  14454. next : ($activeSide.outerHeight(true) / 2)
  14455. }
  14456. }
  14457. ;
  14458. module.verbose('Setting the initial animation position as below', $nextSide, box);
  14459. $sides
  14460. .css({
  14461. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14462. })
  14463. ;
  14464. $activeSide
  14465. .css({
  14466. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14467. })
  14468. ;
  14469. $nextSide
  14470. .addClass(className.animating)
  14471. .css({
  14472. 'top' : box.origin + 'px',
  14473. 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)'
  14474. })
  14475. ;
  14476. },
  14477. left: function() {
  14478. var
  14479. height = {
  14480. active : $activeSide.outerWidth(true),
  14481. next : $nextSide.outerWidth(true)
  14482. },
  14483. box = {
  14484. origin : ( ( height.active - height.next ) / 2),
  14485. depth : {
  14486. active : (height.next / 2),
  14487. next : (height.active / 2)
  14488. }
  14489. }
  14490. ;
  14491. module.verbose('Setting the initial animation position as left', $nextSide, box);
  14492. $sides
  14493. .css({
  14494. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14495. })
  14496. ;
  14497. $activeSide
  14498. .css({
  14499. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14500. })
  14501. ;
  14502. $nextSide
  14503. .addClass(className.animating)
  14504. .css({
  14505. 'left' : box.origin + 'px',
  14506. 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)'
  14507. })
  14508. ;
  14509. },
  14510. right: function() {
  14511. var
  14512. height = {
  14513. active : $activeSide.outerWidth(true),
  14514. next : $nextSide.outerWidth(true)
  14515. },
  14516. box = {
  14517. origin : ( ( height.active - height.next ) / 2),
  14518. depth : {
  14519. active : (height.next / 2),
  14520. next : (height.active / 2)
  14521. }
  14522. }
  14523. ;
  14524. module.verbose('Setting the initial animation position as left', $nextSide, box);
  14525. $sides
  14526. .css({
  14527. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14528. })
  14529. ;
  14530. $activeSide
  14531. .css({
  14532. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14533. })
  14534. ;
  14535. $nextSide
  14536. .addClass(className.animating)
  14537. .css({
  14538. 'left' : box.origin + 'px',
  14539. 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)'
  14540. })
  14541. ;
  14542. },
  14543. behind: function() {
  14544. var
  14545. height = {
  14546. active : $activeSide.outerWidth(true),
  14547. next : $nextSide.outerWidth(true)
  14548. },
  14549. box = {
  14550. origin : ( ( height.active - height.next ) / 2),
  14551. depth : {
  14552. active : (height.next / 2),
  14553. next : (height.active / 2)
  14554. }
  14555. }
  14556. ;
  14557. module.verbose('Setting the initial animation position as behind', $nextSide, box);
  14558. $activeSide
  14559. .css({
  14560. 'transform' : 'rotateY(0deg)'
  14561. })
  14562. ;
  14563. $nextSide
  14564. .addClass(className.animating)
  14565. .css({
  14566. 'left' : box.origin + 'px',
  14567. 'transform' : 'rotateY(-180deg)'
  14568. })
  14569. ;
  14570. }
  14571. },
  14572. setting: function(name, value) {
  14573. module.debug('Changing setting', name, value);
  14574. if( $.isPlainObject(name) ) {
  14575. $.extend(true, settings, name);
  14576. }
  14577. else if(value !== undefined) {
  14578. if($.isPlainObject(settings[name])) {
  14579. $.extend(true, settings[name], value);
  14580. }
  14581. else {
  14582. settings[name] = value;
  14583. }
  14584. }
  14585. else {
  14586. return settings[name];
  14587. }
  14588. },
  14589. internal: function(name, value) {
  14590. if( $.isPlainObject(name) ) {
  14591. $.extend(true, module, name);
  14592. }
  14593. else if(value !== undefined) {
  14594. module[name] = value;
  14595. }
  14596. else {
  14597. return module[name];
  14598. }
  14599. },
  14600. debug: function() {
  14601. if(!settings.silent && settings.debug) {
  14602. if(settings.performance) {
  14603. module.performance.log(arguments);
  14604. }
  14605. else {
  14606. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14607. module.debug.apply(console, arguments);
  14608. }
  14609. }
  14610. },
  14611. verbose: function() {
  14612. if(!settings.silent && settings.verbose && settings.debug) {
  14613. if(settings.performance) {
  14614. module.performance.log(arguments);
  14615. }
  14616. else {
  14617. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14618. module.verbose.apply(console, arguments);
  14619. }
  14620. }
  14621. },
  14622. error: function() {
  14623. if(!settings.silent) {
  14624. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  14625. module.error.apply(console, arguments);
  14626. }
  14627. },
  14628. performance: {
  14629. log: function(message) {
  14630. var
  14631. currentTime,
  14632. executionTime,
  14633. previousTime
  14634. ;
  14635. if(settings.performance) {
  14636. currentTime = new Date().getTime();
  14637. previousTime = time || currentTime;
  14638. executionTime = currentTime - previousTime;
  14639. time = currentTime;
  14640. performance.push({
  14641. 'Name' : message[0],
  14642. 'Arguments' : [].slice.call(message, 1) || '',
  14643. 'Element' : element,
  14644. 'Execution Time' : executionTime
  14645. });
  14646. }
  14647. clearTimeout(module.performance.timer);
  14648. module.performance.timer = setTimeout(module.performance.display, 500);
  14649. },
  14650. display: function() {
  14651. var
  14652. title = settings.name + ':',
  14653. totalTime = 0
  14654. ;
  14655. time = false;
  14656. clearTimeout(module.performance.timer);
  14657. $.each(performance, function(index, data) {
  14658. totalTime += data['Execution Time'];
  14659. });
  14660. title += ' ' + totalTime + 'ms';
  14661. if(moduleSelector) {
  14662. title += ' \'' + moduleSelector + '\'';
  14663. }
  14664. if($allModules.length > 1) {
  14665. title += ' ' + '(' + $allModules.length + ')';
  14666. }
  14667. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  14668. console.groupCollapsed(title);
  14669. if(console.table) {
  14670. console.table(performance);
  14671. }
  14672. else {
  14673. $.each(performance, function(index, data) {
  14674. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  14675. });
  14676. }
  14677. console.groupEnd();
  14678. }
  14679. performance = [];
  14680. }
  14681. },
  14682. invoke: function(query, passedArguments, context) {
  14683. var
  14684. object = instance,
  14685. maxDepth,
  14686. found,
  14687. response
  14688. ;
  14689. passedArguments = passedArguments || queryArguments;
  14690. context = element || context;
  14691. if(typeof query == 'string' && object !== undefined) {
  14692. query = query.split(/[\. ]/);
  14693. maxDepth = query.length - 1;
  14694. $.each(query, function(depth, value) {
  14695. var camelCaseValue = (depth != maxDepth)
  14696. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  14697. : query
  14698. ;
  14699. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  14700. object = object[camelCaseValue];
  14701. }
  14702. else if( object[camelCaseValue] !== undefined ) {
  14703. found = object[camelCaseValue];
  14704. return false;
  14705. }
  14706. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  14707. object = object[value];
  14708. }
  14709. else if( object[value] !== undefined ) {
  14710. found = object[value];
  14711. return false;
  14712. }
  14713. else {
  14714. return false;
  14715. }
  14716. });
  14717. }
  14718. if ( $.isFunction( found ) ) {
  14719. response = found.apply(context, passedArguments);
  14720. }
  14721. else if(found !== undefined) {
  14722. response = found;
  14723. }
  14724. if($.isArray(returnedValue)) {
  14725. returnedValue.push(response);
  14726. }
  14727. else if(returnedValue !== undefined) {
  14728. returnedValue = [returnedValue, response];
  14729. }
  14730. else if(response !== undefined) {
  14731. returnedValue = response;
  14732. }
  14733. return found;
  14734. }
  14735. };
  14736. if(methodInvoked) {
  14737. if(instance === undefined) {
  14738. module.initialize();
  14739. }
  14740. module.invoke(query);
  14741. }
  14742. else {
  14743. if(instance !== undefined) {
  14744. instance.invoke('destroy');
  14745. }
  14746. module.initialize();
  14747. }
  14748. })
  14749. ;
  14750. return (returnedValue !== undefined)
  14751. ? returnedValue
  14752. : this
  14753. ;
  14754. };
  14755. $.fn.shape.settings = {
  14756. // module info
  14757. name : 'Shape',
  14758. // hide all debug content
  14759. silent : false,
  14760. // debug content outputted to console
  14761. debug : false,
  14762. // verbose debug output
  14763. verbose : false,
  14764. // fudge factor in pixels when swapping from 2d to 3d (can be useful to correct rounding errors)
  14765. jitter : 0,
  14766. // performance data output
  14767. performance: true,
  14768. // event namespace
  14769. namespace : 'shape',
  14770. // width during animation, can be set to 'auto', initial', 'next' or pixel amount
  14771. width: 'initial',
  14772. // height during animation, can be set to 'auto', 'initial', 'next' or pixel amount
  14773. height: 'initial',
  14774. // callback occurs on side change
  14775. beforeChange : function() {},
  14776. onChange : function() {},
  14777. // allow animation to same side
  14778. allowRepeats: false,
  14779. // animation duration
  14780. duration : false,
  14781. // possible errors
  14782. error: {
  14783. side : 'You tried to switch to a side that does not exist.',
  14784. method : 'The method you called is not defined'
  14785. },
  14786. // classnames used
  14787. className : {
  14788. animating : 'animating',
  14789. hidden : 'hidden',
  14790. loading : 'loading',
  14791. active : 'active'
  14792. },
  14793. // selectors used
  14794. selector : {
  14795. sides : '.sides',
  14796. side : '.side'
  14797. }
  14798. };
  14799. })( jQuery, window, document );
  14800. /*!
  14801. * # Semantic UI 2.3.0 - Sidebar
  14802. * http://github.com/semantic-org/semantic-ui/
  14803. *
  14804. *
  14805. * Released under the MIT license
  14806. * http://opensource.org/licenses/MIT
  14807. *
  14808. */
  14809. ;(function ($, window, document, undefined) {
  14810. "use strict";
  14811. window = (typeof window != 'undefined' && window.Math == Math)
  14812. ? window
  14813. : (typeof self != 'undefined' && self.Math == Math)
  14814. ? self
  14815. : Function('return this')()
  14816. ;
  14817. $.fn.sidebar = function(parameters) {
  14818. var
  14819. $allModules = $(this),
  14820. $window = $(window),
  14821. $document = $(document),
  14822. $html = $('html'),
  14823. $head = $('head'),
  14824. moduleSelector = $allModules.selector || '',
  14825. time = new Date().getTime(),
  14826. performance = [],
  14827. query = arguments[0],
  14828. methodInvoked = (typeof query == 'string'),
  14829. queryArguments = [].slice.call(arguments, 1),
  14830. requestAnimationFrame = window.requestAnimationFrame
  14831. || window.mozRequestAnimationFrame
  14832. || window.webkitRequestAnimationFrame
  14833. || window.msRequestAnimationFrame
  14834. || function(callback) { setTimeout(callback, 0); },
  14835. returnedValue
  14836. ;
  14837. $allModules
  14838. .each(function() {
  14839. var
  14840. settings = ( $.isPlainObject(parameters) )
  14841. ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
  14842. : $.extend({}, $.fn.sidebar.settings),
  14843. selector = settings.selector,
  14844. className = settings.className,
  14845. namespace = settings.namespace,
  14846. regExp = settings.regExp,
  14847. error = settings.error,
  14848. eventNamespace = '.' + namespace,
  14849. moduleNamespace = 'module-' + namespace,
  14850. $module = $(this),
  14851. $context = $(settings.context),
  14852. $sidebars = $module.children(selector.sidebar),
  14853. $fixed = $context.children(selector.fixed),
  14854. $pusher = $context.children(selector.pusher),
  14855. $style,
  14856. element = this,
  14857. instance = $module.data(moduleNamespace),
  14858. elementNamespace,
  14859. id,
  14860. currentScroll,
  14861. transitionEvent,
  14862. module
  14863. ;
  14864. module = {
  14865. initialize: function() {
  14866. module.debug('Initializing sidebar', parameters);
  14867. module.create.id();
  14868. transitionEvent = module.get.transitionEvent();
  14869. // avoids locking rendering if initialized in onReady
  14870. if(settings.delaySetup) {
  14871. requestAnimationFrame(module.setup.layout);
  14872. }
  14873. else {
  14874. module.setup.layout();
  14875. }
  14876. requestAnimationFrame(function() {
  14877. module.setup.cache();
  14878. });
  14879. module.instantiate();
  14880. },
  14881. instantiate: function() {
  14882. module.verbose('Storing instance of module', module);
  14883. instance = module;
  14884. $module
  14885. .data(moduleNamespace, module)
  14886. ;
  14887. },
  14888. create: {
  14889. id: function() {
  14890. id = (Math.random().toString(16) + '000000000').substr(2,8);
  14891. elementNamespace = '.' + id;
  14892. module.verbose('Creating unique id for element', id);
  14893. }
  14894. },
  14895. destroy: function() {
  14896. module.verbose('Destroying previous module for', $module);
  14897. $module
  14898. .off(eventNamespace)
  14899. .removeData(moduleNamespace)
  14900. ;
  14901. if(module.is.ios()) {
  14902. module.remove.ios();
  14903. }
  14904. // bound by uuid
  14905. $context.off(elementNamespace);
  14906. $window.off(elementNamespace);
  14907. $document.off(elementNamespace);
  14908. },
  14909. event: {
  14910. clickaway: function(event) {
  14911. var
  14912. clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
  14913. clickedContext = ($context.is(event.target))
  14914. ;
  14915. if(clickedInPusher) {
  14916. module.verbose('User clicked on dimmed page');
  14917. module.hide();
  14918. }
  14919. if(clickedContext) {
  14920. module.verbose('User clicked on dimmable context (scaled out page)');
  14921. module.hide();
  14922. }
  14923. },
  14924. touch: function(event) {
  14925. //event.stopPropagation();
  14926. },
  14927. containScroll: function(event) {
  14928. if(element.scrollTop <= 0) {
  14929. element.scrollTop = 1;
  14930. }
  14931. if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
  14932. element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
  14933. }
  14934. },
  14935. scroll: function(event) {
  14936. if( $(event.target).closest(selector.sidebar).length === 0 ) {
  14937. event.preventDefault();
  14938. }
  14939. }
  14940. },
  14941. bind: {
  14942. clickaway: function() {
  14943. module.verbose('Adding clickaway events to context', $context);
  14944. if(settings.closable) {
  14945. $context
  14946. .on('click' + elementNamespace, module.event.clickaway)
  14947. .on('touchend' + elementNamespace, module.event.clickaway)
  14948. ;
  14949. }
  14950. },
  14951. scrollLock: function() {
  14952. if(settings.scrollLock) {
  14953. module.debug('Disabling page scroll');
  14954. $window
  14955. .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
  14956. ;
  14957. }
  14958. module.verbose('Adding events to contain sidebar scroll');
  14959. $document
  14960. .on('touchmove' + elementNamespace, module.event.touch)
  14961. ;
  14962. $module
  14963. .on('scroll' + eventNamespace, module.event.containScroll)
  14964. ;
  14965. }
  14966. },
  14967. unbind: {
  14968. clickaway: function() {
  14969. module.verbose('Removing clickaway events from context', $context);
  14970. $context.off(elementNamespace);
  14971. },
  14972. scrollLock: function() {
  14973. module.verbose('Removing scroll lock from page');
  14974. $document.off(elementNamespace);
  14975. $window.off(elementNamespace);
  14976. $module.off('scroll' + eventNamespace);
  14977. }
  14978. },
  14979. add: {
  14980. inlineCSS: function() {
  14981. var
  14982. width = module.cache.width || $module.outerWidth(),
  14983. height = module.cache.height || $module.outerHeight(),
  14984. isRTL = module.is.rtl(),
  14985. direction = module.get.direction(),
  14986. distance = {
  14987. left : width,
  14988. right : -width,
  14989. top : height,
  14990. bottom : -height
  14991. },
  14992. style
  14993. ;
  14994. if(isRTL){
  14995. module.verbose('RTL detected, flipping widths');
  14996. distance.left = -width;
  14997. distance.right = width;
  14998. }
  14999. style = '<style>';
  15000. if(direction === 'left' || direction === 'right') {
  15001. module.debug('Adding CSS rules for animation distance', width);
  15002. style += ''
  15003. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  15004. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  15005. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15006. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15007. + ' }'
  15008. ;
  15009. }
  15010. else if(direction === 'top' || direction == 'bottom') {
  15011. style += ''
  15012. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  15013. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  15014. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15015. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15016. + ' }'
  15017. ;
  15018. }
  15019. /* IE is only browser not to create context with transforms */
  15020. /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
  15021. if( module.is.ie() ) {
  15022. if(direction === 'left' || direction === 'right') {
  15023. module.debug('Adding CSS rules for animation distance', width);
  15024. style += ''
  15025. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  15026. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15027. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15028. + ' }'
  15029. ;
  15030. }
  15031. else if(direction === 'top' || direction == 'bottom') {
  15032. style += ''
  15033. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  15034. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15035. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15036. + ' }'
  15037. ;
  15038. }
  15039. /* opposite sides visible forces content overlay */
  15040. style += ''
  15041. + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
  15042. + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
  15043. + ' -webkit-transform: translate3d(0px, 0, 0);'
  15044. + ' transform: translate3d(0px, 0, 0);'
  15045. + ' }'
  15046. ;
  15047. }
  15048. style += '</style>';
  15049. $style = $(style)
  15050. .appendTo($head)
  15051. ;
  15052. module.debug('Adding sizing css to head', $style);
  15053. }
  15054. },
  15055. refresh: function() {
  15056. module.verbose('Refreshing selector cache');
  15057. $context = $(settings.context);
  15058. $sidebars = $context.children(selector.sidebar);
  15059. $pusher = $context.children(selector.pusher);
  15060. $fixed = $context.children(selector.fixed);
  15061. module.clear.cache();
  15062. },
  15063. refreshSidebars: function() {
  15064. module.verbose('Refreshing other sidebars');
  15065. $sidebars = $context.children(selector.sidebar);
  15066. },
  15067. repaint: function() {
  15068. module.verbose('Forcing repaint event');
  15069. element.style.display = 'none';
  15070. var ignored = element.offsetHeight;
  15071. element.scrollTop = element.scrollTop;
  15072. element.style.display = '';
  15073. },
  15074. setup: {
  15075. cache: function() {
  15076. module.cache = {
  15077. width : $module.outerWidth(),
  15078. height : $module.outerHeight(),
  15079. rtl : ($module.css('direction') == 'rtl')
  15080. };
  15081. },
  15082. layout: function() {
  15083. if( $context.children(selector.pusher).length === 0 ) {
  15084. module.debug('Adding wrapper element for sidebar');
  15085. module.error(error.pusher);
  15086. $pusher = $('<div class="pusher" />');
  15087. $context
  15088. .children()
  15089. .not(selector.omitted)
  15090. .not($sidebars)
  15091. .wrapAll($pusher)
  15092. ;
  15093. module.refresh();
  15094. }
  15095. if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
  15096. module.debug('Moved sidebar to correct parent element');
  15097. module.error(error.movedSidebar, element);
  15098. $module.detach().prependTo($context);
  15099. module.refresh();
  15100. }
  15101. module.clear.cache();
  15102. module.set.pushable();
  15103. module.set.direction();
  15104. }
  15105. },
  15106. attachEvents: function(selector, event) {
  15107. var
  15108. $toggle = $(selector)
  15109. ;
  15110. event = $.isFunction(module[event])
  15111. ? module[event]
  15112. : module.toggle
  15113. ;
  15114. if($toggle.length > 0) {
  15115. module.debug('Attaching sidebar events to element', selector, event);
  15116. $toggle
  15117. .on('click' + eventNamespace, event)
  15118. ;
  15119. }
  15120. else {
  15121. module.error(error.notFound, selector);
  15122. }
  15123. },
  15124. show: function(callback) {
  15125. callback = $.isFunction(callback)
  15126. ? callback
  15127. : function(){}
  15128. ;
  15129. if(module.is.hidden()) {
  15130. module.refreshSidebars();
  15131. if(settings.overlay) {
  15132. module.error(error.overlay);
  15133. settings.transition = 'overlay';
  15134. }
  15135. module.refresh();
  15136. if(module.othersActive()) {
  15137. module.debug('Other sidebars currently visible');
  15138. if(settings.exclusive) {
  15139. // if not overlay queue animation after hide
  15140. if(settings.transition != 'overlay') {
  15141. module.hideOthers(module.show);
  15142. return;
  15143. }
  15144. else {
  15145. module.hideOthers();
  15146. }
  15147. }
  15148. else {
  15149. settings.transition = 'overlay';
  15150. }
  15151. }
  15152. module.pushPage(function() {
  15153. callback.call(element);
  15154. settings.onShow.call(element);
  15155. });
  15156. settings.onChange.call(element);
  15157. settings.onVisible.call(element);
  15158. }
  15159. else {
  15160. module.debug('Sidebar is already visible');
  15161. }
  15162. },
  15163. hide: function(callback) {
  15164. callback = $.isFunction(callback)
  15165. ? callback
  15166. : function(){}
  15167. ;
  15168. if(module.is.visible() || module.is.animating()) {
  15169. module.debug('Hiding sidebar', callback);
  15170. module.refreshSidebars();
  15171. module.pullPage(function() {
  15172. callback.call(element);
  15173. settings.onHidden.call(element);
  15174. });
  15175. settings.onChange.call(element);
  15176. settings.onHide.call(element);
  15177. }
  15178. },
  15179. othersAnimating: function() {
  15180. return ($sidebars.not($module).filter('.' + className.animating).length > 0);
  15181. },
  15182. othersVisible: function() {
  15183. return ($sidebars.not($module).filter('.' + className.visible).length > 0);
  15184. },
  15185. othersActive: function() {
  15186. return(module.othersVisible() || module.othersAnimating());
  15187. },
  15188. hideOthers: function(callback) {
  15189. var
  15190. $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
  15191. sidebarCount = $otherSidebars.length,
  15192. callbackCount = 0
  15193. ;
  15194. callback = callback || function(){};
  15195. $otherSidebars
  15196. .sidebar('hide', function() {
  15197. callbackCount++;
  15198. if(callbackCount == sidebarCount) {
  15199. callback();
  15200. }
  15201. })
  15202. ;
  15203. },
  15204. toggle: function() {
  15205. module.verbose('Determining toggled direction');
  15206. if(module.is.hidden()) {
  15207. module.show();
  15208. }
  15209. else {
  15210. module.hide();
  15211. }
  15212. },
  15213. pushPage: function(callback) {
  15214. var
  15215. transition = module.get.transition(),
  15216. $transition = (transition === 'overlay' || module.othersActive())
  15217. ? $module
  15218. : $pusher,
  15219. animate,
  15220. dim,
  15221. transitionEnd
  15222. ;
  15223. callback = $.isFunction(callback)
  15224. ? callback
  15225. : function(){}
  15226. ;
  15227. if(settings.transition == 'scale down') {
  15228. module.scrollToTop();
  15229. }
  15230. module.set.transition(transition);
  15231. module.repaint();
  15232. animate = function() {
  15233. module.bind.clickaway();
  15234. module.add.inlineCSS();
  15235. module.set.animating();
  15236. module.set.visible();
  15237. };
  15238. dim = function() {
  15239. module.set.dimmed();
  15240. };
  15241. transitionEnd = function(event) {
  15242. if( event.target == $transition[0] ) {
  15243. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  15244. module.remove.animating();
  15245. module.bind.scrollLock();
  15246. callback.call(element);
  15247. }
  15248. };
  15249. $transition.off(transitionEvent + elementNamespace);
  15250. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  15251. requestAnimationFrame(animate);
  15252. if(settings.dimPage && !module.othersVisible()) {
  15253. requestAnimationFrame(dim);
  15254. }
  15255. },
  15256. pullPage: function(callback) {
  15257. var
  15258. transition = module.get.transition(),
  15259. $transition = (transition == 'overlay' || module.othersActive())
  15260. ? $module
  15261. : $pusher,
  15262. animate,
  15263. transitionEnd
  15264. ;
  15265. callback = $.isFunction(callback)
  15266. ? callback
  15267. : function(){}
  15268. ;
  15269. module.verbose('Removing context push state', module.get.direction());
  15270. module.unbind.clickaway();
  15271. module.unbind.scrollLock();
  15272. animate = function() {
  15273. module.set.transition(transition);
  15274. module.set.animating();
  15275. module.remove.visible();
  15276. if(settings.dimPage && !module.othersVisible()) {
  15277. $pusher.removeClass(className.dimmed);
  15278. }
  15279. };
  15280. transitionEnd = function(event) {
  15281. if( event.target == $transition[0] ) {
  15282. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  15283. module.remove.animating();
  15284. module.remove.transition();
  15285. module.remove.inlineCSS();
  15286. if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
  15287. module.scrollBack();
  15288. }
  15289. callback.call(element);
  15290. }
  15291. };
  15292. $transition.off(transitionEvent + elementNamespace);
  15293. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  15294. requestAnimationFrame(animate);
  15295. },
  15296. scrollToTop: function() {
  15297. module.verbose('Scrolling to top of page to avoid animation issues');
  15298. currentScroll = $(window).scrollTop();
  15299. $module.scrollTop(0);
  15300. window.scrollTo(0, 0);
  15301. },
  15302. scrollBack: function() {
  15303. module.verbose('Scrolling back to original page position');
  15304. window.scrollTo(0, currentScroll);
  15305. },
  15306. clear: {
  15307. cache: function() {
  15308. module.verbose('Clearing cached dimensions');
  15309. module.cache = {};
  15310. }
  15311. },
  15312. set: {
  15313. // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
  15314. // (This is no longer necessary in latest iOS)
  15315. ios: function() {
  15316. $html.addClass(className.ios);
  15317. },
  15318. // container
  15319. pushed: function() {
  15320. $context.addClass(className.pushed);
  15321. },
  15322. pushable: function() {
  15323. $context.addClass(className.pushable);
  15324. },
  15325. // pusher
  15326. dimmed: function() {
  15327. $pusher.addClass(className.dimmed);
  15328. },
  15329. // sidebar
  15330. active: function() {
  15331. $module.addClass(className.active);
  15332. },
  15333. animating: function() {
  15334. $module.addClass(className.animating);
  15335. },
  15336. transition: function(transition) {
  15337. transition = transition || module.get.transition();
  15338. $module.addClass(transition);
  15339. },
  15340. direction: function(direction) {
  15341. direction = direction || module.get.direction();
  15342. $module.addClass(className[direction]);
  15343. },
  15344. visible: function() {
  15345. $module.addClass(className.visible);
  15346. },
  15347. overlay: function() {
  15348. $module.addClass(className.overlay);
  15349. }
  15350. },
  15351. remove: {
  15352. inlineCSS: function() {
  15353. module.debug('Removing inline css styles', $style);
  15354. if($style && $style.length > 0) {
  15355. $style.remove();
  15356. }
  15357. },
  15358. // ios scroll on html not document
  15359. ios: function() {
  15360. $html.removeClass(className.ios);
  15361. },
  15362. // context
  15363. pushed: function() {
  15364. $context.removeClass(className.pushed);
  15365. },
  15366. pushable: function() {
  15367. $context.removeClass(className.pushable);
  15368. },
  15369. // sidebar
  15370. active: function() {
  15371. $module.removeClass(className.active);
  15372. },
  15373. animating: function() {
  15374. $module.removeClass(className.animating);
  15375. },
  15376. transition: function(transition) {
  15377. transition = transition || module.get.transition();
  15378. $module.removeClass(transition);
  15379. },
  15380. direction: function(direction) {
  15381. direction = direction || module.get.direction();
  15382. $module.removeClass(className[direction]);
  15383. },
  15384. visible: function() {
  15385. $module.removeClass(className.visible);
  15386. },
  15387. overlay: function() {
  15388. $module.removeClass(className.overlay);
  15389. }
  15390. },
  15391. get: {
  15392. direction: function() {
  15393. if($module.hasClass(className.top)) {
  15394. return className.top;
  15395. }
  15396. else if($module.hasClass(className.right)) {
  15397. return className.right;
  15398. }
  15399. else if($module.hasClass(className.bottom)) {
  15400. return className.bottom;
  15401. }
  15402. return className.left;
  15403. },
  15404. transition: function() {
  15405. var
  15406. direction = module.get.direction(),
  15407. transition
  15408. ;
  15409. transition = ( module.is.mobile() )
  15410. ? (settings.mobileTransition == 'auto')
  15411. ? settings.defaultTransition.mobile[direction]
  15412. : settings.mobileTransition
  15413. : (settings.transition == 'auto')
  15414. ? settings.defaultTransition.computer[direction]
  15415. : settings.transition
  15416. ;
  15417. module.verbose('Determined transition', transition);
  15418. return transition;
  15419. },
  15420. transitionEvent: function() {
  15421. var
  15422. element = document.createElement('element'),
  15423. transitions = {
  15424. 'transition' :'transitionend',
  15425. 'OTransition' :'oTransitionEnd',
  15426. 'MozTransition' :'transitionend',
  15427. 'WebkitTransition' :'webkitTransitionEnd'
  15428. },
  15429. transition
  15430. ;
  15431. for(transition in transitions){
  15432. if( element.style[transition] !== undefined ){
  15433. return transitions[transition];
  15434. }
  15435. }
  15436. }
  15437. },
  15438. is: {
  15439. ie: function() {
  15440. var
  15441. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  15442. isIE = ('ActiveXObject' in window)
  15443. ;
  15444. return (isIE11 || isIE);
  15445. },
  15446. ios: function() {
  15447. var
  15448. userAgent = navigator.userAgent,
  15449. isIOS = userAgent.match(regExp.ios),
  15450. isMobileChrome = userAgent.match(regExp.mobileChrome)
  15451. ;
  15452. if(isIOS && !isMobileChrome) {
  15453. module.verbose('Browser was found to be iOS', userAgent);
  15454. return true;
  15455. }
  15456. else {
  15457. return false;
  15458. }
  15459. },
  15460. mobile: function() {
  15461. var
  15462. userAgent = navigator.userAgent,
  15463. isMobile = userAgent.match(regExp.mobile)
  15464. ;
  15465. if(isMobile) {
  15466. module.verbose('Browser was found to be mobile', userAgent);
  15467. return true;
  15468. }
  15469. else {
  15470. module.verbose('Browser is not mobile, using regular transition', userAgent);
  15471. return false;
  15472. }
  15473. },
  15474. hidden: function() {
  15475. return !module.is.visible();
  15476. },
  15477. visible: function() {
  15478. return $module.hasClass(className.visible);
  15479. },
  15480. // alias
  15481. open: function() {
  15482. return module.is.visible();
  15483. },
  15484. closed: function() {
  15485. return module.is.hidden();
  15486. },
  15487. vertical: function() {
  15488. return $module.hasClass(className.top);
  15489. },
  15490. animating: function() {
  15491. return $context.hasClass(className.animating);
  15492. },
  15493. rtl: function () {
  15494. if(module.cache.rtl === undefined) {
  15495. module.cache.rtl = ($module.css('direction') == 'rtl');
  15496. }
  15497. return module.cache.rtl;
  15498. }
  15499. },
  15500. setting: function(name, value) {
  15501. module.debug('Changing setting', name, value);
  15502. if( $.isPlainObject(name) ) {
  15503. $.extend(true, settings, name);
  15504. }
  15505. else if(value !== undefined) {
  15506. if($.isPlainObject(settings[name])) {
  15507. $.extend(true, settings[name], value);
  15508. }
  15509. else {
  15510. settings[name] = value;
  15511. }
  15512. }
  15513. else {
  15514. return settings[name];
  15515. }
  15516. },
  15517. internal: function(name, value) {
  15518. if( $.isPlainObject(name) ) {
  15519. $.extend(true, module, name);
  15520. }
  15521. else if(value !== undefined) {
  15522. module[name] = value;
  15523. }
  15524. else {
  15525. return module[name];
  15526. }
  15527. },
  15528. debug: function() {
  15529. if(!settings.silent && settings.debug) {
  15530. if(settings.performance) {
  15531. module.performance.log(arguments);
  15532. }
  15533. else {
  15534. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15535. module.debug.apply(console, arguments);
  15536. }
  15537. }
  15538. },
  15539. verbose: function() {
  15540. if(!settings.silent && settings.verbose && settings.debug) {
  15541. if(settings.performance) {
  15542. module.performance.log(arguments);
  15543. }
  15544. else {
  15545. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15546. module.verbose.apply(console, arguments);
  15547. }
  15548. }
  15549. },
  15550. error: function() {
  15551. if(!settings.silent) {
  15552. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  15553. module.error.apply(console, arguments);
  15554. }
  15555. },
  15556. performance: {
  15557. log: function(message) {
  15558. var
  15559. currentTime,
  15560. executionTime,
  15561. previousTime
  15562. ;
  15563. if(settings.performance) {
  15564. currentTime = new Date().getTime();
  15565. previousTime = time || currentTime;
  15566. executionTime = currentTime - previousTime;
  15567. time = currentTime;
  15568. performance.push({
  15569. 'Name' : message[0],
  15570. 'Arguments' : [].slice.call(message, 1) || '',
  15571. 'Element' : element,
  15572. 'Execution Time' : executionTime
  15573. });
  15574. }
  15575. clearTimeout(module.performance.timer);
  15576. module.performance.timer = setTimeout(module.performance.display, 500);
  15577. },
  15578. display: function() {
  15579. var
  15580. title = settings.name + ':',
  15581. totalTime = 0
  15582. ;
  15583. time = false;
  15584. clearTimeout(module.performance.timer);
  15585. $.each(performance, function(index, data) {
  15586. totalTime += data['Execution Time'];
  15587. });
  15588. title += ' ' + totalTime + 'ms';
  15589. if(moduleSelector) {
  15590. title += ' \'' + moduleSelector + '\'';
  15591. }
  15592. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  15593. console.groupCollapsed(title);
  15594. if(console.table) {
  15595. console.table(performance);
  15596. }
  15597. else {
  15598. $.each(performance, function(index, data) {
  15599. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  15600. });
  15601. }
  15602. console.groupEnd();
  15603. }
  15604. performance = [];
  15605. }
  15606. },
  15607. invoke: function(query, passedArguments, context) {
  15608. var
  15609. object = instance,
  15610. maxDepth,
  15611. found,
  15612. response
  15613. ;
  15614. passedArguments = passedArguments || queryArguments;
  15615. context = element || context;
  15616. if(typeof query == 'string' && object !== undefined) {
  15617. query = query.split(/[\. ]/);
  15618. maxDepth = query.length - 1;
  15619. $.each(query, function(depth, value) {
  15620. var camelCaseValue = (depth != maxDepth)
  15621. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  15622. : query
  15623. ;
  15624. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  15625. object = object[camelCaseValue];
  15626. }
  15627. else if( object[camelCaseValue] !== undefined ) {
  15628. found = object[camelCaseValue];
  15629. return false;
  15630. }
  15631. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  15632. object = object[value];
  15633. }
  15634. else if( object[value] !== undefined ) {
  15635. found = object[value];
  15636. return false;
  15637. }
  15638. else {
  15639. module.error(error.method, query);
  15640. return false;
  15641. }
  15642. });
  15643. }
  15644. if ( $.isFunction( found ) ) {
  15645. response = found.apply(context, passedArguments);
  15646. }
  15647. else if(found !== undefined) {
  15648. response = found;
  15649. }
  15650. if($.isArray(returnedValue)) {
  15651. returnedValue.push(response);
  15652. }
  15653. else if(returnedValue !== undefined) {
  15654. returnedValue = [returnedValue, response];
  15655. }
  15656. else if(response !== undefined) {
  15657. returnedValue = response;
  15658. }
  15659. return found;
  15660. }
  15661. }
  15662. ;
  15663. if(methodInvoked) {
  15664. if(instance === undefined) {
  15665. module.initialize();
  15666. }
  15667. module.invoke(query);
  15668. }
  15669. else {
  15670. if(instance !== undefined) {
  15671. module.invoke('destroy');
  15672. }
  15673. module.initialize();
  15674. }
  15675. });
  15676. return (returnedValue !== undefined)
  15677. ? returnedValue
  15678. : this
  15679. ;
  15680. };
  15681. $.fn.sidebar.settings = {
  15682. name : 'Sidebar',
  15683. namespace : 'sidebar',
  15684. silent : false,
  15685. debug : false,
  15686. verbose : false,
  15687. performance : true,
  15688. transition : 'auto',
  15689. mobileTransition : 'auto',
  15690. defaultTransition : {
  15691. computer: {
  15692. left : 'uncover',
  15693. right : 'uncover',
  15694. top : 'overlay',
  15695. bottom : 'overlay'
  15696. },
  15697. mobile: {
  15698. left : 'uncover',
  15699. right : 'uncover',
  15700. top : 'overlay',
  15701. bottom : 'overlay'
  15702. }
  15703. },
  15704. context : 'body',
  15705. exclusive : false,
  15706. closable : true,
  15707. dimPage : true,
  15708. scrollLock : false,
  15709. returnScroll : false,
  15710. delaySetup : false,
  15711. duration : 500,
  15712. onChange : function(){},
  15713. onShow : function(){},
  15714. onHide : function(){},
  15715. onHidden : function(){},
  15716. onVisible : function(){},
  15717. className : {
  15718. active : 'active',
  15719. animating : 'animating',
  15720. dimmed : 'dimmed',
  15721. ios : 'ios',
  15722. pushable : 'pushable',
  15723. pushed : 'pushed',
  15724. right : 'right',
  15725. top : 'top',
  15726. left : 'left',
  15727. bottom : 'bottom',
  15728. visible : 'visible'
  15729. },
  15730. selector: {
  15731. fixed : '.fixed',
  15732. omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
  15733. pusher : '.pusher',
  15734. sidebar : '.ui.sidebar'
  15735. },
  15736. regExp: {
  15737. ios : /(iPad|iPhone|iPod)/g,
  15738. mobileChrome : /(CriOS)/g,
  15739. 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
  15740. },
  15741. error : {
  15742. method : 'The method you called is not defined.',
  15743. pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
  15744. movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
  15745. overlay : 'The overlay setting is no longer supported, use animation: overlay',
  15746. notFound : 'There were no elements that matched the specified selector'
  15747. }
  15748. };
  15749. })( jQuery, window, document );
  15750. /*!
  15751. * # Semantic UI 2.3.0 - Sticky
  15752. * http://github.com/semantic-org/semantic-ui/
  15753. *
  15754. *
  15755. * Released under the MIT license
  15756. * http://opensource.org/licenses/MIT
  15757. *
  15758. */
  15759. ;(function ($, window, document, undefined) {
  15760. "use strict";
  15761. window = (typeof window != 'undefined' && window.Math == Math)
  15762. ? window
  15763. : (typeof self != 'undefined' && self.Math == Math)
  15764. ? self
  15765. : Function('return this')()
  15766. ;
  15767. $.fn.sticky = function(parameters) {
  15768. var
  15769. $allModules = $(this),
  15770. moduleSelector = $allModules.selector || '',
  15771. time = new Date().getTime(),
  15772. performance = [],
  15773. query = arguments[0],
  15774. methodInvoked = (typeof query == 'string'),
  15775. queryArguments = [].slice.call(arguments, 1),
  15776. returnedValue
  15777. ;
  15778. $allModules
  15779. .each(function() {
  15780. var
  15781. settings = ( $.isPlainObject(parameters) )
  15782. ? $.extend(true, {}, $.fn.sticky.settings, parameters)
  15783. : $.extend({}, $.fn.sticky.settings),
  15784. className = settings.className,
  15785. namespace = settings.namespace,
  15786. error = settings.error,
  15787. eventNamespace = '.' + namespace,
  15788. moduleNamespace = 'module-' + namespace,
  15789. $module = $(this),
  15790. $window = $(window),
  15791. $scroll = $(settings.scrollContext),
  15792. $container,
  15793. $context,
  15794. selector = $module.selector || '',
  15795. instance = $module.data(moduleNamespace),
  15796. requestAnimationFrame = window.requestAnimationFrame
  15797. || window.mozRequestAnimationFrame
  15798. || window.webkitRequestAnimationFrame
  15799. || window.msRequestAnimationFrame
  15800. || function(callback) { setTimeout(callback, 0); },
  15801. element = this,
  15802. documentObserver,
  15803. observer,
  15804. module
  15805. ;
  15806. module = {
  15807. initialize: function() {
  15808. module.determineContainer();
  15809. module.determineContext();
  15810. module.verbose('Initializing sticky', settings, $container);
  15811. module.save.positions();
  15812. module.checkErrors();
  15813. module.bind.events();
  15814. if(settings.observeChanges) {
  15815. module.observeChanges();
  15816. }
  15817. module.instantiate();
  15818. },
  15819. instantiate: function() {
  15820. module.verbose('Storing instance of module', module);
  15821. instance = module;
  15822. $module
  15823. .data(moduleNamespace, module)
  15824. ;
  15825. },
  15826. destroy: function() {
  15827. module.verbose('Destroying previous instance');
  15828. module.reset();
  15829. if(documentObserver) {
  15830. documentObserver.disconnect();
  15831. }
  15832. if(observer) {
  15833. observer.disconnect();
  15834. }
  15835. $window
  15836. .off('load' + eventNamespace, module.event.load)
  15837. .off('resize' + eventNamespace, module.event.resize)
  15838. ;
  15839. $scroll
  15840. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  15841. ;
  15842. $module.removeData(moduleNamespace);
  15843. },
  15844. observeChanges: function() {
  15845. if('MutationObserver' in window) {
  15846. documentObserver = new MutationObserver(module.event.documentChanged);
  15847. observer = new MutationObserver(module.event.changed);
  15848. documentObserver.observe(document, {
  15849. childList : true,
  15850. subtree : true
  15851. });
  15852. observer.observe(element, {
  15853. childList : true,
  15854. subtree : true
  15855. });
  15856. observer.observe($context[0], {
  15857. childList : true,
  15858. subtree : true
  15859. });
  15860. module.debug('Setting up mutation observer', observer);
  15861. }
  15862. },
  15863. determineContainer: function() {
  15864. if(settings.container) {
  15865. $container = $(settings.container);
  15866. }
  15867. else {
  15868. $container = $module.offsetParent();
  15869. }
  15870. },
  15871. determineContext: function() {
  15872. if(settings.context) {
  15873. $context = $(settings.context);
  15874. }
  15875. else {
  15876. $context = $container;
  15877. }
  15878. if($context.length === 0) {
  15879. module.error(error.invalidContext, settings.context, $module);
  15880. return;
  15881. }
  15882. },
  15883. checkErrors: function() {
  15884. if( module.is.hidden() ) {
  15885. module.error(error.visible, $module);
  15886. }
  15887. if(module.cache.element.height > module.cache.context.height) {
  15888. module.reset();
  15889. module.error(error.elementSize, $module);
  15890. return;
  15891. }
  15892. },
  15893. bind: {
  15894. events: function() {
  15895. $window
  15896. .on('load' + eventNamespace, module.event.load)
  15897. .on('resize' + eventNamespace, module.event.resize)
  15898. ;
  15899. // pub/sub pattern
  15900. $scroll
  15901. .off('scroll' + eventNamespace)
  15902. .on('scroll' + eventNamespace, module.event.scroll)
  15903. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  15904. ;
  15905. }
  15906. },
  15907. event: {
  15908. changed: function(mutations) {
  15909. clearTimeout(module.timer);
  15910. module.timer = setTimeout(function() {
  15911. module.verbose('DOM tree modified, updating sticky menu', mutations);
  15912. module.refresh();
  15913. }, 100);
  15914. },
  15915. documentChanged: function(mutations) {
  15916. [].forEach.call(mutations, function(mutation) {
  15917. if(mutation.removedNodes) {
  15918. [].forEach.call(mutation.removedNodes, function(node) {
  15919. if(node == element || $(node).find(element).length > 0) {
  15920. module.debug('Element removed from DOM, tearing down events');
  15921. module.destroy();
  15922. }
  15923. });
  15924. }
  15925. });
  15926. },
  15927. load: function() {
  15928. module.verbose('Page contents finished loading');
  15929. requestAnimationFrame(module.refresh);
  15930. },
  15931. resize: function() {
  15932. module.verbose('Window resized');
  15933. requestAnimationFrame(module.refresh);
  15934. },
  15935. scroll: function() {
  15936. requestAnimationFrame(function() {
  15937. $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
  15938. });
  15939. },
  15940. scrollchange: function(event, scrollPosition) {
  15941. module.stick(scrollPosition);
  15942. settings.onScroll.call(element);
  15943. }
  15944. },
  15945. refresh: function(hardRefresh) {
  15946. module.reset();
  15947. if(!settings.context) {
  15948. module.determineContext();
  15949. }
  15950. if(hardRefresh) {
  15951. module.determineContainer();
  15952. }
  15953. module.save.positions();
  15954. module.stick();
  15955. settings.onReposition.call(element);
  15956. },
  15957. supports: {
  15958. sticky: function() {
  15959. var
  15960. $element = $('<div/>'),
  15961. element = $element[0]
  15962. ;
  15963. $element.addClass(className.supported);
  15964. return($element.css('position').match('sticky'));
  15965. }
  15966. },
  15967. save: {
  15968. lastScroll: function(scroll) {
  15969. module.lastScroll = scroll;
  15970. },
  15971. elementScroll: function(scroll) {
  15972. module.elementScroll = scroll;
  15973. },
  15974. positions: function() {
  15975. var
  15976. scrollContext = {
  15977. height : $scroll.height()
  15978. },
  15979. element = {
  15980. margin: {
  15981. top : parseInt($module.css('margin-top'), 10),
  15982. bottom : parseInt($module.css('margin-bottom'), 10),
  15983. },
  15984. offset : $module.offset(),
  15985. width : $module.outerWidth(),
  15986. height : $module.outerHeight()
  15987. },
  15988. context = {
  15989. offset : $context.offset(),
  15990. height : $context.outerHeight()
  15991. },
  15992. container = {
  15993. height: $container.outerHeight()
  15994. }
  15995. ;
  15996. if( !module.is.standardScroll() ) {
  15997. module.debug('Non-standard scroll. Removing scroll offset from element offset');
  15998. scrollContext.top = $scroll.scrollTop();
  15999. scrollContext.left = $scroll.scrollLeft();
  16000. element.offset.top += scrollContext.top;
  16001. context.offset.top += scrollContext.top;
  16002. element.offset.left += scrollContext.left;
  16003. context.offset.left += scrollContext.left;
  16004. }
  16005. module.cache = {
  16006. fits : ( (element.height + settings.offset) <= scrollContext.height),
  16007. sameHeight : (element.height == context.height),
  16008. scrollContext : {
  16009. height : scrollContext.height
  16010. },
  16011. element: {
  16012. margin : element.margin,
  16013. top : element.offset.top - element.margin.top,
  16014. left : element.offset.left,
  16015. width : element.width,
  16016. height : element.height,
  16017. bottom : element.offset.top + element.height
  16018. },
  16019. context: {
  16020. top : context.offset.top,
  16021. height : context.height,
  16022. bottom : context.offset.top + context.height
  16023. }
  16024. };
  16025. module.set.containerSize();
  16026. module.stick();
  16027. module.debug('Caching element positions', module.cache);
  16028. }
  16029. },
  16030. get: {
  16031. direction: function(scroll) {
  16032. var
  16033. direction = 'down'
  16034. ;
  16035. scroll = scroll || $scroll.scrollTop();
  16036. if(module.lastScroll !== undefined) {
  16037. if(module.lastScroll < scroll) {
  16038. direction = 'down';
  16039. }
  16040. else if(module.lastScroll > scroll) {
  16041. direction = 'up';
  16042. }
  16043. }
  16044. return direction;
  16045. },
  16046. scrollChange: function(scroll) {
  16047. scroll = scroll || $scroll.scrollTop();
  16048. return (module.lastScroll)
  16049. ? (scroll - module.lastScroll)
  16050. : 0
  16051. ;
  16052. },
  16053. currentElementScroll: function() {
  16054. if(module.elementScroll) {
  16055. return module.elementScroll;
  16056. }
  16057. return ( module.is.top() )
  16058. ? Math.abs(parseInt($module.css('top'), 10)) || 0
  16059. : Math.abs(parseInt($module.css('bottom'), 10)) || 0
  16060. ;
  16061. },
  16062. elementScroll: function(scroll) {
  16063. scroll = scroll || $scroll.scrollTop();
  16064. var
  16065. element = module.cache.element,
  16066. scrollContext = module.cache.scrollContext,
  16067. delta = module.get.scrollChange(scroll),
  16068. maxScroll = (element.height - scrollContext.height + settings.offset),
  16069. elementScroll = module.get.currentElementScroll(),
  16070. possibleScroll = (elementScroll + delta)
  16071. ;
  16072. if(module.cache.fits || possibleScroll < 0) {
  16073. elementScroll = 0;
  16074. }
  16075. else if(possibleScroll > maxScroll ) {
  16076. elementScroll = maxScroll;
  16077. }
  16078. else {
  16079. elementScroll = possibleScroll;
  16080. }
  16081. return elementScroll;
  16082. }
  16083. },
  16084. remove: {
  16085. lastScroll: function() {
  16086. delete module.lastScroll;
  16087. },
  16088. elementScroll: function(scroll) {
  16089. delete module.elementScroll;
  16090. },
  16091. minimumSize: function() {
  16092. $container
  16093. .css('min-height', '')
  16094. ;
  16095. },
  16096. offset: function() {
  16097. $module.css('margin-top', '');
  16098. }
  16099. },
  16100. set: {
  16101. offset: function() {
  16102. module.verbose('Setting offset on element', settings.offset);
  16103. $module
  16104. .css('margin-top', settings.offset)
  16105. ;
  16106. },
  16107. containerSize: function() {
  16108. var
  16109. tagName = $container.get(0).tagName
  16110. ;
  16111. if(tagName === 'HTML' || tagName == 'body') {
  16112. // this can trigger for too many reasons
  16113. //module.error(error.container, tagName, $module);
  16114. module.determineContainer();
  16115. }
  16116. else {
  16117. if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
  16118. module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
  16119. $container.css({
  16120. height: module.cache.context.height
  16121. });
  16122. }
  16123. }
  16124. },
  16125. minimumSize: function() {
  16126. var
  16127. element = module.cache.element
  16128. ;
  16129. $container
  16130. .css('min-height', element.height)
  16131. ;
  16132. },
  16133. scroll: function(scroll) {
  16134. module.debug('Setting scroll on element', scroll);
  16135. if(module.elementScroll == scroll) {
  16136. return;
  16137. }
  16138. if( module.is.top() ) {
  16139. $module
  16140. .css('bottom', '')
  16141. .css('top', -scroll)
  16142. ;
  16143. }
  16144. if( module.is.bottom() ) {
  16145. $module
  16146. .css('top', '')
  16147. .css('bottom', scroll)
  16148. ;
  16149. }
  16150. },
  16151. size: function() {
  16152. if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
  16153. element.style.setProperty('width', module.cache.element.width + 'px', 'important');
  16154. element.style.setProperty('height', module.cache.element.height + 'px', 'important');
  16155. }
  16156. }
  16157. },
  16158. is: {
  16159. standardScroll: function() {
  16160. return ($scroll[0] == window);
  16161. },
  16162. top: function() {
  16163. return $module.hasClass(className.top);
  16164. },
  16165. bottom: function() {
  16166. return $module.hasClass(className.bottom);
  16167. },
  16168. initialPosition: function() {
  16169. return (!module.is.fixed() && !module.is.bound());
  16170. },
  16171. hidden: function() {
  16172. return (!$module.is(':visible'));
  16173. },
  16174. bound: function() {
  16175. return $module.hasClass(className.bound);
  16176. },
  16177. fixed: function() {
  16178. return $module.hasClass(className.fixed);
  16179. }
  16180. },
  16181. stick: function(scroll) {
  16182. var
  16183. cachedPosition = scroll || $scroll.scrollTop(),
  16184. cache = module.cache,
  16185. fits = cache.fits,
  16186. sameHeight = cache.sameHeight,
  16187. element = cache.element,
  16188. scrollContext = cache.scrollContext,
  16189. context = cache.context,
  16190. offset = (module.is.bottom() && settings.pushing)
  16191. ? settings.bottomOffset
  16192. : settings.offset,
  16193. scroll = {
  16194. top : cachedPosition + offset,
  16195. bottom : cachedPosition + offset + scrollContext.height
  16196. },
  16197. direction = module.get.direction(scroll.top),
  16198. elementScroll = (fits)
  16199. ? 0
  16200. : module.get.elementScroll(scroll.top),
  16201. // shorthand
  16202. doesntFit = !fits,
  16203. elementVisible = (element.height !== 0)
  16204. ;
  16205. if(elementVisible && !sameHeight) {
  16206. if( module.is.initialPosition() ) {
  16207. if(scroll.top >= context.bottom) {
  16208. module.debug('Initial element position is bottom of container');
  16209. module.bindBottom();
  16210. }
  16211. else if(scroll.top > element.top) {
  16212. if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  16213. module.debug('Initial element position is bottom of container');
  16214. module.bindBottom();
  16215. }
  16216. else {
  16217. module.debug('Initial element position is fixed');
  16218. module.fixTop();
  16219. }
  16220. }
  16221. }
  16222. else if( module.is.fixed() ) {
  16223. // currently fixed top
  16224. if( module.is.top() ) {
  16225. if( scroll.top <= element.top ) {
  16226. module.debug('Fixed element reached top of container');
  16227. module.setInitialPosition();
  16228. }
  16229. else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  16230. module.debug('Fixed element reached bottom of container');
  16231. module.bindBottom();
  16232. }
  16233. // scroll element if larger than screen
  16234. else if(doesntFit) {
  16235. module.set.scroll(elementScroll);
  16236. module.save.lastScroll(scroll.top);
  16237. module.save.elementScroll(elementScroll);
  16238. }
  16239. }
  16240. // currently fixed bottom
  16241. else if(module.is.bottom() ) {
  16242. // top edge
  16243. if( (scroll.bottom - element.height) <= element.top) {
  16244. module.debug('Bottom fixed rail has reached top of container');
  16245. module.setInitialPosition();
  16246. }
  16247. // bottom edge
  16248. else if(scroll.bottom >= context.bottom) {
  16249. module.debug('Bottom fixed rail has reached bottom of container');
  16250. module.bindBottom();
  16251. }
  16252. // scroll element if larger than screen
  16253. else if(doesntFit) {
  16254. module.set.scroll(elementScroll);
  16255. module.save.lastScroll(scroll.top);
  16256. module.save.elementScroll(elementScroll);
  16257. }
  16258. }
  16259. }
  16260. else if( module.is.bottom() ) {
  16261. if( scroll.top <= element.top ) {
  16262. module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
  16263. module.setInitialPosition();
  16264. }
  16265. else {
  16266. if(settings.pushing) {
  16267. if(module.is.bound() && scroll.bottom <= context.bottom ) {
  16268. module.debug('Fixing bottom attached element to bottom of browser.');
  16269. module.fixBottom();
  16270. }
  16271. }
  16272. else {
  16273. if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
  16274. module.debug('Fixing bottom attached element to top of browser.');
  16275. module.fixTop();
  16276. }
  16277. }
  16278. }
  16279. }
  16280. }
  16281. },
  16282. bindTop: function() {
  16283. module.debug('Binding element to top of parent container');
  16284. module.remove.offset();
  16285. $module
  16286. .css({
  16287. left : '',
  16288. top : '',
  16289. marginBottom : ''
  16290. })
  16291. .removeClass(className.fixed)
  16292. .removeClass(className.bottom)
  16293. .addClass(className.bound)
  16294. .addClass(className.top)
  16295. ;
  16296. settings.onTop.call(element);
  16297. settings.onUnstick.call(element);
  16298. },
  16299. bindBottom: function() {
  16300. module.debug('Binding element to bottom of parent container');
  16301. module.remove.offset();
  16302. $module
  16303. .css({
  16304. left : '',
  16305. top : ''
  16306. })
  16307. .removeClass(className.fixed)
  16308. .removeClass(className.top)
  16309. .addClass(className.bound)
  16310. .addClass(className.bottom)
  16311. ;
  16312. settings.onBottom.call(element);
  16313. settings.onUnstick.call(element);
  16314. },
  16315. setInitialPosition: function() {
  16316. module.debug('Returning to initial position');
  16317. module.unfix();
  16318. module.unbind();
  16319. },
  16320. fixTop: function() {
  16321. module.debug('Fixing element to top of page');
  16322. if(settings.setSize) {
  16323. module.set.size();
  16324. }
  16325. module.set.minimumSize();
  16326. module.set.offset();
  16327. $module
  16328. .css({
  16329. left : module.cache.element.left,
  16330. bottom : '',
  16331. marginBottom : ''
  16332. })
  16333. .removeClass(className.bound)
  16334. .removeClass(className.bottom)
  16335. .addClass(className.fixed)
  16336. .addClass(className.top)
  16337. ;
  16338. settings.onStick.call(element);
  16339. },
  16340. fixBottom: function() {
  16341. module.debug('Sticking element to bottom of page');
  16342. if(settings.setSize) {
  16343. module.set.size();
  16344. }
  16345. module.set.minimumSize();
  16346. module.set.offset();
  16347. $module
  16348. .css({
  16349. left : module.cache.element.left,
  16350. bottom : '',
  16351. marginBottom : ''
  16352. })
  16353. .removeClass(className.bound)
  16354. .removeClass(className.top)
  16355. .addClass(className.fixed)
  16356. .addClass(className.bottom)
  16357. ;
  16358. settings.onStick.call(element);
  16359. },
  16360. unbind: function() {
  16361. if( module.is.bound() ) {
  16362. module.debug('Removing container bound position on element');
  16363. module.remove.offset();
  16364. $module
  16365. .removeClass(className.bound)
  16366. .removeClass(className.top)
  16367. .removeClass(className.bottom)
  16368. ;
  16369. }
  16370. },
  16371. unfix: function() {
  16372. if( module.is.fixed() ) {
  16373. module.debug('Removing fixed position on element');
  16374. module.remove.minimumSize();
  16375. module.remove.offset();
  16376. $module
  16377. .removeClass(className.fixed)
  16378. .removeClass(className.top)
  16379. .removeClass(className.bottom)
  16380. ;
  16381. settings.onUnstick.call(element);
  16382. }
  16383. },
  16384. reset: function() {
  16385. module.debug('Resetting elements position');
  16386. module.unbind();
  16387. module.unfix();
  16388. module.resetCSS();
  16389. module.remove.offset();
  16390. module.remove.lastScroll();
  16391. },
  16392. resetCSS: function() {
  16393. $module
  16394. .css({
  16395. width : '',
  16396. height : ''
  16397. })
  16398. ;
  16399. $container
  16400. .css({
  16401. height: ''
  16402. })
  16403. ;
  16404. },
  16405. setting: function(name, value) {
  16406. if( $.isPlainObject(name) ) {
  16407. $.extend(true, settings, name);
  16408. }
  16409. else if(value !== undefined) {
  16410. settings[name] = value;
  16411. }
  16412. else {
  16413. return settings[name];
  16414. }
  16415. },
  16416. internal: function(name, value) {
  16417. if( $.isPlainObject(name) ) {
  16418. $.extend(true, module, name);
  16419. }
  16420. else if(value !== undefined) {
  16421. module[name] = value;
  16422. }
  16423. else {
  16424. return module[name];
  16425. }
  16426. },
  16427. debug: function() {
  16428. if(!settings.silent && settings.debug) {
  16429. if(settings.performance) {
  16430. module.performance.log(arguments);
  16431. }
  16432. else {
  16433. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16434. module.debug.apply(console, arguments);
  16435. }
  16436. }
  16437. },
  16438. verbose: function() {
  16439. if(!settings.silent && settings.verbose && settings.debug) {
  16440. if(settings.performance) {
  16441. module.performance.log(arguments);
  16442. }
  16443. else {
  16444. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16445. module.verbose.apply(console, arguments);
  16446. }
  16447. }
  16448. },
  16449. error: function() {
  16450. if(!settings.silent) {
  16451. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  16452. module.error.apply(console, arguments);
  16453. }
  16454. },
  16455. performance: {
  16456. log: function(message) {
  16457. var
  16458. currentTime,
  16459. executionTime,
  16460. previousTime
  16461. ;
  16462. if(settings.performance) {
  16463. currentTime = new Date().getTime();
  16464. previousTime = time || currentTime;
  16465. executionTime = currentTime - previousTime;
  16466. time = currentTime;
  16467. performance.push({
  16468. 'Name' : message[0],
  16469. 'Arguments' : [].slice.call(message, 1) || '',
  16470. 'Element' : element,
  16471. 'Execution Time' : executionTime
  16472. });
  16473. }
  16474. clearTimeout(module.performance.timer);
  16475. module.performance.timer = setTimeout(module.performance.display, 0);
  16476. },
  16477. display: function() {
  16478. var
  16479. title = settings.name + ':',
  16480. totalTime = 0
  16481. ;
  16482. time = false;
  16483. clearTimeout(module.performance.timer);
  16484. $.each(performance, function(index, data) {
  16485. totalTime += data['Execution Time'];
  16486. });
  16487. title += ' ' + totalTime + 'ms';
  16488. if(moduleSelector) {
  16489. title += ' \'' + moduleSelector + '\'';
  16490. }
  16491. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  16492. console.groupCollapsed(title);
  16493. if(console.table) {
  16494. console.table(performance);
  16495. }
  16496. else {
  16497. $.each(performance, function(index, data) {
  16498. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  16499. });
  16500. }
  16501. console.groupEnd();
  16502. }
  16503. performance = [];
  16504. }
  16505. },
  16506. invoke: function(query, passedArguments, context) {
  16507. var
  16508. object = instance,
  16509. maxDepth,
  16510. found,
  16511. response
  16512. ;
  16513. passedArguments = passedArguments || queryArguments;
  16514. context = element || context;
  16515. if(typeof query == 'string' && object !== undefined) {
  16516. query = query.split(/[\. ]/);
  16517. maxDepth = query.length - 1;
  16518. $.each(query, function(depth, value) {
  16519. var camelCaseValue = (depth != maxDepth)
  16520. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  16521. : query
  16522. ;
  16523. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  16524. object = object[camelCaseValue];
  16525. }
  16526. else if( object[camelCaseValue] !== undefined ) {
  16527. found = object[camelCaseValue];
  16528. return false;
  16529. }
  16530. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  16531. object = object[value];
  16532. }
  16533. else if( object[value] !== undefined ) {
  16534. found = object[value];
  16535. return false;
  16536. }
  16537. else {
  16538. return false;
  16539. }
  16540. });
  16541. }
  16542. if ( $.isFunction( found ) ) {
  16543. response = found.apply(context, passedArguments);
  16544. }
  16545. else if(found !== undefined) {
  16546. response = found;
  16547. }
  16548. if($.isArray(returnedValue)) {
  16549. returnedValue.push(response);
  16550. }
  16551. else if(returnedValue !== undefined) {
  16552. returnedValue = [returnedValue, response];
  16553. }
  16554. else if(response !== undefined) {
  16555. returnedValue = response;
  16556. }
  16557. return found;
  16558. }
  16559. };
  16560. if(methodInvoked) {
  16561. if(instance === undefined) {
  16562. module.initialize();
  16563. }
  16564. module.invoke(query);
  16565. }
  16566. else {
  16567. if(instance !== undefined) {
  16568. instance.invoke('destroy');
  16569. }
  16570. module.initialize();
  16571. }
  16572. })
  16573. ;
  16574. return (returnedValue !== undefined)
  16575. ? returnedValue
  16576. : this
  16577. ;
  16578. };
  16579. $.fn.sticky.settings = {
  16580. name : 'Sticky',
  16581. namespace : 'sticky',
  16582. silent : false,
  16583. debug : false,
  16584. verbose : true,
  16585. performance : true,
  16586. // whether to stick in the opposite direction on scroll up
  16587. pushing : false,
  16588. context : false,
  16589. container : false,
  16590. // Context to watch scroll events
  16591. scrollContext : window,
  16592. // Offset to adjust scroll
  16593. offset : 0,
  16594. // Offset to adjust scroll when attached to bottom of screen
  16595. bottomOffset : 0,
  16596. // will only set container height if difference between context and container is larger than this number
  16597. jitter : 5,
  16598. // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
  16599. setSize : true,
  16600. // Whether to automatically observe changes with Mutation Observers
  16601. observeChanges : false,
  16602. // Called when position is recalculated
  16603. onReposition : function(){},
  16604. // Called on each scroll
  16605. onScroll : function(){},
  16606. // Called when element is stuck to viewport
  16607. onStick : function(){},
  16608. // Called when element is unstuck from viewport
  16609. onUnstick : function(){},
  16610. // Called when element reaches top of context
  16611. onTop : function(){},
  16612. // Called when element reaches bottom of context
  16613. onBottom : function(){},
  16614. error : {
  16615. container : 'Sticky element must be inside a relative container',
  16616. visible : 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to surpress this warning in production.',
  16617. method : 'The method you called is not defined.',
  16618. invalidContext : 'Context specified does not exist',
  16619. elementSize : 'Sticky element is larger than its container, cannot create sticky.'
  16620. },
  16621. className : {
  16622. bound : 'bound',
  16623. fixed : 'fixed',
  16624. supported : 'native',
  16625. top : 'top',
  16626. bottom : 'bottom'
  16627. }
  16628. };
  16629. })( jQuery, window, document );
  16630. /*!
  16631. * # Semantic UI 2.3.0 - Tab
  16632. * http://github.com/semantic-org/semantic-ui/
  16633. *
  16634. *
  16635. * Released under the MIT license
  16636. * http://opensource.org/licenses/MIT
  16637. *
  16638. */
  16639. ;(function ($, window, document, undefined) {
  16640. "use strict";
  16641. window = (typeof window != 'undefined' && window.Math == Math)
  16642. ? window
  16643. : (typeof self != 'undefined' && self.Math == Math)
  16644. ? self
  16645. : Function('return this')()
  16646. ;
  16647. $.fn.tab = function(parameters) {
  16648. var
  16649. // use window context if none specified
  16650. $allModules = $.isFunction(this)
  16651. ? $(window)
  16652. : $(this),
  16653. moduleSelector = $allModules.selector || '',
  16654. time = new Date().getTime(),
  16655. performance = [],
  16656. query = arguments[0],
  16657. methodInvoked = (typeof query == 'string'),
  16658. queryArguments = [].slice.call(arguments, 1),
  16659. initializedHistory = false,
  16660. returnedValue
  16661. ;
  16662. $allModules
  16663. .each(function() {
  16664. var
  16665. settings = ( $.isPlainObject(parameters) )
  16666. ? $.extend(true, {}, $.fn.tab.settings, parameters)
  16667. : $.extend({}, $.fn.tab.settings),
  16668. className = settings.className,
  16669. metadata = settings.metadata,
  16670. selector = settings.selector,
  16671. error = settings.error,
  16672. eventNamespace = '.' + settings.namespace,
  16673. moduleNamespace = 'module-' + settings.namespace,
  16674. $module = $(this),
  16675. $context,
  16676. $tabs,
  16677. cache = {},
  16678. firstLoad = true,
  16679. recursionDepth = 0,
  16680. element = this,
  16681. instance = $module.data(moduleNamespace),
  16682. activeTabPath,
  16683. parameterArray,
  16684. module,
  16685. historyEvent
  16686. ;
  16687. module = {
  16688. initialize: function() {
  16689. module.debug('Initializing tab menu item', $module);
  16690. module.fix.callbacks();
  16691. module.determineTabs();
  16692. module.debug('Determining tabs', settings.context, $tabs);
  16693. // set up automatic routing
  16694. if(settings.auto) {
  16695. module.set.auto();
  16696. }
  16697. module.bind.events();
  16698. if(settings.history && !initializedHistory) {
  16699. module.initializeHistory();
  16700. initializedHistory = true;
  16701. }
  16702. module.instantiate();
  16703. },
  16704. instantiate: function () {
  16705. module.verbose('Storing instance of module', module);
  16706. instance = module;
  16707. $module
  16708. .data(moduleNamespace, module)
  16709. ;
  16710. },
  16711. destroy: function() {
  16712. module.debug('Destroying tabs', $module);
  16713. $module
  16714. .removeData(moduleNamespace)
  16715. .off(eventNamespace)
  16716. ;
  16717. },
  16718. bind: {
  16719. events: function() {
  16720. // if using $.tab don't add events
  16721. if( !$.isWindow( element ) ) {
  16722. module.debug('Attaching tab activation events to element', $module);
  16723. $module
  16724. .on('click' + eventNamespace, module.event.click)
  16725. ;
  16726. }
  16727. }
  16728. },
  16729. determineTabs: function() {
  16730. var
  16731. $reference
  16732. ;
  16733. // determine tab context
  16734. if(settings.context === 'parent') {
  16735. if($module.closest(selector.ui).length > 0) {
  16736. $reference = $module.closest(selector.ui);
  16737. module.verbose('Using closest UI element as parent', $reference);
  16738. }
  16739. else {
  16740. $reference = $module;
  16741. }
  16742. $context = $reference.parent();
  16743. module.verbose('Determined parent element for creating context', $context);
  16744. }
  16745. else if(settings.context) {
  16746. $context = $(settings.context);
  16747. module.verbose('Using selector for tab context', settings.context, $context);
  16748. }
  16749. else {
  16750. $context = $('body');
  16751. }
  16752. // find tabs
  16753. if(settings.childrenOnly) {
  16754. $tabs = $context.children(selector.tabs);
  16755. module.debug('Searching tab context children for tabs', $context, $tabs);
  16756. }
  16757. else {
  16758. $tabs = $context.find(selector.tabs);
  16759. module.debug('Searching tab context for tabs', $context, $tabs);
  16760. }
  16761. },
  16762. fix: {
  16763. callbacks: function() {
  16764. if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
  16765. if(parameters.onTabLoad) {
  16766. parameters.onLoad = parameters.onTabLoad;
  16767. delete parameters.onTabLoad;
  16768. module.error(error.legacyLoad, parameters.onLoad);
  16769. }
  16770. if(parameters.onTabInit) {
  16771. parameters.onFirstLoad = parameters.onTabInit;
  16772. delete parameters.onTabInit;
  16773. module.error(error.legacyInit, parameters.onFirstLoad);
  16774. }
  16775. settings = $.extend(true, {}, $.fn.tab.settings, parameters);
  16776. }
  16777. }
  16778. },
  16779. initializeHistory: function() {
  16780. module.debug('Initializing page state');
  16781. if( $.address === undefined ) {
  16782. module.error(error.state);
  16783. return false;
  16784. }
  16785. else {
  16786. if(settings.historyType == 'state') {
  16787. module.debug('Using HTML5 to manage state');
  16788. if(settings.path !== false) {
  16789. $.address
  16790. .history(true)
  16791. .state(settings.path)
  16792. ;
  16793. }
  16794. else {
  16795. module.error(error.path);
  16796. return false;
  16797. }
  16798. }
  16799. $.address
  16800. .bind('change', module.event.history.change)
  16801. ;
  16802. }
  16803. },
  16804. event: {
  16805. click: function(event) {
  16806. var
  16807. tabPath = $(this).data(metadata.tab)
  16808. ;
  16809. if(tabPath !== undefined) {
  16810. if(settings.history) {
  16811. module.verbose('Updating page state', event);
  16812. $.address.value(tabPath);
  16813. }
  16814. else {
  16815. module.verbose('Changing tab', event);
  16816. module.changeTab(tabPath);
  16817. }
  16818. event.preventDefault();
  16819. }
  16820. else {
  16821. module.debug('No tab specified');
  16822. }
  16823. },
  16824. history: {
  16825. change: function(event) {
  16826. var
  16827. tabPath = event.pathNames.join('/') || module.get.initialPath(),
  16828. pageTitle = settings.templates.determineTitle(tabPath) || false
  16829. ;
  16830. module.performance.display();
  16831. module.debug('History change event', tabPath, event);
  16832. historyEvent = event;
  16833. if(tabPath !== undefined) {
  16834. module.changeTab(tabPath);
  16835. }
  16836. if(pageTitle) {
  16837. $.address.title(pageTitle);
  16838. }
  16839. }
  16840. }
  16841. },
  16842. refresh: function() {
  16843. if(activeTabPath) {
  16844. module.debug('Refreshing tab', activeTabPath);
  16845. module.changeTab(activeTabPath);
  16846. }
  16847. },
  16848. cache: {
  16849. read: function(cacheKey) {
  16850. return (cacheKey !== undefined)
  16851. ? cache[cacheKey]
  16852. : false
  16853. ;
  16854. },
  16855. add: function(cacheKey, content) {
  16856. cacheKey = cacheKey || activeTabPath;
  16857. module.debug('Adding cached content for', cacheKey);
  16858. cache[cacheKey] = content;
  16859. },
  16860. remove: function(cacheKey) {
  16861. cacheKey = cacheKey || activeTabPath;
  16862. module.debug('Removing cached content for', cacheKey);
  16863. delete cache[cacheKey];
  16864. }
  16865. },
  16866. set: {
  16867. auto: function() {
  16868. var
  16869. url = (typeof settings.path == 'string')
  16870. ? settings.path.replace(/\/$/, '') + '/{$tab}'
  16871. : '/{$tab}'
  16872. ;
  16873. module.verbose('Setting up automatic tab retrieval from server', url);
  16874. if($.isPlainObject(settings.apiSettings)) {
  16875. settings.apiSettings.url = url;
  16876. }
  16877. else {
  16878. settings.apiSettings = {
  16879. url: url
  16880. };
  16881. }
  16882. },
  16883. loading: function(tabPath) {
  16884. var
  16885. $tab = module.get.tabElement(tabPath),
  16886. isLoading = $tab.hasClass(className.loading)
  16887. ;
  16888. if(!isLoading) {
  16889. module.verbose('Setting loading state for', $tab);
  16890. $tab
  16891. .addClass(className.loading)
  16892. .siblings($tabs)
  16893. .removeClass(className.active + ' ' + className.loading)
  16894. ;
  16895. if($tab.length > 0) {
  16896. settings.onRequest.call($tab[0], tabPath);
  16897. }
  16898. }
  16899. },
  16900. state: function(state) {
  16901. $.address.value(state);
  16902. }
  16903. },
  16904. changeTab: function(tabPath) {
  16905. var
  16906. pushStateAvailable = (window.history && window.history.pushState),
  16907. shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
  16908. remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
  16909. // only add default path if not remote content
  16910. pathArray = (remoteContent && !shouldIgnoreLoad)
  16911. ? module.utilities.pathToArray(tabPath)
  16912. : module.get.defaultPathArray(tabPath)
  16913. ;
  16914. tabPath = module.utilities.arrayToPath(pathArray);
  16915. $.each(pathArray, function(index, tab) {
  16916. var
  16917. currentPathArray = pathArray.slice(0, index + 1),
  16918. currentPath = module.utilities.arrayToPath(currentPathArray),
  16919. isTab = module.is.tab(currentPath),
  16920. isLastIndex = (index + 1 == pathArray.length),
  16921. $tab = module.get.tabElement(currentPath),
  16922. $anchor,
  16923. nextPathArray,
  16924. nextPath,
  16925. isLastTab
  16926. ;
  16927. module.verbose('Looking for tab', tab);
  16928. if(isTab) {
  16929. module.verbose('Tab was found', tab);
  16930. // scope up
  16931. activeTabPath = currentPath;
  16932. parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
  16933. if(isLastIndex) {
  16934. isLastTab = true;
  16935. }
  16936. else {
  16937. nextPathArray = pathArray.slice(0, index + 2);
  16938. nextPath = module.utilities.arrayToPath(nextPathArray);
  16939. isLastTab = ( !module.is.tab(nextPath) );
  16940. if(isLastTab) {
  16941. module.verbose('Tab parameters found', nextPathArray);
  16942. }
  16943. }
  16944. if(isLastTab && remoteContent) {
  16945. if(!shouldIgnoreLoad) {
  16946. module.activate.navigation(currentPath);
  16947. module.fetch.content(currentPath, tabPath);
  16948. }
  16949. else {
  16950. module.debug('Ignoring remote content on first tab load', currentPath);
  16951. firstLoad = false;
  16952. module.cache.add(tabPath, $tab.html());
  16953. module.activate.all(currentPath);
  16954. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16955. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16956. }
  16957. return false;
  16958. }
  16959. else {
  16960. module.debug('Opened local tab', currentPath);
  16961. module.activate.all(currentPath);
  16962. if( !module.cache.read(currentPath) ) {
  16963. module.cache.add(currentPath, true);
  16964. module.debug('First time tab loaded calling tab init');
  16965. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16966. }
  16967. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16968. }
  16969. }
  16970. else if(tabPath.search('/') == -1 && tabPath !== '') {
  16971. // look for in page anchor
  16972. $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
  16973. currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
  16974. $tab = module.get.tabElement(currentPath);
  16975. // if anchor exists use parent tab
  16976. if($anchor && $anchor.length > 0 && currentPath) {
  16977. module.debug('Anchor link used, opening parent tab', $tab, $anchor);
  16978. if( !$tab.hasClass(className.active) ) {
  16979. setTimeout(function() {
  16980. module.scrollTo($anchor);
  16981. }, 0);
  16982. }
  16983. module.activate.all(currentPath);
  16984. if( !module.cache.read(currentPath) ) {
  16985. module.cache.add(currentPath, true);
  16986. module.debug('First time tab loaded calling tab init');
  16987. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16988. }
  16989. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  16990. return false;
  16991. }
  16992. }
  16993. else {
  16994. module.error(error.missingTab, $module, $context, currentPath);
  16995. return false;
  16996. }
  16997. });
  16998. },
  16999. scrollTo: function($element) {
  17000. var
  17001. scrollOffset = ($element && $element.length > 0)
  17002. ? $element.offset().top
  17003. : false
  17004. ;
  17005. if(scrollOffset !== false) {
  17006. module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
  17007. $(document).scrollTop(scrollOffset);
  17008. }
  17009. },
  17010. update: {
  17011. content: function(tabPath, html, evaluateScripts) {
  17012. var
  17013. $tab = module.get.tabElement(tabPath),
  17014. tab = $tab[0]
  17015. ;
  17016. evaluateScripts = (evaluateScripts !== undefined)
  17017. ? evaluateScripts
  17018. : settings.evaluateScripts
  17019. ;
  17020. if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') {
  17021. $tab
  17022. .empty()
  17023. .append($(html).clone(true))
  17024. ;
  17025. }
  17026. else {
  17027. if(evaluateScripts) {
  17028. module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
  17029. $tab.html(html);
  17030. }
  17031. else {
  17032. module.debug('Updating HTML', tabPath, html);
  17033. tab.innerHTML = html;
  17034. }
  17035. }
  17036. }
  17037. },
  17038. fetch: {
  17039. content: function(tabPath, fullTabPath) {
  17040. var
  17041. $tab = module.get.tabElement(tabPath),
  17042. apiSettings = {
  17043. dataType : 'html',
  17044. encodeParameters : false,
  17045. on : 'now',
  17046. cache : settings.alwaysRefresh,
  17047. headers : {
  17048. 'X-Remote': true
  17049. },
  17050. onSuccess : function(response) {
  17051. if(settings.cacheType == 'response') {
  17052. module.cache.add(fullTabPath, response);
  17053. }
  17054. module.update.content(tabPath, response);
  17055. if(tabPath == activeTabPath) {
  17056. module.debug('Content loaded', tabPath);
  17057. module.activate.tab(tabPath);
  17058. }
  17059. else {
  17060. module.debug('Content loaded in background', tabPath);
  17061. }
  17062. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17063. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17064. if(settings.loadOnce) {
  17065. module.cache.add(fullTabPath, true);
  17066. }
  17067. else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) {
  17068. setTimeout(function() {
  17069. var
  17070. $clone = $tab.children().clone(true)
  17071. ;
  17072. $clone = $clone.not('script');
  17073. module.cache.add(fullTabPath, $clone);
  17074. }, 0);
  17075. }
  17076. else {
  17077. module.cache.add(fullTabPath, $tab.html());
  17078. }
  17079. },
  17080. urlData: {
  17081. tab: fullTabPath
  17082. }
  17083. },
  17084. request = $tab.api('get request') || false,
  17085. existingRequest = ( request && request.state() === 'pending' ),
  17086. requestSettings,
  17087. cachedContent
  17088. ;
  17089. fullTabPath = fullTabPath || tabPath;
  17090. cachedContent = module.cache.read(fullTabPath);
  17091. if(settings.cache && cachedContent) {
  17092. module.activate.tab(tabPath);
  17093. module.debug('Adding cached content', fullTabPath);
  17094. if(!settings.loadOnce) {
  17095. if(settings.evaluateScripts == 'once') {
  17096. module.update.content(tabPath, cachedContent, false);
  17097. }
  17098. else {
  17099. module.update.content(tabPath, cachedContent);
  17100. }
  17101. }
  17102. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17103. }
  17104. else if(existingRequest) {
  17105. module.set.loading(tabPath);
  17106. module.debug('Content is already loading', fullTabPath);
  17107. }
  17108. else if($.api !== undefined) {
  17109. requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
  17110. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  17111. module.set.loading(tabPath);
  17112. $tab.api(requestSettings);
  17113. }
  17114. else {
  17115. module.error(error.api);
  17116. }
  17117. }
  17118. },
  17119. activate: {
  17120. all: function(tabPath) {
  17121. module.activate.tab(tabPath);
  17122. module.activate.navigation(tabPath);
  17123. },
  17124. tab: function(tabPath) {
  17125. var
  17126. $tab = module.get.tabElement(tabPath),
  17127. $deactiveTabs = (settings.deactivate == 'siblings')
  17128. ? $tab.siblings($tabs)
  17129. : $tabs.not($tab),
  17130. isActive = $tab.hasClass(className.active)
  17131. ;
  17132. module.verbose('Showing tab content for', $tab);
  17133. if(!isActive) {
  17134. $tab
  17135. .addClass(className.active)
  17136. ;
  17137. $deactiveTabs
  17138. .removeClass(className.active + ' ' + className.loading)
  17139. ;
  17140. if($tab.length > 0) {
  17141. settings.onVisible.call($tab[0], tabPath);
  17142. }
  17143. }
  17144. },
  17145. navigation: function(tabPath) {
  17146. var
  17147. $navigation = module.get.navElement(tabPath),
  17148. $deactiveNavigation = (settings.deactivate == 'siblings')
  17149. ? $navigation.siblings($allModules)
  17150. : $allModules.not($navigation),
  17151. isActive = $navigation.hasClass(className.active)
  17152. ;
  17153. module.verbose('Activating tab navigation for', $navigation, tabPath);
  17154. if(!isActive) {
  17155. $navigation
  17156. .addClass(className.active)
  17157. ;
  17158. $deactiveNavigation
  17159. .removeClass(className.active + ' ' + className.loading)
  17160. ;
  17161. }
  17162. }
  17163. },
  17164. deactivate: {
  17165. all: function() {
  17166. module.deactivate.navigation();
  17167. module.deactivate.tabs();
  17168. },
  17169. navigation: function() {
  17170. $allModules
  17171. .removeClass(className.active)
  17172. ;
  17173. },
  17174. tabs: function() {
  17175. $tabs
  17176. .removeClass(className.active + ' ' + className.loading)
  17177. ;
  17178. }
  17179. },
  17180. is: {
  17181. tab: function(tabName) {
  17182. return (tabName !== undefined)
  17183. ? ( module.get.tabElement(tabName).length > 0 )
  17184. : false
  17185. ;
  17186. }
  17187. },
  17188. get: {
  17189. initialPath: function() {
  17190. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  17191. },
  17192. path: function() {
  17193. return $.address.value();
  17194. },
  17195. // adds default tabs to tab path
  17196. defaultPathArray: function(tabPath) {
  17197. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  17198. },
  17199. defaultPath: function(tabPath) {
  17200. var
  17201. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0),
  17202. defaultTab = $defaultNav.data(metadata.tab) || false
  17203. ;
  17204. if( defaultTab ) {
  17205. module.debug('Found default tab', defaultTab);
  17206. if(recursionDepth < settings.maxDepth) {
  17207. recursionDepth++;
  17208. return module.get.defaultPath(defaultTab);
  17209. }
  17210. module.error(error.recursion);
  17211. }
  17212. else {
  17213. module.debug('No default tabs found for', tabPath, $tabs);
  17214. }
  17215. recursionDepth = 0;
  17216. return tabPath;
  17217. },
  17218. navElement: function(tabPath) {
  17219. tabPath = tabPath || activeTabPath;
  17220. return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  17221. },
  17222. tabElement: function(tabPath) {
  17223. var
  17224. $fullPathTab,
  17225. $simplePathTab,
  17226. tabPathArray,
  17227. lastTab
  17228. ;
  17229. tabPath = tabPath || activeTabPath;
  17230. tabPathArray = module.utilities.pathToArray(tabPath);
  17231. lastTab = module.utilities.last(tabPathArray);
  17232. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  17233. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]');
  17234. return ($fullPathTab.length > 0)
  17235. ? $fullPathTab
  17236. : $simplePathTab
  17237. ;
  17238. },
  17239. tab: function() {
  17240. return activeTabPath;
  17241. }
  17242. },
  17243. utilities: {
  17244. filterArray: function(keepArray, removeArray) {
  17245. return $.grep(keepArray, function(keepValue) {
  17246. return ( $.inArray(keepValue, removeArray) == -1);
  17247. });
  17248. },
  17249. last: function(array) {
  17250. return $.isArray(array)
  17251. ? array[ array.length - 1]
  17252. : false
  17253. ;
  17254. },
  17255. pathToArray: function(pathName) {
  17256. if(pathName === undefined) {
  17257. pathName = activeTabPath;
  17258. }
  17259. return typeof pathName == 'string'
  17260. ? pathName.split('/')
  17261. : [pathName]
  17262. ;
  17263. },
  17264. arrayToPath: function(pathArray) {
  17265. return $.isArray(pathArray)
  17266. ? pathArray.join('/')
  17267. : false
  17268. ;
  17269. }
  17270. },
  17271. setting: function(name, value) {
  17272. module.debug('Changing setting', name, value);
  17273. if( $.isPlainObject(name) ) {
  17274. $.extend(true, settings, name);
  17275. }
  17276. else if(value !== undefined) {
  17277. if($.isPlainObject(settings[name])) {
  17278. $.extend(true, settings[name], value);
  17279. }
  17280. else {
  17281. settings[name] = value;
  17282. }
  17283. }
  17284. else {
  17285. return settings[name];
  17286. }
  17287. },
  17288. internal: function(name, value) {
  17289. if( $.isPlainObject(name) ) {
  17290. $.extend(true, module, name);
  17291. }
  17292. else if(value !== undefined) {
  17293. module[name] = value;
  17294. }
  17295. else {
  17296. return module[name];
  17297. }
  17298. },
  17299. debug: function() {
  17300. if(!settings.silent && settings.debug) {
  17301. if(settings.performance) {
  17302. module.performance.log(arguments);
  17303. }
  17304. else {
  17305. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17306. module.debug.apply(console, arguments);
  17307. }
  17308. }
  17309. },
  17310. verbose: function() {
  17311. if(!settings.silent && settings.verbose && settings.debug) {
  17312. if(settings.performance) {
  17313. module.performance.log(arguments);
  17314. }
  17315. else {
  17316. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17317. module.verbose.apply(console, arguments);
  17318. }
  17319. }
  17320. },
  17321. error: function() {
  17322. if(!settings.silent) {
  17323. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  17324. module.error.apply(console, arguments);
  17325. }
  17326. },
  17327. performance: {
  17328. log: function(message) {
  17329. var
  17330. currentTime,
  17331. executionTime,
  17332. previousTime
  17333. ;
  17334. if(settings.performance) {
  17335. currentTime = new Date().getTime();
  17336. previousTime = time || currentTime;
  17337. executionTime = currentTime - previousTime;
  17338. time = currentTime;
  17339. performance.push({
  17340. 'Name' : message[0],
  17341. 'Arguments' : [].slice.call(message, 1) || '',
  17342. 'Element' : element,
  17343. 'Execution Time' : executionTime
  17344. });
  17345. }
  17346. clearTimeout(module.performance.timer);
  17347. module.performance.timer = setTimeout(module.performance.display, 500);
  17348. },
  17349. display: function() {
  17350. var
  17351. title = settings.name + ':',
  17352. totalTime = 0
  17353. ;
  17354. time = false;
  17355. clearTimeout(module.performance.timer);
  17356. $.each(performance, function(index, data) {
  17357. totalTime += data['Execution Time'];
  17358. });
  17359. title += ' ' + totalTime + 'ms';
  17360. if(moduleSelector) {
  17361. title += ' \'' + moduleSelector + '\'';
  17362. }
  17363. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  17364. console.groupCollapsed(title);
  17365. if(console.table) {
  17366. console.table(performance);
  17367. }
  17368. else {
  17369. $.each(performance, function(index, data) {
  17370. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  17371. });
  17372. }
  17373. console.groupEnd();
  17374. }
  17375. performance = [];
  17376. }
  17377. },
  17378. invoke: function(query, passedArguments, context) {
  17379. var
  17380. object = instance,
  17381. maxDepth,
  17382. found,
  17383. response
  17384. ;
  17385. passedArguments = passedArguments || queryArguments;
  17386. context = element || context;
  17387. if(typeof query == 'string' && object !== undefined) {
  17388. query = query.split(/[\. ]/);
  17389. maxDepth = query.length - 1;
  17390. $.each(query, function(depth, value) {
  17391. var camelCaseValue = (depth != maxDepth)
  17392. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  17393. : query
  17394. ;
  17395. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  17396. object = object[camelCaseValue];
  17397. }
  17398. else if( object[camelCaseValue] !== undefined ) {
  17399. found = object[camelCaseValue];
  17400. return false;
  17401. }
  17402. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  17403. object = object[value];
  17404. }
  17405. else if( object[value] !== undefined ) {
  17406. found = object[value];
  17407. return false;
  17408. }
  17409. else {
  17410. module.error(error.method, query);
  17411. return false;
  17412. }
  17413. });
  17414. }
  17415. if ( $.isFunction( found ) ) {
  17416. response = found.apply(context, passedArguments);
  17417. }
  17418. else if(found !== undefined) {
  17419. response = found;
  17420. }
  17421. if($.isArray(returnedValue)) {
  17422. returnedValue.push(response);
  17423. }
  17424. else if(returnedValue !== undefined) {
  17425. returnedValue = [returnedValue, response];
  17426. }
  17427. else if(response !== undefined) {
  17428. returnedValue = response;
  17429. }
  17430. return found;
  17431. }
  17432. };
  17433. if(methodInvoked) {
  17434. if(instance === undefined) {
  17435. module.initialize();
  17436. }
  17437. module.invoke(query);
  17438. }
  17439. else {
  17440. if(instance !== undefined) {
  17441. instance.invoke('destroy');
  17442. }
  17443. module.initialize();
  17444. }
  17445. })
  17446. ;
  17447. return (returnedValue !== undefined)
  17448. ? returnedValue
  17449. : this
  17450. ;
  17451. };
  17452. // shortcut for tabbed content with no defined navigation
  17453. $.tab = function() {
  17454. $(window).tab.apply(this, arguments);
  17455. };
  17456. $.fn.tab.settings = {
  17457. name : 'Tab',
  17458. namespace : 'tab',
  17459. silent : false,
  17460. debug : false,
  17461. verbose : false,
  17462. performance : true,
  17463. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  17464. history : false, // use browser history
  17465. historyType : 'hash', // #/ or html5 state
  17466. path : false, // base path of url
  17467. context : false, // specify a context that tabs must appear inside
  17468. childrenOnly : false, // use only tabs that are children of context
  17469. maxDepth : 25, // max depth a tab can be nested
  17470. deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together
  17471. alwaysRefresh : false, // load tab content new every tab click
  17472. cache : true, // cache the content requests to pull locally
  17473. loadOnce : false, // Whether tab data should only be loaded once when using remote content
  17474. cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute
  17475. ignoreFirstLoad : false, // don't load remote content on first load
  17476. apiSettings : false, // settings for api call
  17477. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  17478. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  17479. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  17480. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  17481. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  17482. templates : {
  17483. determineTitle: function(tabArray) {} // returns page title for path
  17484. },
  17485. error: {
  17486. api : 'You attempted to load content without API module',
  17487. method : 'The method you called is not defined',
  17488. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  17489. noContent : 'The tab you specified is missing a content url.',
  17490. path : 'History enabled, but no path was specified',
  17491. recursion : 'Max recursive depth reached',
  17492. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  17493. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  17494. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  17495. },
  17496. metadata : {
  17497. tab : 'tab',
  17498. loaded : 'loaded',
  17499. promise: 'promise'
  17500. },
  17501. className : {
  17502. loading : 'loading',
  17503. active : 'active'
  17504. },
  17505. selector : {
  17506. tabs : '.ui.tab',
  17507. ui : '.ui'
  17508. }
  17509. };
  17510. })( jQuery, window, document );
  17511. /*!
  17512. * # Semantic UI 2.3.0 - Transition
  17513. * http://github.com/semantic-org/semantic-ui/
  17514. *
  17515. *
  17516. * Released under the MIT license
  17517. * http://opensource.org/licenses/MIT
  17518. *
  17519. */
  17520. ;(function ($, window, document, undefined) {
  17521. "use strict";
  17522. window = (typeof window != 'undefined' && window.Math == Math)
  17523. ? window
  17524. : (typeof self != 'undefined' && self.Math == Math)
  17525. ? self
  17526. : Function('return this')()
  17527. ;
  17528. $.fn.transition = function() {
  17529. var
  17530. $allModules = $(this),
  17531. moduleSelector = $allModules.selector || '',
  17532. time = new Date().getTime(),
  17533. performance = [],
  17534. moduleArguments = arguments,
  17535. query = moduleArguments[0],
  17536. queryArguments = [].slice.call(arguments, 1),
  17537. methodInvoked = (typeof query === 'string'),
  17538. requestAnimationFrame = window.requestAnimationFrame
  17539. || window.mozRequestAnimationFrame
  17540. || window.webkitRequestAnimationFrame
  17541. || window.msRequestAnimationFrame
  17542. || function(callback) { setTimeout(callback, 0); },
  17543. returnedValue
  17544. ;
  17545. $allModules
  17546. .each(function(index) {
  17547. var
  17548. $module = $(this),
  17549. element = this,
  17550. // set at run time
  17551. settings,
  17552. instance,
  17553. error,
  17554. className,
  17555. metadata,
  17556. animationEnd,
  17557. animationName,
  17558. namespace,
  17559. moduleNamespace,
  17560. eventNamespace,
  17561. module
  17562. ;
  17563. module = {
  17564. initialize: function() {
  17565. // get full settings
  17566. settings = module.get.settings.apply(element, moduleArguments);
  17567. // shorthand
  17568. className = settings.className;
  17569. error = settings.error;
  17570. metadata = settings.metadata;
  17571. // define namespace
  17572. eventNamespace = '.' + settings.namespace;
  17573. moduleNamespace = 'module-' + settings.namespace;
  17574. instance = $module.data(moduleNamespace) || module;
  17575. // get vendor specific events
  17576. animationEnd = module.get.animationEndEvent();
  17577. if(methodInvoked) {
  17578. methodInvoked = module.invoke(query);
  17579. }
  17580. // method not invoked, lets run an animation
  17581. if(methodInvoked === false) {
  17582. module.verbose('Converted arguments into settings object', settings);
  17583. if(settings.interval) {
  17584. module.delay(settings.animate);
  17585. }
  17586. else {
  17587. module.animate();
  17588. }
  17589. module.instantiate();
  17590. }
  17591. },
  17592. instantiate: function() {
  17593. module.verbose('Storing instance of module', module);
  17594. instance = module;
  17595. $module
  17596. .data(moduleNamespace, instance)
  17597. ;
  17598. },
  17599. destroy: function() {
  17600. module.verbose('Destroying previous module for', element);
  17601. $module
  17602. .removeData(moduleNamespace)
  17603. ;
  17604. },
  17605. refresh: function() {
  17606. module.verbose('Refreshing display type on next animation');
  17607. delete module.displayType;
  17608. },
  17609. forceRepaint: function() {
  17610. module.verbose('Forcing element repaint');
  17611. var
  17612. $parentElement = $module.parent(),
  17613. $nextElement = $module.next()
  17614. ;
  17615. if($nextElement.length === 0) {
  17616. $module.detach().appendTo($parentElement);
  17617. }
  17618. else {
  17619. $module.detach().insertBefore($nextElement);
  17620. }
  17621. },
  17622. repaint: function() {
  17623. module.verbose('Repainting element');
  17624. var
  17625. fakeAssignment = element.offsetWidth
  17626. ;
  17627. },
  17628. delay: function(interval) {
  17629. var
  17630. direction = module.get.animationDirection(),
  17631. shouldReverse,
  17632. delay
  17633. ;
  17634. if(!direction) {
  17635. direction = module.can.transition()
  17636. ? module.get.direction()
  17637. : 'static'
  17638. ;
  17639. }
  17640. interval = (interval !== undefined)
  17641. ? interval
  17642. : settings.interval
  17643. ;
  17644. shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
  17645. delay = (shouldReverse || settings.reverse == true)
  17646. ? ($allModules.length - index) * settings.interval
  17647. : index * settings.interval
  17648. ;
  17649. module.debug('Delaying animation by', delay);
  17650. setTimeout(module.animate, delay);
  17651. },
  17652. animate: function(overrideSettings) {
  17653. settings = overrideSettings || settings;
  17654. if(!module.is.supported()) {
  17655. module.error(error.support);
  17656. return false;
  17657. }
  17658. module.debug('Preparing animation', settings.animation);
  17659. if(module.is.animating()) {
  17660. if(settings.queue) {
  17661. if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
  17662. module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
  17663. }
  17664. else {
  17665. module.queue(settings.animation);
  17666. }
  17667. return false;
  17668. }
  17669. else if(!settings.allowRepeats && module.is.occurring()) {
  17670. module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
  17671. return false;
  17672. }
  17673. else {
  17674. module.debug('New animation started, completing previous early', settings.animation);
  17675. instance.complete();
  17676. }
  17677. }
  17678. if( module.can.animate() ) {
  17679. module.set.animating(settings.animation);
  17680. }
  17681. else {
  17682. module.error(error.noAnimation, settings.animation, element);
  17683. }
  17684. },
  17685. reset: function() {
  17686. module.debug('Resetting animation to beginning conditions');
  17687. module.remove.animationCallbacks();
  17688. module.restore.conditions();
  17689. module.remove.animating();
  17690. },
  17691. queue: function(animation) {
  17692. module.debug('Queueing animation of', animation);
  17693. module.queuing = true;
  17694. $module
  17695. .one(animationEnd + '.queue' + eventNamespace, function() {
  17696. module.queuing = false;
  17697. module.repaint();
  17698. module.animate.apply(this, settings);
  17699. })
  17700. ;
  17701. },
  17702. complete: function (event) {
  17703. module.debug('Animation complete', settings.animation);
  17704. module.remove.completeCallback();
  17705. module.remove.failSafe();
  17706. if(!module.is.looping()) {
  17707. if( module.is.outward() ) {
  17708. module.verbose('Animation is outward, hiding element');
  17709. module.restore.conditions();
  17710. module.hide();
  17711. }
  17712. else if( module.is.inward() ) {
  17713. module.verbose('Animation is outward, showing element');
  17714. module.restore.conditions();
  17715. module.show();
  17716. }
  17717. else {
  17718. module.verbose('Static animation completed');
  17719. module.restore.conditions();
  17720. settings.onComplete.call(element);
  17721. }
  17722. }
  17723. },
  17724. force: {
  17725. visible: function() {
  17726. var
  17727. style = $module.attr('style'),
  17728. userStyle = module.get.userStyle(),
  17729. displayType = module.get.displayType(),
  17730. overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
  17731. currentDisplay = $module.css('display'),
  17732. emptyStyle = (style === undefined || style === '')
  17733. ;
  17734. if(currentDisplay !== displayType) {
  17735. module.verbose('Overriding default display to show element', displayType);
  17736. $module
  17737. .attr('style', overrideStyle)
  17738. ;
  17739. }
  17740. else if(emptyStyle) {
  17741. $module.removeAttr('style');
  17742. }
  17743. },
  17744. hidden: function() {
  17745. var
  17746. style = $module.attr('style'),
  17747. currentDisplay = $module.css('display'),
  17748. emptyStyle = (style === undefined || style === '')
  17749. ;
  17750. if(currentDisplay !== 'none' && !module.is.hidden()) {
  17751. module.verbose('Overriding default display to hide element');
  17752. $module
  17753. .css('display', 'none')
  17754. ;
  17755. }
  17756. else if(emptyStyle) {
  17757. $module
  17758. .removeAttr('style')
  17759. ;
  17760. }
  17761. }
  17762. },
  17763. has: {
  17764. direction: function(animation) {
  17765. var
  17766. hasDirection = false
  17767. ;
  17768. animation = animation || settings.animation;
  17769. if(typeof animation === 'string') {
  17770. animation = animation.split(' ');
  17771. $.each(animation, function(index, word){
  17772. if(word === className.inward || word === className.outward) {
  17773. hasDirection = true;
  17774. }
  17775. });
  17776. }
  17777. return hasDirection;
  17778. },
  17779. inlineDisplay: function() {
  17780. var
  17781. style = $module.attr('style') || ''
  17782. ;
  17783. return $.isArray(style.match(/display.*?;/, ''));
  17784. }
  17785. },
  17786. set: {
  17787. animating: function(animation) {
  17788. var
  17789. animationClass,
  17790. direction
  17791. ;
  17792. // remove previous callbacks
  17793. module.remove.completeCallback();
  17794. // determine exact animation
  17795. animation = animation || settings.animation;
  17796. animationClass = module.get.animationClass(animation);
  17797. // save animation class in cache to restore class names
  17798. module.save.animation(animationClass);
  17799. // override display if necessary so animation appears visibly
  17800. module.force.visible();
  17801. module.remove.hidden();
  17802. module.remove.direction();
  17803. module.start.animation(animationClass);
  17804. },
  17805. duration: function(animationName, duration) {
  17806. duration = duration || settings.duration;
  17807. duration = (typeof duration == 'number')
  17808. ? duration + 'ms'
  17809. : duration
  17810. ;
  17811. if(duration || duration === 0) {
  17812. module.verbose('Setting animation duration', duration);
  17813. $module
  17814. .css({
  17815. 'animation-duration': duration
  17816. })
  17817. ;
  17818. }
  17819. },
  17820. direction: function(direction) {
  17821. direction = direction || module.get.direction();
  17822. if(direction == className.inward) {
  17823. module.set.inward();
  17824. }
  17825. else {
  17826. module.set.outward();
  17827. }
  17828. },
  17829. looping: function() {
  17830. module.debug('Transition set to loop');
  17831. $module
  17832. .addClass(className.looping)
  17833. ;
  17834. },
  17835. hidden: function() {
  17836. $module
  17837. .addClass(className.transition)
  17838. .addClass(className.hidden)
  17839. ;
  17840. },
  17841. inward: function() {
  17842. module.debug('Setting direction to inward');
  17843. $module
  17844. .removeClass(className.outward)
  17845. .addClass(className.inward)
  17846. ;
  17847. },
  17848. outward: function() {
  17849. module.debug('Setting direction to outward');
  17850. $module
  17851. .removeClass(className.inward)
  17852. .addClass(className.outward)
  17853. ;
  17854. },
  17855. visible: function() {
  17856. $module
  17857. .addClass(className.transition)
  17858. .addClass(className.visible)
  17859. ;
  17860. }
  17861. },
  17862. start: {
  17863. animation: function(animationClass) {
  17864. animationClass = animationClass || module.get.animationClass();
  17865. module.debug('Starting tween', animationClass);
  17866. $module
  17867. .addClass(animationClass)
  17868. .one(animationEnd + '.complete' + eventNamespace, module.complete)
  17869. ;
  17870. if(settings.useFailSafe) {
  17871. module.add.failSafe();
  17872. }
  17873. module.set.duration(settings.duration);
  17874. settings.onStart.call(element);
  17875. }
  17876. },
  17877. save: {
  17878. animation: function(animation) {
  17879. if(!module.cache) {
  17880. module.cache = {};
  17881. }
  17882. module.cache.animation = animation;
  17883. },
  17884. displayType: function(displayType) {
  17885. if(displayType !== 'none') {
  17886. $module.data(metadata.displayType, displayType);
  17887. }
  17888. },
  17889. transitionExists: function(animation, exists) {
  17890. $.fn.transition.exists[animation] = exists;
  17891. module.verbose('Saving existence of transition', animation, exists);
  17892. }
  17893. },
  17894. restore: {
  17895. conditions: function() {
  17896. var
  17897. animation = module.get.currentAnimation()
  17898. ;
  17899. if(animation) {
  17900. $module
  17901. .removeClass(animation)
  17902. ;
  17903. module.verbose('Removing animation class', module.cache);
  17904. }
  17905. module.remove.duration();
  17906. }
  17907. },
  17908. add: {
  17909. failSafe: function() {
  17910. var
  17911. duration = module.get.duration()
  17912. ;
  17913. module.timer = setTimeout(function() {
  17914. $module.triggerHandler(animationEnd);
  17915. }, duration + settings.failSafeDelay);
  17916. module.verbose('Adding fail safe timer', module.timer);
  17917. }
  17918. },
  17919. remove: {
  17920. animating: function() {
  17921. $module.removeClass(className.animating);
  17922. },
  17923. animationCallbacks: function() {
  17924. module.remove.queueCallback();
  17925. module.remove.completeCallback();
  17926. },
  17927. queueCallback: function() {
  17928. $module.off('.queue' + eventNamespace);
  17929. },
  17930. completeCallback: function() {
  17931. $module.off('.complete' + eventNamespace);
  17932. },
  17933. display: function() {
  17934. $module.css('display', '');
  17935. },
  17936. direction: function() {
  17937. $module
  17938. .removeClass(className.inward)
  17939. .removeClass(className.outward)
  17940. ;
  17941. },
  17942. duration: function() {
  17943. $module
  17944. .css('animation-duration', '')
  17945. ;
  17946. },
  17947. failSafe: function() {
  17948. module.verbose('Removing fail safe timer', module.timer);
  17949. if(module.timer) {
  17950. clearTimeout(module.timer);
  17951. }
  17952. },
  17953. hidden: function() {
  17954. $module.removeClass(className.hidden);
  17955. },
  17956. visible: function() {
  17957. $module.removeClass(className.visible);
  17958. },
  17959. looping: function() {
  17960. module.debug('Transitions are no longer looping');
  17961. if( module.is.looping() ) {
  17962. module.reset();
  17963. $module
  17964. .removeClass(className.looping)
  17965. ;
  17966. }
  17967. },
  17968. transition: function() {
  17969. $module
  17970. .removeClass(className.visible)
  17971. .removeClass(className.hidden)
  17972. ;
  17973. }
  17974. },
  17975. get: {
  17976. settings: function(animation, duration, onComplete) {
  17977. // single settings object
  17978. if(typeof animation == 'object') {
  17979. return $.extend(true, {}, $.fn.transition.settings, animation);
  17980. }
  17981. // all arguments provided
  17982. else if(typeof onComplete == 'function') {
  17983. return $.extend({}, $.fn.transition.settings, {
  17984. animation : animation,
  17985. onComplete : onComplete,
  17986. duration : duration
  17987. });
  17988. }
  17989. // only duration provided
  17990. else if(typeof duration == 'string' || typeof duration == 'number') {
  17991. return $.extend({}, $.fn.transition.settings, {
  17992. animation : animation,
  17993. duration : duration
  17994. });
  17995. }
  17996. // duration is actually settings object
  17997. else if(typeof duration == 'object') {
  17998. return $.extend({}, $.fn.transition.settings, duration, {
  17999. animation : animation
  18000. });
  18001. }
  18002. // duration is actually callback
  18003. else if(typeof duration == 'function') {
  18004. return $.extend({}, $.fn.transition.settings, {
  18005. animation : animation,
  18006. onComplete : duration
  18007. });
  18008. }
  18009. // only animation provided
  18010. else {
  18011. return $.extend({}, $.fn.transition.settings, {
  18012. animation : animation
  18013. });
  18014. }
  18015. },
  18016. animationClass: function(animation) {
  18017. var
  18018. animationClass = animation || settings.animation,
  18019. directionClass = (module.can.transition() && !module.has.direction())
  18020. ? module.get.direction() + ' '
  18021. : ''
  18022. ;
  18023. return className.animating + ' '
  18024. + className.transition + ' '
  18025. + directionClass
  18026. + animationClass
  18027. ;
  18028. },
  18029. currentAnimation: function() {
  18030. return (module.cache && module.cache.animation !== undefined)
  18031. ? module.cache.animation
  18032. : false
  18033. ;
  18034. },
  18035. currentDirection: function() {
  18036. return module.is.inward()
  18037. ? className.inward
  18038. : className.outward
  18039. ;
  18040. },
  18041. direction: function() {
  18042. return module.is.hidden() || !module.is.visible()
  18043. ? className.inward
  18044. : className.outward
  18045. ;
  18046. },
  18047. animationDirection: function(animation) {
  18048. var
  18049. direction
  18050. ;
  18051. animation = animation || settings.animation;
  18052. if(typeof animation === 'string') {
  18053. animation = animation.split(' ');
  18054. // search animation name for out/in class
  18055. $.each(animation, function(index, word){
  18056. if(word === className.inward) {
  18057. direction = className.inward;
  18058. }
  18059. else if(word === className.outward) {
  18060. direction = className.outward;
  18061. }
  18062. });
  18063. }
  18064. // return found direction
  18065. if(direction) {
  18066. return direction;
  18067. }
  18068. return false;
  18069. },
  18070. duration: function(duration) {
  18071. duration = duration || settings.duration;
  18072. if(duration === false) {
  18073. duration = $module.css('animation-duration') || 0;
  18074. }
  18075. return (typeof duration === 'string')
  18076. ? (duration.indexOf('ms') > -1)
  18077. ? parseFloat(duration)
  18078. : parseFloat(duration) * 1000
  18079. : duration
  18080. ;
  18081. },
  18082. displayType: function(shouldDetermine) {
  18083. shouldDetermine = (shouldDetermine !== undefined)
  18084. ? shouldDetermine
  18085. : true
  18086. ;
  18087. if(settings.displayType) {
  18088. return settings.displayType;
  18089. }
  18090. if(shouldDetermine && $module.data(metadata.displayType) === undefined) {
  18091. // create fake element to determine display state
  18092. module.can.transition(true);
  18093. }
  18094. return $module.data(metadata.displayType);
  18095. },
  18096. userStyle: function(style) {
  18097. style = style || $module.attr('style') || '';
  18098. return style.replace(/display.*?;/, '');
  18099. },
  18100. transitionExists: function(animation) {
  18101. return $.fn.transition.exists[animation];
  18102. },
  18103. animationStartEvent: function() {
  18104. var
  18105. element = document.createElement('div'),
  18106. animations = {
  18107. 'animation' :'animationstart',
  18108. 'OAnimation' :'oAnimationStart',
  18109. 'MozAnimation' :'mozAnimationStart',
  18110. 'WebkitAnimation' :'webkitAnimationStart'
  18111. },
  18112. animation
  18113. ;
  18114. for(animation in animations){
  18115. if( element.style[animation] !== undefined ){
  18116. return animations[animation];
  18117. }
  18118. }
  18119. return false;
  18120. },
  18121. animationEndEvent: function() {
  18122. var
  18123. element = document.createElement('div'),
  18124. animations = {
  18125. 'animation' :'animationend',
  18126. 'OAnimation' :'oAnimationEnd',
  18127. 'MozAnimation' :'mozAnimationEnd',
  18128. 'WebkitAnimation' :'webkitAnimationEnd'
  18129. },
  18130. animation
  18131. ;
  18132. for(animation in animations){
  18133. if( element.style[animation] !== undefined ){
  18134. return animations[animation];
  18135. }
  18136. }
  18137. return false;
  18138. }
  18139. },
  18140. can: {
  18141. transition: function(forced) {
  18142. var
  18143. animation = settings.animation,
  18144. transitionExists = module.get.transitionExists(animation),
  18145. displayType = module.get.displayType(false),
  18146. elementClass,
  18147. tagName,
  18148. $clone,
  18149. currentAnimation,
  18150. inAnimation,
  18151. directionExists
  18152. ;
  18153. if( transitionExists === undefined || forced) {
  18154. module.verbose('Determining whether animation exists');
  18155. elementClass = $module.attr('class');
  18156. tagName = $module.prop('tagName');
  18157. $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
  18158. currentAnimation = $clone
  18159. .addClass(animation)
  18160. .removeClass(className.inward)
  18161. .removeClass(className.outward)
  18162. .addClass(className.animating)
  18163. .addClass(className.transition)
  18164. .css('animationName')
  18165. ;
  18166. inAnimation = $clone
  18167. .addClass(className.inward)
  18168. .css('animationName')
  18169. ;
  18170. if(!displayType) {
  18171. displayType = $clone
  18172. .attr('class', elementClass)
  18173. .removeAttr('style')
  18174. .removeClass(className.hidden)
  18175. .removeClass(className.visible)
  18176. .show()
  18177. .css('display')
  18178. ;
  18179. module.verbose('Determining final display state', displayType);
  18180. module.save.displayType(displayType);
  18181. }
  18182. $clone.remove();
  18183. if(currentAnimation != inAnimation) {
  18184. module.debug('Direction exists for animation', animation);
  18185. directionExists = true;
  18186. }
  18187. else if(currentAnimation == 'none' || !currentAnimation) {
  18188. module.debug('No animation defined in css', animation);
  18189. return;
  18190. }
  18191. else {
  18192. module.debug('Static animation found', animation, displayType);
  18193. directionExists = false;
  18194. }
  18195. module.save.transitionExists(animation, directionExists);
  18196. }
  18197. return (transitionExists !== undefined)
  18198. ? transitionExists
  18199. : directionExists
  18200. ;
  18201. },
  18202. animate: function() {
  18203. // can transition does not return a value if animation does not exist
  18204. return (module.can.transition() !== undefined);
  18205. }
  18206. },
  18207. is: {
  18208. animating: function() {
  18209. return $module.hasClass(className.animating);
  18210. },
  18211. inward: function() {
  18212. return $module.hasClass(className.inward);
  18213. },
  18214. outward: function() {
  18215. return $module.hasClass(className.outward);
  18216. },
  18217. looping: function() {
  18218. return $module.hasClass(className.looping);
  18219. },
  18220. occurring: function(animation) {
  18221. animation = animation || settings.animation;
  18222. animation = '.' + animation.replace(' ', '.');
  18223. return ( $module.filter(animation).length > 0 );
  18224. },
  18225. visible: function() {
  18226. return $module.is(':visible');
  18227. },
  18228. hidden: function() {
  18229. return $module.css('visibility') === 'hidden';
  18230. },
  18231. supported: function() {
  18232. return(animationEnd !== false);
  18233. }
  18234. },
  18235. hide: function() {
  18236. module.verbose('Hiding element');
  18237. if( module.is.animating() ) {
  18238. module.reset();
  18239. }
  18240. element.blur(); // IE will trigger focus change if element is not blurred before hiding
  18241. module.remove.display();
  18242. module.remove.visible();
  18243. module.set.hidden();
  18244. module.force.hidden();
  18245. settings.onHide.call(element);
  18246. settings.onComplete.call(element);
  18247. // module.repaint();
  18248. },
  18249. show: function(display) {
  18250. module.verbose('Showing element', display);
  18251. module.remove.hidden();
  18252. module.set.visible();
  18253. module.force.visible();
  18254. settings.onShow.call(element);
  18255. settings.onComplete.call(element);
  18256. // module.repaint();
  18257. },
  18258. toggle: function() {
  18259. if( module.is.visible() ) {
  18260. module.hide();
  18261. }
  18262. else {
  18263. module.show();
  18264. }
  18265. },
  18266. stop: function() {
  18267. module.debug('Stopping current animation');
  18268. $module.triggerHandler(animationEnd);
  18269. },
  18270. stopAll: function() {
  18271. module.debug('Stopping all animation');
  18272. module.remove.queueCallback();
  18273. $module.triggerHandler(animationEnd);
  18274. },
  18275. clear: {
  18276. queue: function() {
  18277. module.debug('Clearing animation queue');
  18278. module.remove.queueCallback();
  18279. }
  18280. },
  18281. enable: function() {
  18282. module.verbose('Starting animation');
  18283. $module.removeClass(className.disabled);
  18284. },
  18285. disable: function() {
  18286. module.debug('Stopping animation');
  18287. $module.addClass(className.disabled);
  18288. },
  18289. setting: function(name, value) {
  18290. module.debug('Changing setting', name, value);
  18291. if( $.isPlainObject(name) ) {
  18292. $.extend(true, settings, name);
  18293. }
  18294. else if(value !== undefined) {
  18295. if($.isPlainObject(settings[name])) {
  18296. $.extend(true, settings[name], value);
  18297. }
  18298. else {
  18299. settings[name] = value;
  18300. }
  18301. }
  18302. else {
  18303. return settings[name];
  18304. }
  18305. },
  18306. internal: function(name, value) {
  18307. if( $.isPlainObject(name) ) {
  18308. $.extend(true, module, name);
  18309. }
  18310. else if(value !== undefined) {
  18311. module[name] = value;
  18312. }
  18313. else {
  18314. return module[name];
  18315. }
  18316. },
  18317. debug: function() {
  18318. if(!settings.silent && settings.debug) {
  18319. if(settings.performance) {
  18320. module.performance.log(arguments);
  18321. }
  18322. else {
  18323. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18324. module.debug.apply(console, arguments);
  18325. }
  18326. }
  18327. },
  18328. verbose: function() {
  18329. if(!settings.silent && settings.verbose && settings.debug) {
  18330. if(settings.performance) {
  18331. module.performance.log(arguments);
  18332. }
  18333. else {
  18334. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18335. module.verbose.apply(console, arguments);
  18336. }
  18337. }
  18338. },
  18339. error: function() {
  18340. if(!settings.silent) {
  18341. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  18342. module.error.apply(console, arguments);
  18343. }
  18344. },
  18345. performance: {
  18346. log: function(message) {
  18347. var
  18348. currentTime,
  18349. executionTime,
  18350. previousTime
  18351. ;
  18352. if(settings.performance) {
  18353. currentTime = new Date().getTime();
  18354. previousTime = time || currentTime;
  18355. executionTime = currentTime - previousTime;
  18356. time = currentTime;
  18357. performance.push({
  18358. 'Name' : message[0],
  18359. 'Arguments' : [].slice.call(message, 1) || '',
  18360. 'Element' : element,
  18361. 'Execution Time' : executionTime
  18362. });
  18363. }
  18364. clearTimeout(module.performance.timer);
  18365. module.performance.timer = setTimeout(module.performance.display, 500);
  18366. },
  18367. display: function() {
  18368. var
  18369. title = settings.name + ':',
  18370. totalTime = 0
  18371. ;
  18372. time = false;
  18373. clearTimeout(module.performance.timer);
  18374. $.each(performance, function(index, data) {
  18375. totalTime += data['Execution Time'];
  18376. });
  18377. title += ' ' + totalTime + 'ms';
  18378. if(moduleSelector) {
  18379. title += ' \'' + moduleSelector + '\'';
  18380. }
  18381. if($allModules.length > 1) {
  18382. title += ' ' + '(' + $allModules.length + ')';
  18383. }
  18384. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  18385. console.groupCollapsed(title);
  18386. if(console.table) {
  18387. console.table(performance);
  18388. }
  18389. else {
  18390. $.each(performance, function(index, data) {
  18391. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  18392. });
  18393. }
  18394. console.groupEnd();
  18395. }
  18396. performance = [];
  18397. }
  18398. },
  18399. // modified for transition to return invoke success
  18400. invoke: function(query, passedArguments, context) {
  18401. var
  18402. object = instance,
  18403. maxDepth,
  18404. found,
  18405. response
  18406. ;
  18407. passedArguments = passedArguments || queryArguments;
  18408. context = element || context;
  18409. if(typeof query == 'string' && object !== undefined) {
  18410. query = query.split(/[\. ]/);
  18411. maxDepth = query.length - 1;
  18412. $.each(query, function(depth, value) {
  18413. var camelCaseValue = (depth != maxDepth)
  18414. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  18415. : query
  18416. ;
  18417. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  18418. object = object[camelCaseValue];
  18419. }
  18420. else if( object[camelCaseValue] !== undefined ) {
  18421. found = object[camelCaseValue];
  18422. return false;
  18423. }
  18424. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  18425. object = object[value];
  18426. }
  18427. else if( object[value] !== undefined ) {
  18428. found = object[value];
  18429. return false;
  18430. }
  18431. else {
  18432. return false;
  18433. }
  18434. });
  18435. }
  18436. if ( $.isFunction( found ) ) {
  18437. response = found.apply(context, passedArguments);
  18438. }
  18439. else if(found !== undefined) {
  18440. response = found;
  18441. }
  18442. if($.isArray(returnedValue)) {
  18443. returnedValue.push(response);
  18444. }
  18445. else if(returnedValue !== undefined) {
  18446. returnedValue = [returnedValue, response];
  18447. }
  18448. else if(response !== undefined) {
  18449. returnedValue = response;
  18450. }
  18451. return (found !== undefined)
  18452. ? found
  18453. : false
  18454. ;
  18455. }
  18456. };
  18457. module.initialize();
  18458. })
  18459. ;
  18460. return (returnedValue !== undefined)
  18461. ? returnedValue
  18462. : this
  18463. ;
  18464. };
  18465. // Records if CSS transition is available
  18466. $.fn.transition.exists = {};
  18467. $.fn.transition.settings = {
  18468. // module info
  18469. name : 'Transition',
  18470. // hide all output from this component regardless of other settings
  18471. silent : false,
  18472. // debug content outputted to console
  18473. debug : false,
  18474. // verbose debug output
  18475. verbose : false,
  18476. // performance data output
  18477. performance : true,
  18478. // event namespace
  18479. namespace : 'transition',
  18480. // delay between animations in group
  18481. interval : 0,
  18482. // whether group animations should be reversed
  18483. reverse : 'auto',
  18484. // animation callback event
  18485. onStart : function() {},
  18486. onComplete : function() {},
  18487. onShow : function() {},
  18488. onHide : function() {},
  18489. // whether timeout should be used to ensure callback fires in cases animationend does not
  18490. useFailSafe : true,
  18491. // delay in ms for fail safe
  18492. failSafeDelay : 100,
  18493. // whether EXACT animation can occur twice in a row
  18494. allowRepeats : false,
  18495. // Override final display type on visible
  18496. displayType : false,
  18497. // animation duration
  18498. animation : 'fade',
  18499. duration : false,
  18500. // new animations will occur after previous ones
  18501. queue : true,
  18502. metadata : {
  18503. displayType: 'display'
  18504. },
  18505. className : {
  18506. animating : 'animating',
  18507. disabled : 'disabled',
  18508. hidden : 'hidden',
  18509. inward : 'in',
  18510. loading : 'loading',
  18511. looping : 'looping',
  18512. outward : 'out',
  18513. transition : 'transition',
  18514. visible : 'visible'
  18515. },
  18516. // possible errors
  18517. error: {
  18518. noAnimation : 'Element is no longer attached to DOM. Unable to animate. Use silent setting to surpress this warning in production.',
  18519. repeated : 'That animation is already occurring, cancelling repeated animation',
  18520. method : 'The method you called is not defined',
  18521. support : 'This browser does not support CSS animations'
  18522. }
  18523. };
  18524. })( jQuery, window, document );
  18525. /*!
  18526. * # Semantic UI 2.3.0 - API
  18527. * http://github.com/semantic-org/semantic-ui/
  18528. *
  18529. *
  18530. * Released under the MIT license
  18531. * http://opensource.org/licenses/MIT
  18532. *
  18533. */
  18534. ;(function ($, window, document, undefined) {
  18535. "use strict";
  18536. var
  18537. window = (typeof window != 'undefined' && window.Math == Math)
  18538. ? window
  18539. : (typeof self != 'undefined' && self.Math == Math)
  18540. ? self
  18541. : Function('return this')()
  18542. ;
  18543. $.api = $.fn.api = function(parameters) {
  18544. var
  18545. // use window context if none specified
  18546. $allModules = $.isFunction(this)
  18547. ? $(window)
  18548. : $(this),
  18549. moduleSelector = $allModules.selector || '',
  18550. time = new Date().getTime(),
  18551. performance = [],
  18552. query = arguments[0],
  18553. methodInvoked = (typeof query == 'string'),
  18554. queryArguments = [].slice.call(arguments, 1),
  18555. returnedValue
  18556. ;
  18557. $allModules
  18558. .each(function() {
  18559. var
  18560. settings = ( $.isPlainObject(parameters) )
  18561. ? $.extend(true, {}, $.fn.api.settings, parameters)
  18562. : $.extend({}, $.fn.api.settings),
  18563. // internal aliases
  18564. namespace = settings.namespace,
  18565. metadata = settings.metadata,
  18566. selector = settings.selector,
  18567. error = settings.error,
  18568. className = settings.className,
  18569. // define namespaces for modules
  18570. eventNamespace = '.' + namespace,
  18571. moduleNamespace = 'module-' + namespace,
  18572. // element that creates request
  18573. $module = $(this),
  18574. $form = $module.closest(selector.form),
  18575. // context used for state
  18576. $context = (settings.stateContext)
  18577. ? $(settings.stateContext)
  18578. : $module,
  18579. // request details
  18580. ajaxSettings,
  18581. requestSettings,
  18582. url,
  18583. data,
  18584. requestStartTime,
  18585. // standard module
  18586. element = this,
  18587. context = $context[0],
  18588. instance = $module.data(moduleNamespace),
  18589. module
  18590. ;
  18591. module = {
  18592. initialize: function() {
  18593. if(!methodInvoked) {
  18594. module.bind.events();
  18595. }
  18596. module.instantiate();
  18597. },
  18598. instantiate: function() {
  18599. module.verbose('Storing instance of module', module);
  18600. instance = module;
  18601. $module
  18602. .data(moduleNamespace, instance)
  18603. ;
  18604. },
  18605. destroy: function() {
  18606. module.verbose('Destroying previous module for', element);
  18607. $module
  18608. .removeData(moduleNamespace)
  18609. .off(eventNamespace)
  18610. ;
  18611. },
  18612. bind: {
  18613. events: function() {
  18614. var
  18615. triggerEvent = module.get.event()
  18616. ;
  18617. if( triggerEvent ) {
  18618. module.verbose('Attaching API events to element', triggerEvent);
  18619. $module
  18620. .on(triggerEvent + eventNamespace, module.event.trigger)
  18621. ;
  18622. }
  18623. else if(settings.on == 'now') {
  18624. module.debug('Querying API endpoint immediately');
  18625. module.query();
  18626. }
  18627. }
  18628. },
  18629. decode: {
  18630. json: function(response) {
  18631. if(response !== undefined && typeof response == 'string') {
  18632. try {
  18633. response = JSON.parse(response);
  18634. }
  18635. catch(e) {
  18636. // isnt json string
  18637. }
  18638. }
  18639. return response;
  18640. }
  18641. },
  18642. read: {
  18643. cachedResponse: function(url) {
  18644. var
  18645. response
  18646. ;
  18647. if(window.Storage === undefined) {
  18648. module.error(error.noStorage);
  18649. return;
  18650. }
  18651. response = sessionStorage.getItem(url);
  18652. module.debug('Using cached response', url, response);
  18653. response = module.decode.json(response);
  18654. return response;
  18655. }
  18656. },
  18657. write: {
  18658. cachedResponse: function(url, response) {
  18659. if(response && response === '') {
  18660. module.debug('Response empty, not caching', response);
  18661. return;
  18662. }
  18663. if(window.Storage === undefined) {
  18664. module.error(error.noStorage);
  18665. return;
  18666. }
  18667. if( $.isPlainObject(response) ) {
  18668. response = JSON.stringify(response);
  18669. }
  18670. sessionStorage.setItem(url, response);
  18671. module.verbose('Storing cached response for url', url, response);
  18672. }
  18673. },
  18674. query: function() {
  18675. if(module.is.disabled()) {
  18676. module.debug('Element is disabled API request aborted');
  18677. return;
  18678. }
  18679. if(module.is.loading()) {
  18680. if(settings.interruptRequests) {
  18681. module.debug('Interrupting previous request');
  18682. module.abort();
  18683. }
  18684. else {
  18685. module.debug('Cancelling request, previous request is still pending');
  18686. return;
  18687. }
  18688. }
  18689. // pass element metadata to url (value, text)
  18690. if(settings.defaultData) {
  18691. $.extend(true, settings.urlData, module.get.defaultData());
  18692. }
  18693. // Add form content
  18694. if(settings.serializeForm) {
  18695. settings.data = module.add.formData(settings.data);
  18696. }
  18697. // call beforesend and get any settings changes
  18698. requestSettings = module.get.settings();
  18699. // check if before send cancelled request
  18700. if(requestSettings === false) {
  18701. module.cancelled = true;
  18702. module.error(error.beforeSend);
  18703. return;
  18704. }
  18705. else {
  18706. module.cancelled = false;
  18707. }
  18708. // get url
  18709. url = module.get.templatedURL();
  18710. if(!url && !module.is.mocked()) {
  18711. module.error(error.missingURL);
  18712. return;
  18713. }
  18714. // replace variables
  18715. url = module.add.urlData( url );
  18716. // missing url parameters
  18717. if( !url && !module.is.mocked()) {
  18718. return;
  18719. }
  18720. requestSettings.url = settings.base + url;
  18721. // look for jQuery ajax parameters in settings
  18722. ajaxSettings = $.extend(true, {}, settings, {
  18723. type : settings.method || settings.type,
  18724. data : data,
  18725. url : settings.base + url,
  18726. beforeSend : settings.beforeXHR,
  18727. success : function() {},
  18728. failure : function() {},
  18729. complete : function() {}
  18730. });
  18731. module.debug('Querying URL', ajaxSettings.url);
  18732. module.verbose('Using AJAX settings', ajaxSettings);
  18733. if(settings.cache === 'local' && module.read.cachedResponse(url)) {
  18734. module.debug('Response returned from local cache');
  18735. module.request = module.create.request();
  18736. module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
  18737. return;
  18738. }
  18739. if( !settings.throttle ) {
  18740. module.debug('Sending request', data, ajaxSettings.method);
  18741. module.send.request();
  18742. }
  18743. else {
  18744. if(!settings.throttleFirstRequest && !module.timer) {
  18745. module.debug('Sending request', data, ajaxSettings.method);
  18746. module.send.request();
  18747. module.timer = setTimeout(function(){}, settings.throttle);
  18748. }
  18749. else {
  18750. module.debug('Throttling request', settings.throttle);
  18751. clearTimeout(module.timer);
  18752. module.timer = setTimeout(function() {
  18753. if(module.timer) {
  18754. delete module.timer;
  18755. }
  18756. module.debug('Sending throttled request', data, ajaxSettings.method);
  18757. module.send.request();
  18758. }, settings.throttle);
  18759. }
  18760. }
  18761. },
  18762. should: {
  18763. removeError: function() {
  18764. return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
  18765. }
  18766. },
  18767. is: {
  18768. disabled: function() {
  18769. return ($module.filter(selector.disabled).length > 0);
  18770. },
  18771. expectingJSON: function() {
  18772. return settings.dataType === 'json' || settings.dataType === 'jsonp';
  18773. },
  18774. form: function() {
  18775. return $module.is('form') || $context.is('form');
  18776. },
  18777. mocked: function() {
  18778. return (settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync);
  18779. },
  18780. input: function() {
  18781. return $module.is('input');
  18782. },
  18783. loading: function() {
  18784. return (module.request)
  18785. ? (module.request.state() == 'pending')
  18786. : false
  18787. ;
  18788. },
  18789. abortedRequest: function(xhr) {
  18790. if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
  18791. module.verbose('XHR request determined to be aborted');
  18792. return true;
  18793. }
  18794. else {
  18795. module.verbose('XHR request was not aborted');
  18796. return false;
  18797. }
  18798. },
  18799. validResponse: function(response) {
  18800. if( (!module.is.expectingJSON()) || !$.isFunction(settings.successTest) ) {
  18801. module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
  18802. return true;
  18803. }
  18804. module.debug('Checking JSON returned success', settings.successTest, response);
  18805. if( settings.successTest(response) ) {
  18806. module.debug('Response passed success test', response);
  18807. return true;
  18808. }
  18809. else {
  18810. module.debug('Response failed success test', response);
  18811. return false;
  18812. }
  18813. }
  18814. },
  18815. was: {
  18816. cancelled: function() {
  18817. return (module.cancelled || false);
  18818. },
  18819. succesful: function() {
  18820. return (module.request && module.request.state() == 'resolved');
  18821. },
  18822. failure: function() {
  18823. return (module.request && module.request.state() == 'rejected');
  18824. },
  18825. complete: function() {
  18826. return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
  18827. }
  18828. },
  18829. add: {
  18830. urlData: function(url, urlData) {
  18831. var
  18832. requiredVariables,
  18833. optionalVariables
  18834. ;
  18835. if(url) {
  18836. requiredVariables = url.match(settings.regExp.required);
  18837. optionalVariables = url.match(settings.regExp.optional);
  18838. urlData = urlData || settings.urlData;
  18839. if(requiredVariables) {
  18840. module.debug('Looking for required URL variables', requiredVariables);
  18841. $.each(requiredVariables, function(index, templatedString) {
  18842. var
  18843. // allow legacy {$var} style
  18844. variable = (templatedString.indexOf('$') !== -1)
  18845. ? templatedString.substr(2, templatedString.length - 3)
  18846. : templatedString.substr(1, templatedString.length - 2),
  18847. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  18848. ? urlData[variable]
  18849. : ($module.data(variable) !== undefined)
  18850. ? $module.data(variable)
  18851. : ($context.data(variable) !== undefined)
  18852. ? $context.data(variable)
  18853. : urlData[variable]
  18854. ;
  18855. // remove value
  18856. if(value === undefined) {
  18857. module.error(error.requiredParameter, variable, url);
  18858. url = false;
  18859. return false;
  18860. }
  18861. else {
  18862. module.verbose('Found required variable', variable, value);
  18863. value = (settings.encodeParameters)
  18864. ? module.get.urlEncodedValue(value)
  18865. : value
  18866. ;
  18867. url = url.replace(templatedString, value);
  18868. }
  18869. });
  18870. }
  18871. if(optionalVariables) {
  18872. module.debug('Looking for optional URL variables', requiredVariables);
  18873. $.each(optionalVariables, function(index, templatedString) {
  18874. var
  18875. // allow legacy {/$var} style
  18876. variable = (templatedString.indexOf('$') !== -1)
  18877. ? templatedString.substr(3, templatedString.length - 4)
  18878. : templatedString.substr(2, templatedString.length - 3),
  18879. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  18880. ? urlData[variable]
  18881. : ($module.data(variable) !== undefined)
  18882. ? $module.data(variable)
  18883. : ($context.data(variable) !== undefined)
  18884. ? $context.data(variable)
  18885. : urlData[variable]
  18886. ;
  18887. // optional replacement
  18888. if(value !== undefined) {
  18889. module.verbose('Optional variable Found', variable, value);
  18890. url = url.replace(templatedString, value);
  18891. }
  18892. else {
  18893. module.verbose('Optional variable not found', variable);
  18894. // remove preceding slash if set
  18895. if(url.indexOf('/' + templatedString) !== -1) {
  18896. url = url.replace('/' + templatedString, '');
  18897. }
  18898. else {
  18899. url = url.replace(templatedString, '');
  18900. }
  18901. }
  18902. });
  18903. }
  18904. }
  18905. return url;
  18906. },
  18907. formData: function(data) {
  18908. var
  18909. canSerialize = ($.fn.serializeObject !== undefined),
  18910. formData = (canSerialize)
  18911. ? $form.serializeObject()
  18912. : $form.serialize(),
  18913. hasOtherData
  18914. ;
  18915. data = data || settings.data;
  18916. hasOtherData = $.isPlainObject(data);
  18917. if(hasOtherData) {
  18918. if(canSerialize) {
  18919. module.debug('Extending existing data with form data', data, formData);
  18920. data = $.extend(true, {}, data, formData);
  18921. }
  18922. else {
  18923. module.error(error.missingSerialize);
  18924. module.debug('Cant extend data. Replacing data with form data', data, formData);
  18925. data = formData;
  18926. }
  18927. }
  18928. else {
  18929. module.debug('Adding form data', formData);
  18930. data = formData;
  18931. }
  18932. return data;
  18933. }
  18934. },
  18935. send: {
  18936. request: function() {
  18937. module.set.loading();
  18938. module.request = module.create.request();
  18939. if( module.is.mocked() ) {
  18940. module.mockedXHR = module.create.mockedXHR();
  18941. }
  18942. else {
  18943. module.xhr = module.create.xhr();
  18944. }
  18945. settings.onRequest.call(context, module.request, module.xhr);
  18946. }
  18947. },
  18948. event: {
  18949. trigger: function(event) {
  18950. module.query();
  18951. if(event.type == 'submit' || event.type == 'click') {
  18952. event.preventDefault();
  18953. }
  18954. },
  18955. xhr: {
  18956. always: function() {
  18957. // nothing special
  18958. },
  18959. done: function(response, textStatus, xhr) {
  18960. var
  18961. context = this,
  18962. elapsedTime = (new Date().getTime() - requestStartTime),
  18963. timeLeft = (settings.loadingDuration - elapsedTime),
  18964. translatedResponse = ( $.isFunction(settings.onResponse) )
  18965. ? module.is.expectingJSON()
  18966. ? settings.onResponse.call(context, $.extend(true, {}, response))
  18967. : settings.onResponse.call(context, response)
  18968. : false
  18969. ;
  18970. timeLeft = (timeLeft > 0)
  18971. ? timeLeft
  18972. : 0
  18973. ;
  18974. if(translatedResponse) {
  18975. module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
  18976. response = translatedResponse;
  18977. }
  18978. if(timeLeft > 0) {
  18979. module.debug('Response completed early delaying state change by', timeLeft);
  18980. }
  18981. setTimeout(function() {
  18982. if( module.is.validResponse(response) ) {
  18983. module.request.resolveWith(context, [response, xhr]);
  18984. }
  18985. else {
  18986. module.request.rejectWith(context, [xhr, 'invalid']);
  18987. }
  18988. }, timeLeft);
  18989. },
  18990. fail: function(xhr, status, httpMessage) {
  18991. var
  18992. context = this,
  18993. elapsedTime = (new Date().getTime() - requestStartTime),
  18994. timeLeft = (settings.loadingDuration - elapsedTime)
  18995. ;
  18996. timeLeft = (timeLeft > 0)
  18997. ? timeLeft
  18998. : 0
  18999. ;
  19000. if(timeLeft > 0) {
  19001. module.debug('Response completed early delaying state change by', timeLeft);
  19002. }
  19003. setTimeout(function() {
  19004. if( module.is.abortedRequest(xhr) ) {
  19005. module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
  19006. }
  19007. else {
  19008. module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
  19009. }
  19010. }, timeLeft);
  19011. }
  19012. },
  19013. request: {
  19014. done: function(response, xhr) {
  19015. module.debug('Successful API Response', response);
  19016. if(settings.cache === 'local' && url) {
  19017. module.write.cachedResponse(url, response);
  19018. module.debug('Saving server response locally', module.cache);
  19019. }
  19020. settings.onSuccess.call(context, response, $module, xhr);
  19021. },
  19022. complete: function(firstParameter, secondParameter) {
  19023. var
  19024. xhr,
  19025. response
  19026. ;
  19027. // have to guess callback parameters based on request success
  19028. if( module.was.succesful() ) {
  19029. response = firstParameter;
  19030. xhr = secondParameter;
  19031. }
  19032. else {
  19033. xhr = firstParameter;
  19034. response = module.get.responseFromXHR(xhr);
  19035. }
  19036. module.remove.loading();
  19037. settings.onComplete.call(context, response, $module, xhr);
  19038. },
  19039. fail: function(xhr, status, httpMessage) {
  19040. var
  19041. // pull response from xhr if available
  19042. response = module.get.responseFromXHR(xhr),
  19043. errorMessage = module.get.errorFromRequest(response, status, httpMessage)
  19044. ;
  19045. if(status == 'aborted') {
  19046. module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
  19047. settings.onAbort.call(context, status, $module, xhr);
  19048. return true;
  19049. }
  19050. else if(status == 'invalid') {
  19051. module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
  19052. }
  19053. else if(status == 'error') {
  19054. if(xhr !== undefined) {
  19055. module.debug('XHR produced a server error', status, httpMessage);
  19056. // make sure we have an error to display to console
  19057. if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
  19058. module.error(error.statusMessage + httpMessage, ajaxSettings.url);
  19059. }
  19060. settings.onError.call(context, errorMessage, $module, xhr);
  19061. }
  19062. }
  19063. if(settings.errorDuration && status !== 'aborted') {
  19064. module.debug('Adding error state');
  19065. module.set.error();
  19066. if( module.should.removeError() ) {
  19067. setTimeout(module.remove.error, settings.errorDuration);
  19068. }
  19069. }
  19070. module.debug('API Request failed', errorMessage, xhr);
  19071. settings.onFailure.call(context, response, $module, xhr);
  19072. }
  19073. }
  19074. },
  19075. create: {
  19076. request: function() {
  19077. // api request promise
  19078. return $.Deferred()
  19079. .always(module.event.request.complete)
  19080. .done(module.event.request.done)
  19081. .fail(module.event.request.fail)
  19082. ;
  19083. },
  19084. mockedXHR: function () {
  19085. var
  19086. // xhr does not simulate these properties of xhr but must return them
  19087. textStatus = false,
  19088. status = false,
  19089. httpMessage = false,
  19090. responder = settings.mockResponse || settings.response,
  19091. asyncResponder = settings.mockResponseAsync || settings.responseAsync,
  19092. asyncCallback,
  19093. response,
  19094. mockedXHR
  19095. ;
  19096. mockedXHR = $.Deferred()
  19097. .always(module.event.xhr.complete)
  19098. .done(module.event.xhr.done)
  19099. .fail(module.event.xhr.fail)
  19100. ;
  19101. if(responder) {
  19102. if( $.isFunction(responder) ) {
  19103. module.debug('Using specified synchronous callback', responder);
  19104. response = responder.call(context, requestSettings);
  19105. }
  19106. else {
  19107. module.debug('Using settings specified response', responder);
  19108. response = responder;
  19109. }
  19110. // simulating response
  19111. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  19112. }
  19113. else if( $.isFunction(asyncResponder) ) {
  19114. asyncCallback = function(response) {
  19115. module.debug('Async callback returned response', response);
  19116. if(response) {
  19117. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  19118. }
  19119. else {
  19120. mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
  19121. }
  19122. };
  19123. module.debug('Using specified async response callback', asyncResponder);
  19124. asyncResponder.call(context, requestSettings, asyncCallback);
  19125. }
  19126. return mockedXHR;
  19127. },
  19128. xhr: function() {
  19129. var
  19130. xhr
  19131. ;
  19132. // ajax request promise
  19133. xhr = $.ajax(ajaxSettings)
  19134. .always(module.event.xhr.always)
  19135. .done(module.event.xhr.done)
  19136. .fail(module.event.xhr.fail)
  19137. ;
  19138. module.verbose('Created server request', xhr, ajaxSettings);
  19139. return xhr;
  19140. }
  19141. },
  19142. set: {
  19143. error: function() {
  19144. module.verbose('Adding error state to element', $context);
  19145. $context.addClass(className.error);
  19146. },
  19147. loading: function() {
  19148. module.verbose('Adding loading state to element', $context);
  19149. $context.addClass(className.loading);
  19150. requestStartTime = new Date().getTime();
  19151. }
  19152. },
  19153. remove: {
  19154. error: function() {
  19155. module.verbose('Removing error state from element', $context);
  19156. $context.removeClass(className.error);
  19157. },
  19158. loading: function() {
  19159. module.verbose('Removing loading state from element', $context);
  19160. $context.removeClass(className.loading);
  19161. }
  19162. },
  19163. get: {
  19164. responseFromXHR: function(xhr) {
  19165. return $.isPlainObject(xhr)
  19166. ? (module.is.expectingJSON())
  19167. ? module.decode.json(xhr.responseText)
  19168. : xhr.responseText
  19169. : false
  19170. ;
  19171. },
  19172. errorFromRequest: function(response, status, httpMessage) {
  19173. return ($.isPlainObject(response) && response.error !== undefined)
  19174. ? response.error // use json error message
  19175. : (settings.error[status] !== undefined) // use server error message
  19176. ? settings.error[status]
  19177. : httpMessage
  19178. ;
  19179. },
  19180. request: function() {
  19181. return module.request || false;
  19182. },
  19183. xhr: function() {
  19184. return module.xhr || false;
  19185. },
  19186. settings: function() {
  19187. var
  19188. runSettings
  19189. ;
  19190. runSettings = settings.beforeSend.call(context, settings);
  19191. if(runSettings) {
  19192. if(runSettings.success !== undefined) {
  19193. module.debug('Legacy success callback detected', runSettings);
  19194. module.error(error.legacyParameters, runSettings.success);
  19195. runSettings.onSuccess = runSettings.success;
  19196. }
  19197. if(runSettings.failure !== undefined) {
  19198. module.debug('Legacy failure callback detected', runSettings);
  19199. module.error(error.legacyParameters, runSettings.failure);
  19200. runSettings.onFailure = runSettings.failure;
  19201. }
  19202. if(runSettings.complete !== undefined) {
  19203. module.debug('Legacy complete callback detected', runSettings);
  19204. module.error(error.legacyParameters, runSettings.complete);
  19205. runSettings.onComplete = runSettings.complete;
  19206. }
  19207. }
  19208. if(runSettings === undefined) {
  19209. module.error(error.noReturnedValue);
  19210. }
  19211. if(runSettings === false) {
  19212. return runSettings;
  19213. }
  19214. return (runSettings !== undefined)
  19215. ? $.extend(true, {}, runSettings)
  19216. : $.extend(true, {}, settings)
  19217. ;
  19218. },
  19219. urlEncodedValue: function(value) {
  19220. var
  19221. decodedValue = window.decodeURIComponent(value),
  19222. encodedValue = window.encodeURIComponent(value),
  19223. alreadyEncoded = (decodedValue !== value)
  19224. ;
  19225. if(alreadyEncoded) {
  19226. module.debug('URL value is already encoded, avoiding double encoding', value);
  19227. return value;
  19228. }
  19229. module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
  19230. return encodedValue;
  19231. },
  19232. defaultData: function() {
  19233. var
  19234. data = {}
  19235. ;
  19236. if( !$.isWindow(element) ) {
  19237. if( module.is.input() ) {
  19238. data.value = $module.val();
  19239. }
  19240. else if( module.is.form() ) {
  19241. }
  19242. else {
  19243. data.text = $module.text();
  19244. }
  19245. }
  19246. return data;
  19247. },
  19248. event: function() {
  19249. if( $.isWindow(element) || settings.on == 'now' ) {
  19250. module.debug('API called without element, no events attached');
  19251. return false;
  19252. }
  19253. else if(settings.on == 'auto') {
  19254. if( $module.is('input') ) {
  19255. return (element.oninput !== undefined)
  19256. ? 'input'
  19257. : (element.onpropertychange !== undefined)
  19258. ? 'propertychange'
  19259. : 'keyup'
  19260. ;
  19261. }
  19262. else if( $module.is('form') ) {
  19263. return 'submit';
  19264. }
  19265. else {
  19266. return 'click';
  19267. }
  19268. }
  19269. else {
  19270. return settings.on;
  19271. }
  19272. },
  19273. templatedURL: function(action) {
  19274. action = action || $module.data(metadata.action) || settings.action || false;
  19275. url = $module.data(metadata.url) || settings.url || false;
  19276. if(url) {
  19277. module.debug('Using specified url', url);
  19278. return url;
  19279. }
  19280. if(action) {
  19281. module.debug('Looking up url for action', action, settings.api);
  19282. if(settings.api[action] === undefined && !module.is.mocked()) {
  19283. module.error(error.missingAction, settings.action, settings.api);
  19284. return;
  19285. }
  19286. url = settings.api[action];
  19287. }
  19288. else if( module.is.form() ) {
  19289. url = $module.attr('action') || $context.attr('action') || false;
  19290. module.debug('No url or action specified, defaulting to form action', url);
  19291. }
  19292. return url;
  19293. }
  19294. },
  19295. abort: function() {
  19296. var
  19297. xhr = module.get.xhr()
  19298. ;
  19299. if( xhr && xhr.state() !== 'resolved') {
  19300. module.debug('Cancelling API request');
  19301. xhr.abort();
  19302. }
  19303. },
  19304. // reset state
  19305. reset: function() {
  19306. module.remove.error();
  19307. module.remove.loading();
  19308. },
  19309. setting: function(name, value) {
  19310. module.debug('Changing setting', name, value);
  19311. if( $.isPlainObject(name) ) {
  19312. $.extend(true, settings, name);
  19313. }
  19314. else if(value !== undefined) {
  19315. if($.isPlainObject(settings[name])) {
  19316. $.extend(true, settings[name], value);
  19317. }
  19318. else {
  19319. settings[name] = value;
  19320. }
  19321. }
  19322. else {
  19323. return settings[name];
  19324. }
  19325. },
  19326. internal: function(name, value) {
  19327. if( $.isPlainObject(name) ) {
  19328. $.extend(true, module, name);
  19329. }
  19330. else if(value !== undefined) {
  19331. module[name] = value;
  19332. }
  19333. else {
  19334. return module[name];
  19335. }
  19336. },
  19337. debug: function() {
  19338. if(!settings.silent && settings.debug) {
  19339. if(settings.performance) {
  19340. module.performance.log(arguments);
  19341. }
  19342. else {
  19343. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19344. module.debug.apply(console, arguments);
  19345. }
  19346. }
  19347. },
  19348. verbose: function() {
  19349. if(!settings.silent && settings.verbose && settings.debug) {
  19350. if(settings.performance) {
  19351. module.performance.log(arguments);
  19352. }
  19353. else {
  19354. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19355. module.verbose.apply(console, arguments);
  19356. }
  19357. }
  19358. },
  19359. error: function() {
  19360. if(!settings.silent) {
  19361. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  19362. module.error.apply(console, arguments);
  19363. }
  19364. },
  19365. performance: {
  19366. log: function(message) {
  19367. var
  19368. currentTime,
  19369. executionTime,
  19370. previousTime
  19371. ;
  19372. if(settings.performance) {
  19373. currentTime = new Date().getTime();
  19374. previousTime = time || currentTime;
  19375. executionTime = currentTime - previousTime;
  19376. time = currentTime;
  19377. performance.push({
  19378. 'Name' : message[0],
  19379. 'Arguments' : [].slice.call(message, 1) || '',
  19380. //'Element' : element,
  19381. 'Execution Time' : executionTime
  19382. });
  19383. }
  19384. clearTimeout(module.performance.timer);
  19385. module.performance.timer = setTimeout(module.performance.display, 500);
  19386. },
  19387. display: function() {
  19388. var
  19389. title = settings.name + ':',
  19390. totalTime = 0
  19391. ;
  19392. time = false;
  19393. clearTimeout(module.performance.timer);
  19394. $.each(performance, function(index, data) {
  19395. totalTime += data['Execution Time'];
  19396. });
  19397. title += ' ' + totalTime + 'ms';
  19398. if(moduleSelector) {
  19399. title += ' \'' + moduleSelector + '\'';
  19400. }
  19401. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  19402. console.groupCollapsed(title);
  19403. if(console.table) {
  19404. console.table(performance);
  19405. }
  19406. else {
  19407. $.each(performance, function(index, data) {
  19408. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  19409. });
  19410. }
  19411. console.groupEnd();
  19412. }
  19413. performance = [];
  19414. }
  19415. },
  19416. invoke: function(query, passedArguments, context) {
  19417. var
  19418. object = instance,
  19419. maxDepth,
  19420. found,
  19421. response
  19422. ;
  19423. passedArguments = passedArguments || queryArguments;
  19424. context = element || context;
  19425. if(typeof query == 'string' && object !== undefined) {
  19426. query = query.split(/[\. ]/);
  19427. maxDepth = query.length - 1;
  19428. $.each(query, function(depth, value) {
  19429. var camelCaseValue = (depth != maxDepth)
  19430. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  19431. : query
  19432. ;
  19433. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  19434. object = object[camelCaseValue];
  19435. }
  19436. else if( object[camelCaseValue] !== undefined ) {
  19437. found = object[camelCaseValue];
  19438. return false;
  19439. }
  19440. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  19441. object = object[value];
  19442. }
  19443. else if( object[value] !== undefined ) {
  19444. found = object[value];
  19445. return false;
  19446. }
  19447. else {
  19448. module.error(error.method, query);
  19449. return false;
  19450. }
  19451. });
  19452. }
  19453. if ( $.isFunction( found ) ) {
  19454. response = found.apply(context, passedArguments);
  19455. }
  19456. else if(found !== undefined) {
  19457. response = found;
  19458. }
  19459. if($.isArray(returnedValue)) {
  19460. returnedValue.push(response);
  19461. }
  19462. else if(returnedValue !== undefined) {
  19463. returnedValue = [returnedValue, response];
  19464. }
  19465. else if(response !== undefined) {
  19466. returnedValue = response;
  19467. }
  19468. return found;
  19469. }
  19470. };
  19471. if(methodInvoked) {
  19472. if(instance === undefined) {
  19473. module.initialize();
  19474. }
  19475. module.invoke(query);
  19476. }
  19477. else {
  19478. if(instance !== undefined) {
  19479. instance.invoke('destroy');
  19480. }
  19481. module.initialize();
  19482. }
  19483. })
  19484. ;
  19485. return (returnedValue !== undefined)
  19486. ? returnedValue
  19487. : this
  19488. ;
  19489. };
  19490. $.api.settings = {
  19491. name : 'API',
  19492. namespace : 'api',
  19493. debug : false,
  19494. verbose : false,
  19495. performance : true,
  19496. // object containing all templates endpoints
  19497. api : {},
  19498. // whether to cache responses
  19499. cache : true,
  19500. // whether new requests should abort previous requests
  19501. interruptRequests : true,
  19502. // event binding
  19503. on : 'auto',
  19504. // context for applying state classes
  19505. stateContext : false,
  19506. // duration for loading state
  19507. loadingDuration : 0,
  19508. // whether to hide errors after a period of time
  19509. hideError : 'auto',
  19510. // duration for error state
  19511. errorDuration : 2000,
  19512. // whether parameters should be encoded with encodeURIComponent
  19513. encodeParameters : true,
  19514. // API action to use
  19515. action : false,
  19516. // templated URL to use
  19517. url : false,
  19518. // base URL to apply to all endpoints
  19519. base : '',
  19520. // data that will
  19521. urlData : {},
  19522. // whether to add default data to url data
  19523. defaultData : true,
  19524. // whether to serialize closest form
  19525. serializeForm : false,
  19526. // how long to wait before request should occur
  19527. throttle : 0,
  19528. // whether to throttle first request or only repeated
  19529. throttleFirstRequest : true,
  19530. // standard ajax settings
  19531. method : 'get',
  19532. data : {},
  19533. dataType : 'json',
  19534. // mock response
  19535. mockResponse : false,
  19536. mockResponseAsync : false,
  19537. // aliases for mock
  19538. response : false,
  19539. responseAsync : false,
  19540. // callbacks before request
  19541. beforeSend : function(settings) { return settings; },
  19542. beforeXHR : function(xhr) {},
  19543. onRequest : function(promise, xhr) {},
  19544. // after request
  19545. onResponse : false, // function(response) { },
  19546. // response was successful, if JSON passed validation
  19547. onSuccess : function(response, $module) {},
  19548. // request finished without aborting
  19549. onComplete : function(response, $module) {},
  19550. // failed JSON success test
  19551. onFailure : function(response, $module) {},
  19552. // server error
  19553. onError : function(errorMessage, $module) {},
  19554. // request aborted
  19555. onAbort : function(errorMessage, $module) {},
  19556. successTest : false,
  19557. // errors
  19558. error : {
  19559. beforeSend : 'The before send function has aborted the request',
  19560. error : 'There was an error with your request',
  19561. exitConditions : 'API Request Aborted. Exit conditions met',
  19562. JSONParse : 'JSON could not be parsed during error handling',
  19563. legacyParameters : 'You are using legacy API success callback names',
  19564. method : 'The method you called is not defined',
  19565. missingAction : 'API action used but no url was defined',
  19566. missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
  19567. missingURL : 'No URL specified for api event',
  19568. noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
  19569. noStorage : 'Caching responses locally requires session storage',
  19570. parseError : 'There was an error parsing your request',
  19571. requiredParameter : 'Missing a required URL parameter: ',
  19572. statusMessage : 'Server gave an error: ',
  19573. timeout : 'Your request timed out'
  19574. },
  19575. regExp : {
  19576. required : /\{\$*[A-z0-9]+\}/g,
  19577. optional : /\{\/\$*[A-z0-9]+\}/g,
  19578. },
  19579. className: {
  19580. loading : 'loading',
  19581. error : 'error'
  19582. },
  19583. selector: {
  19584. disabled : '.disabled',
  19585. form : 'form'
  19586. },
  19587. metadata: {
  19588. action : 'action',
  19589. url : 'url'
  19590. }
  19591. };
  19592. })( jQuery, window, document );
  19593. /*!
  19594. * # Semantic UI 2.3.0 - State
  19595. * http://github.com/semantic-org/semantic-ui/
  19596. *
  19597. *
  19598. * Released under the MIT license
  19599. * http://opensource.org/licenses/MIT
  19600. *
  19601. */
  19602. ;(function ($, window, document, undefined) {
  19603. "use strict";
  19604. window = (typeof window != 'undefined' && window.Math == Math)
  19605. ? window
  19606. : (typeof self != 'undefined' && self.Math == Math)
  19607. ? self
  19608. : Function('return this')()
  19609. ;
  19610. $.fn.state = function(parameters) {
  19611. var
  19612. $allModules = $(this),
  19613. moduleSelector = $allModules.selector || '',
  19614. hasTouch = ('ontouchstart' in document.documentElement),
  19615. time = new Date().getTime(),
  19616. performance = [],
  19617. query = arguments[0],
  19618. methodInvoked = (typeof query == 'string'),
  19619. queryArguments = [].slice.call(arguments, 1),
  19620. returnedValue
  19621. ;
  19622. $allModules
  19623. .each(function() {
  19624. var
  19625. settings = ( $.isPlainObject(parameters) )
  19626. ? $.extend(true, {}, $.fn.state.settings, parameters)
  19627. : $.extend({}, $.fn.state.settings),
  19628. error = settings.error,
  19629. metadata = settings.metadata,
  19630. className = settings.className,
  19631. namespace = settings.namespace,
  19632. states = settings.states,
  19633. text = settings.text,
  19634. eventNamespace = '.' + namespace,
  19635. moduleNamespace = namespace + '-module',
  19636. $module = $(this),
  19637. element = this,
  19638. instance = $module.data(moduleNamespace),
  19639. module
  19640. ;
  19641. module = {
  19642. initialize: function() {
  19643. module.verbose('Initializing module');
  19644. // allow module to guess desired state based on element
  19645. if(settings.automatic) {
  19646. module.add.defaults();
  19647. }
  19648. // bind events with delegated events
  19649. if(settings.context && moduleSelector !== '') {
  19650. $(settings.context)
  19651. .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text)
  19652. .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text)
  19653. .on(moduleSelector, 'click' + eventNamespace, module.toggle.state)
  19654. ;
  19655. }
  19656. else {
  19657. $module
  19658. .on('mouseenter' + eventNamespace, module.change.text)
  19659. .on('mouseleave' + eventNamespace, module.reset.text)
  19660. .on('click' + eventNamespace, module.toggle.state)
  19661. ;
  19662. }
  19663. module.instantiate();
  19664. },
  19665. instantiate: function() {
  19666. module.verbose('Storing instance of module', module);
  19667. instance = module;
  19668. $module
  19669. .data(moduleNamespace, module)
  19670. ;
  19671. },
  19672. destroy: function() {
  19673. module.verbose('Destroying previous module', instance);
  19674. $module
  19675. .off(eventNamespace)
  19676. .removeData(moduleNamespace)
  19677. ;
  19678. },
  19679. refresh: function() {
  19680. module.verbose('Refreshing selector cache');
  19681. $module = $(element);
  19682. },
  19683. add: {
  19684. defaults: function() {
  19685. var
  19686. userStates = parameters && $.isPlainObject(parameters.states)
  19687. ? parameters.states
  19688. : {}
  19689. ;
  19690. $.each(settings.defaults, function(type, typeStates) {
  19691. if( module.is[type] !== undefined && module.is[type]() ) {
  19692. module.verbose('Adding default states', type, element);
  19693. $.extend(settings.states, typeStates, userStates);
  19694. }
  19695. });
  19696. }
  19697. },
  19698. is: {
  19699. active: function() {
  19700. return $module.hasClass(className.active);
  19701. },
  19702. loading: function() {
  19703. return $module.hasClass(className.loading);
  19704. },
  19705. inactive: function() {
  19706. return !( $module.hasClass(className.active) );
  19707. },
  19708. state: function(state) {
  19709. if(className[state] === undefined) {
  19710. return false;
  19711. }
  19712. return $module.hasClass( className[state] );
  19713. },
  19714. enabled: function() {
  19715. return !( $module.is(settings.filter.active) );
  19716. },
  19717. disabled: function() {
  19718. return ( $module.is(settings.filter.active) );
  19719. },
  19720. textEnabled: function() {
  19721. return !( $module.is(settings.filter.text) );
  19722. },
  19723. // definitions for automatic type detection
  19724. button: function() {
  19725. return $module.is('.button:not(a, .submit)');
  19726. },
  19727. input: function() {
  19728. return $module.is('input');
  19729. },
  19730. progress: function() {
  19731. return $module.is('.ui.progress');
  19732. }
  19733. },
  19734. allow: function(state) {
  19735. module.debug('Now allowing state', state);
  19736. states[state] = true;
  19737. },
  19738. disallow: function(state) {
  19739. module.debug('No longer allowing', state);
  19740. states[state] = false;
  19741. },
  19742. allows: function(state) {
  19743. return states[state] || false;
  19744. },
  19745. enable: function() {
  19746. $module.removeClass(className.disabled);
  19747. },
  19748. disable: function() {
  19749. $module.addClass(className.disabled);
  19750. },
  19751. setState: function(state) {
  19752. if(module.allows(state)) {
  19753. $module.addClass( className[state] );
  19754. }
  19755. },
  19756. removeState: function(state) {
  19757. if(module.allows(state)) {
  19758. $module.removeClass( className[state] );
  19759. }
  19760. },
  19761. toggle: {
  19762. state: function() {
  19763. var
  19764. apiRequest,
  19765. requestCancelled
  19766. ;
  19767. if( module.allows('active') && module.is.enabled() ) {
  19768. module.refresh();
  19769. if($.fn.api !== undefined) {
  19770. apiRequest = $module.api('get request');
  19771. requestCancelled = $module.api('was cancelled');
  19772. if( requestCancelled ) {
  19773. module.debug('API Request cancelled by beforesend');
  19774. settings.activateTest = function(){ return false; };
  19775. settings.deactivateTest = function(){ return false; };
  19776. }
  19777. else if(apiRequest) {
  19778. module.listenTo(apiRequest);
  19779. return;
  19780. }
  19781. }
  19782. module.change.state();
  19783. }
  19784. }
  19785. },
  19786. listenTo: function(apiRequest) {
  19787. module.debug('API request detected, waiting for state signal', apiRequest);
  19788. if(apiRequest) {
  19789. if(text.loading) {
  19790. module.update.text(text.loading);
  19791. }
  19792. $.when(apiRequest)
  19793. .then(function() {
  19794. if(apiRequest.state() == 'resolved') {
  19795. module.debug('API request succeeded');
  19796. settings.activateTest = function(){ return true; };
  19797. settings.deactivateTest = function(){ return true; };
  19798. }
  19799. else {
  19800. module.debug('API request failed');
  19801. settings.activateTest = function(){ return false; };
  19802. settings.deactivateTest = function(){ return false; };
  19803. }
  19804. module.change.state();
  19805. })
  19806. ;
  19807. }
  19808. },
  19809. // checks whether active/inactive state can be given
  19810. change: {
  19811. state: function() {
  19812. module.debug('Determining state change direction');
  19813. // inactive to active change
  19814. if( module.is.inactive() ) {
  19815. module.activate();
  19816. }
  19817. else {
  19818. module.deactivate();
  19819. }
  19820. if(settings.sync) {
  19821. module.sync();
  19822. }
  19823. settings.onChange.call(element);
  19824. },
  19825. text: function() {
  19826. if( module.is.textEnabled() ) {
  19827. if(module.is.disabled() ) {
  19828. module.verbose('Changing text to disabled text', text.hover);
  19829. module.update.text(text.disabled);
  19830. }
  19831. else if( module.is.active() ) {
  19832. if(text.hover) {
  19833. module.verbose('Changing text to hover text', text.hover);
  19834. module.update.text(text.hover);
  19835. }
  19836. else if(text.deactivate) {
  19837. module.verbose('Changing text to deactivating text', text.deactivate);
  19838. module.update.text(text.deactivate);
  19839. }
  19840. }
  19841. else {
  19842. if(text.hover) {
  19843. module.verbose('Changing text to hover text', text.hover);
  19844. module.update.text(text.hover);
  19845. }
  19846. else if(text.activate){
  19847. module.verbose('Changing text to activating text', text.activate);
  19848. module.update.text(text.activate);
  19849. }
  19850. }
  19851. }
  19852. }
  19853. },
  19854. activate: function() {
  19855. if( settings.activateTest.call(element) ) {
  19856. module.debug('Setting state to active');
  19857. $module
  19858. .addClass(className.active)
  19859. ;
  19860. module.update.text(text.active);
  19861. settings.onActivate.call(element);
  19862. }
  19863. },
  19864. deactivate: function() {
  19865. if( settings.deactivateTest.call(element) ) {
  19866. module.debug('Setting state to inactive');
  19867. $module
  19868. .removeClass(className.active)
  19869. ;
  19870. module.update.text(text.inactive);
  19871. settings.onDeactivate.call(element);
  19872. }
  19873. },
  19874. sync: function() {
  19875. module.verbose('Syncing other buttons to current state');
  19876. if( module.is.active() ) {
  19877. $allModules
  19878. .not($module)
  19879. .state('activate');
  19880. }
  19881. else {
  19882. $allModules
  19883. .not($module)
  19884. .state('deactivate')
  19885. ;
  19886. }
  19887. },
  19888. get: {
  19889. text: function() {
  19890. return (settings.selector.text)
  19891. ? $module.find(settings.selector.text).text()
  19892. : $module.html()
  19893. ;
  19894. },
  19895. textFor: function(state) {
  19896. return text[state] || false;
  19897. }
  19898. },
  19899. flash: {
  19900. text: function(text, duration, callback) {
  19901. var
  19902. previousText = module.get.text()
  19903. ;
  19904. module.debug('Flashing text message', text, duration);
  19905. text = text || settings.text.flash;
  19906. duration = duration || settings.flashDuration;
  19907. callback = callback || function() {};
  19908. module.update.text(text);
  19909. setTimeout(function(){
  19910. module.update.text(previousText);
  19911. callback.call(element);
  19912. }, duration);
  19913. }
  19914. },
  19915. reset: {
  19916. // on mouseout sets text to previous value
  19917. text: function() {
  19918. var
  19919. activeText = text.active || $module.data(metadata.storedText),
  19920. inactiveText = text.inactive || $module.data(metadata.storedText)
  19921. ;
  19922. if( module.is.textEnabled() ) {
  19923. if( module.is.active() && activeText) {
  19924. module.verbose('Resetting active text', activeText);
  19925. module.update.text(activeText);
  19926. }
  19927. else if(inactiveText) {
  19928. module.verbose('Resetting inactive text', activeText);
  19929. module.update.text(inactiveText);
  19930. }
  19931. }
  19932. }
  19933. },
  19934. update: {
  19935. text: function(text) {
  19936. var
  19937. currentText = module.get.text()
  19938. ;
  19939. if(text && text !== currentText) {
  19940. module.debug('Updating text', text);
  19941. if(settings.selector.text) {
  19942. $module
  19943. .data(metadata.storedText, text)
  19944. .find(settings.selector.text)
  19945. .text(text)
  19946. ;
  19947. }
  19948. else {
  19949. $module
  19950. .data(metadata.storedText, text)
  19951. .html(text)
  19952. ;
  19953. }
  19954. }
  19955. else {
  19956. module.debug('Text is already set, ignoring update', text);
  19957. }
  19958. }
  19959. },
  19960. setting: function(name, value) {
  19961. module.debug('Changing setting', name, value);
  19962. if( $.isPlainObject(name) ) {
  19963. $.extend(true, settings, name);
  19964. }
  19965. else if(value !== undefined) {
  19966. if($.isPlainObject(settings[name])) {
  19967. $.extend(true, settings[name], value);
  19968. }
  19969. else {
  19970. settings[name] = value;
  19971. }
  19972. }
  19973. else {
  19974. return settings[name];
  19975. }
  19976. },
  19977. internal: function(name, value) {
  19978. if( $.isPlainObject(name) ) {
  19979. $.extend(true, module, name);
  19980. }
  19981. else if(value !== undefined) {
  19982. module[name] = value;
  19983. }
  19984. else {
  19985. return module[name];
  19986. }
  19987. },
  19988. debug: function() {
  19989. if(!settings.silent && settings.debug) {
  19990. if(settings.performance) {
  19991. module.performance.log(arguments);
  19992. }
  19993. else {
  19994. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19995. module.debug.apply(console, arguments);
  19996. }
  19997. }
  19998. },
  19999. verbose: function() {
  20000. if(!settings.silent && settings.verbose && settings.debug) {
  20001. if(settings.performance) {
  20002. module.performance.log(arguments);
  20003. }
  20004. else {
  20005. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20006. module.verbose.apply(console, arguments);
  20007. }
  20008. }
  20009. },
  20010. error: function() {
  20011. if(!settings.silent) {
  20012. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  20013. module.error.apply(console, arguments);
  20014. }
  20015. },
  20016. performance: {
  20017. log: function(message) {
  20018. var
  20019. currentTime,
  20020. executionTime,
  20021. previousTime
  20022. ;
  20023. if(settings.performance) {
  20024. currentTime = new Date().getTime();
  20025. previousTime = time || currentTime;
  20026. executionTime = currentTime - previousTime;
  20027. time = currentTime;
  20028. performance.push({
  20029. 'Name' : message[0],
  20030. 'Arguments' : [].slice.call(message, 1) || '',
  20031. 'Element' : element,
  20032. 'Execution Time' : executionTime
  20033. });
  20034. }
  20035. clearTimeout(module.performance.timer);
  20036. module.performance.timer = setTimeout(module.performance.display, 500);
  20037. },
  20038. display: function() {
  20039. var
  20040. title = settings.name + ':',
  20041. totalTime = 0
  20042. ;
  20043. time = false;
  20044. clearTimeout(module.performance.timer);
  20045. $.each(performance, function(index, data) {
  20046. totalTime += data['Execution Time'];
  20047. });
  20048. title += ' ' + totalTime + 'ms';
  20049. if(moduleSelector) {
  20050. title += ' \'' + moduleSelector + '\'';
  20051. }
  20052. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  20053. console.groupCollapsed(title);
  20054. if(console.table) {
  20055. console.table(performance);
  20056. }
  20057. else {
  20058. $.each(performance, function(index, data) {
  20059. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  20060. });
  20061. }
  20062. console.groupEnd();
  20063. }
  20064. performance = [];
  20065. }
  20066. },
  20067. invoke: function(query, passedArguments, context) {
  20068. var
  20069. object = instance,
  20070. maxDepth,
  20071. found,
  20072. response
  20073. ;
  20074. passedArguments = passedArguments || queryArguments;
  20075. context = element || context;
  20076. if(typeof query == 'string' && object !== undefined) {
  20077. query = query.split(/[\. ]/);
  20078. maxDepth = query.length - 1;
  20079. $.each(query, function(depth, value) {
  20080. var camelCaseValue = (depth != maxDepth)
  20081. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  20082. : query
  20083. ;
  20084. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  20085. object = object[camelCaseValue];
  20086. }
  20087. else if( object[camelCaseValue] !== undefined ) {
  20088. found = object[camelCaseValue];
  20089. return false;
  20090. }
  20091. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  20092. object = object[value];
  20093. }
  20094. else if( object[value] !== undefined ) {
  20095. found = object[value];
  20096. return false;
  20097. }
  20098. else {
  20099. module.error(error.method, query);
  20100. return false;
  20101. }
  20102. });
  20103. }
  20104. if ( $.isFunction( found ) ) {
  20105. response = found.apply(context, passedArguments);
  20106. }
  20107. else if(found !== undefined) {
  20108. response = found;
  20109. }
  20110. if($.isArray(returnedValue)) {
  20111. returnedValue.push(response);
  20112. }
  20113. else if(returnedValue !== undefined) {
  20114. returnedValue = [returnedValue, response];
  20115. }
  20116. else if(response !== undefined) {
  20117. returnedValue = response;
  20118. }
  20119. return found;
  20120. }
  20121. };
  20122. if(methodInvoked) {
  20123. if(instance === undefined) {
  20124. module.initialize();
  20125. }
  20126. module.invoke(query);
  20127. }
  20128. else {
  20129. if(instance !== undefined) {
  20130. instance.invoke('destroy');
  20131. }
  20132. module.initialize();
  20133. }
  20134. })
  20135. ;
  20136. return (returnedValue !== undefined)
  20137. ? returnedValue
  20138. : this
  20139. ;
  20140. };
  20141. $.fn.state.settings = {
  20142. // module info
  20143. name : 'State',
  20144. // debug output
  20145. debug : false,
  20146. // verbose debug output
  20147. verbose : false,
  20148. // namespace for events
  20149. namespace : 'state',
  20150. // debug data includes performance
  20151. performance : true,
  20152. // callback occurs on state change
  20153. onActivate : function() {},
  20154. onDeactivate : function() {},
  20155. onChange : function() {},
  20156. // state test functions
  20157. activateTest : function() { return true; },
  20158. deactivateTest : function() { return true; },
  20159. // whether to automatically map default states
  20160. automatic : true,
  20161. // activate / deactivate changes all elements instantiated at same time
  20162. sync : false,
  20163. // default flash text duration, used for temporarily changing text of an element
  20164. flashDuration : 1000,
  20165. // selector filter
  20166. filter : {
  20167. text : '.loading, .disabled',
  20168. active : '.disabled'
  20169. },
  20170. context : false,
  20171. // error
  20172. error: {
  20173. beforeSend : 'The before send function has cancelled state change',
  20174. method : 'The method you called is not defined.'
  20175. },
  20176. // metadata
  20177. metadata: {
  20178. promise : 'promise',
  20179. storedText : 'stored-text'
  20180. },
  20181. // change class on state
  20182. className: {
  20183. active : 'active',
  20184. disabled : 'disabled',
  20185. error : 'error',
  20186. loading : 'loading',
  20187. success : 'success',
  20188. warning : 'warning'
  20189. },
  20190. selector: {
  20191. // selector for text node
  20192. text: false
  20193. },
  20194. defaults : {
  20195. input: {
  20196. disabled : true,
  20197. loading : true,
  20198. active : true
  20199. },
  20200. button: {
  20201. disabled : true,
  20202. loading : true,
  20203. active : true,
  20204. },
  20205. progress: {
  20206. active : true,
  20207. success : true,
  20208. warning : true,
  20209. error : true
  20210. }
  20211. },
  20212. states : {
  20213. active : true,
  20214. disabled : true,
  20215. error : true,
  20216. loading : true,
  20217. success : true,
  20218. warning : true
  20219. },
  20220. text : {
  20221. disabled : false,
  20222. flash : false,
  20223. hover : false,
  20224. active : false,
  20225. inactive : false,
  20226. activate : false,
  20227. deactivate : false
  20228. }
  20229. };
  20230. })( jQuery, window, document );
  20231. /*!
  20232. * # Semantic UI 2.3.0 - Visibility
  20233. * http://github.com/semantic-org/semantic-ui/
  20234. *
  20235. *
  20236. * Released under the MIT license
  20237. * http://opensource.org/licenses/MIT
  20238. *
  20239. */
  20240. ;(function ($, window, document, undefined) {
  20241. "use strict";
  20242. window = (typeof window != 'undefined' && window.Math == Math)
  20243. ? window
  20244. : (typeof self != 'undefined' && self.Math == Math)
  20245. ? self
  20246. : Function('return this')()
  20247. ;
  20248. $.fn.visibility = function(parameters) {
  20249. var
  20250. $allModules = $(this),
  20251. moduleSelector = $allModules.selector || '',
  20252. time = new Date().getTime(),
  20253. performance = [],
  20254. query = arguments[0],
  20255. methodInvoked = (typeof query == 'string'),
  20256. queryArguments = [].slice.call(arguments, 1),
  20257. returnedValue,
  20258. moduleCount = $allModules.length,
  20259. loadedCount = 0
  20260. ;
  20261. $allModules
  20262. .each(function() {
  20263. var
  20264. settings = ( $.isPlainObject(parameters) )
  20265. ? $.extend(true, {}, $.fn.visibility.settings, parameters)
  20266. : $.extend({}, $.fn.visibility.settings),
  20267. className = settings.className,
  20268. namespace = settings.namespace,
  20269. error = settings.error,
  20270. metadata = settings.metadata,
  20271. eventNamespace = '.' + namespace,
  20272. moduleNamespace = 'module-' + namespace,
  20273. $window = $(window),
  20274. $module = $(this),
  20275. $context = $(settings.context),
  20276. $placeholder,
  20277. selector = $module.selector || '',
  20278. instance = $module.data(moduleNamespace),
  20279. requestAnimationFrame = window.requestAnimationFrame
  20280. || window.mozRequestAnimationFrame
  20281. || window.webkitRequestAnimationFrame
  20282. || window.msRequestAnimationFrame
  20283. || function(callback) { setTimeout(callback, 0); },
  20284. element = this,
  20285. disabled = false,
  20286. contextObserver,
  20287. observer,
  20288. module
  20289. ;
  20290. module = {
  20291. initialize: function() {
  20292. module.debug('Initializing', settings);
  20293. module.setup.cache();
  20294. if( module.should.trackChanges() ) {
  20295. if(settings.type == 'image') {
  20296. module.setup.image();
  20297. }
  20298. if(settings.type == 'fixed') {
  20299. module.setup.fixed();
  20300. }
  20301. if(settings.observeChanges) {
  20302. module.observeChanges();
  20303. }
  20304. module.bind.events();
  20305. }
  20306. module.save.position();
  20307. if( !module.is.visible() ) {
  20308. module.error(error.visible, $module);
  20309. }
  20310. if(settings.initialCheck) {
  20311. module.checkVisibility();
  20312. }
  20313. module.instantiate();
  20314. },
  20315. instantiate: function() {
  20316. module.debug('Storing instance', module);
  20317. $module
  20318. .data(moduleNamespace, module)
  20319. ;
  20320. instance = module;
  20321. },
  20322. destroy: function() {
  20323. module.verbose('Destroying previous module');
  20324. if(observer) {
  20325. observer.disconnect();
  20326. }
  20327. if(contextObserver) {
  20328. contextObserver.disconnect();
  20329. }
  20330. $window
  20331. .off('load' + eventNamespace, module.event.load)
  20332. .off('resize' + eventNamespace, module.event.resize)
  20333. ;
  20334. $context
  20335. .off('scroll' + eventNamespace, module.event.scroll)
  20336. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  20337. ;
  20338. if(settings.type == 'fixed') {
  20339. module.resetFixed();
  20340. module.remove.placeholder();
  20341. }
  20342. $module
  20343. .off(eventNamespace)
  20344. .removeData(moduleNamespace)
  20345. ;
  20346. },
  20347. observeChanges: function() {
  20348. if('MutationObserver' in window) {
  20349. contextObserver = new MutationObserver(module.event.contextChanged);
  20350. observer = new MutationObserver(module.event.changed);
  20351. contextObserver.observe(document, {
  20352. childList : true,
  20353. subtree : true
  20354. });
  20355. observer.observe(element, {
  20356. childList : true,
  20357. subtree : true
  20358. });
  20359. module.debug('Setting up mutation observer', observer);
  20360. }
  20361. },
  20362. bind: {
  20363. events: function() {
  20364. module.verbose('Binding visibility events to scroll and resize');
  20365. if(settings.refreshOnLoad) {
  20366. $window
  20367. .on('load' + eventNamespace, module.event.load)
  20368. ;
  20369. }
  20370. $window
  20371. .on('resize' + eventNamespace, module.event.resize)
  20372. ;
  20373. // pub/sub pattern
  20374. $context
  20375. .off('scroll' + eventNamespace)
  20376. .on('scroll' + eventNamespace, module.event.scroll)
  20377. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  20378. ;
  20379. }
  20380. },
  20381. event: {
  20382. changed: function(mutations) {
  20383. module.verbose('DOM tree modified, updating visibility calculations');
  20384. module.timer = setTimeout(function() {
  20385. module.verbose('DOM tree modified, updating sticky menu');
  20386. module.refresh();
  20387. }, 100);
  20388. },
  20389. contextChanged: function(mutations) {
  20390. [].forEach.call(mutations, function(mutation) {
  20391. if(mutation.removedNodes) {
  20392. [].forEach.call(mutation.removedNodes, function(node) {
  20393. if(node == element || $(node).find(element).length > 0) {
  20394. module.debug('Element removed from DOM, tearing down events');
  20395. module.destroy();
  20396. }
  20397. });
  20398. }
  20399. });
  20400. },
  20401. resize: function() {
  20402. module.debug('Window resized');
  20403. if(settings.refreshOnResize) {
  20404. requestAnimationFrame(module.refresh);
  20405. }
  20406. },
  20407. load: function() {
  20408. module.debug('Page finished loading');
  20409. requestAnimationFrame(module.refresh);
  20410. },
  20411. // publishes scrollchange event on one scroll
  20412. scroll: function() {
  20413. if(settings.throttle) {
  20414. clearTimeout(module.timer);
  20415. module.timer = setTimeout(function() {
  20416. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  20417. }, settings.throttle);
  20418. }
  20419. else {
  20420. requestAnimationFrame(function() {
  20421. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  20422. });
  20423. }
  20424. },
  20425. // subscribes to scrollchange
  20426. scrollchange: function(event, scrollPosition) {
  20427. module.checkVisibility(scrollPosition);
  20428. },
  20429. },
  20430. precache: function(images, callback) {
  20431. if (!(images instanceof Array)) {
  20432. images = [images];
  20433. }
  20434. var
  20435. imagesLength = images.length,
  20436. loadedCounter = 0,
  20437. cache = [],
  20438. cacheImage = document.createElement('img'),
  20439. handleLoad = function() {
  20440. loadedCounter++;
  20441. if (loadedCounter >= images.length) {
  20442. if ($.isFunction(callback)) {
  20443. callback();
  20444. }
  20445. }
  20446. }
  20447. ;
  20448. while (imagesLength--) {
  20449. cacheImage = document.createElement('img');
  20450. cacheImage.onload = handleLoad;
  20451. cacheImage.onerror = handleLoad;
  20452. cacheImage.src = images[imagesLength];
  20453. cache.push(cacheImage);
  20454. }
  20455. },
  20456. enableCallbacks: function() {
  20457. module.debug('Allowing callbacks to occur');
  20458. disabled = false;
  20459. },
  20460. disableCallbacks: function() {
  20461. module.debug('Disabling all callbacks temporarily');
  20462. disabled = true;
  20463. },
  20464. should: {
  20465. trackChanges: function() {
  20466. if(methodInvoked) {
  20467. module.debug('One time query, no need to bind events');
  20468. return false;
  20469. }
  20470. module.debug('Callbacks being attached');
  20471. return true;
  20472. }
  20473. },
  20474. setup: {
  20475. cache: function() {
  20476. module.cache = {
  20477. occurred : {},
  20478. screen : {},
  20479. element : {},
  20480. };
  20481. },
  20482. image: function() {
  20483. var
  20484. src = $module.data(metadata.src)
  20485. ;
  20486. if(src) {
  20487. module.verbose('Lazy loading image', src);
  20488. settings.once = true;
  20489. settings.observeChanges = false;
  20490. // show when top visible
  20491. settings.onOnScreen = function() {
  20492. module.debug('Image on screen', element);
  20493. module.precache(src, function() {
  20494. module.set.image(src, function() {
  20495. loadedCount++;
  20496. if(loadedCount == moduleCount) {
  20497. settings.onAllLoaded.call(this);
  20498. }
  20499. settings.onLoad.call(this);
  20500. });
  20501. });
  20502. };
  20503. }
  20504. },
  20505. fixed: function() {
  20506. module.debug('Setting up fixed');
  20507. settings.once = false;
  20508. settings.observeChanges = false;
  20509. settings.initialCheck = true;
  20510. settings.refreshOnLoad = true;
  20511. if(!parameters.transition) {
  20512. settings.transition = false;
  20513. }
  20514. module.create.placeholder();
  20515. module.debug('Added placeholder', $placeholder);
  20516. settings.onTopPassed = function() {
  20517. module.debug('Element passed, adding fixed position', $module);
  20518. module.show.placeholder();
  20519. module.set.fixed();
  20520. if(settings.transition) {
  20521. if($.fn.transition !== undefined) {
  20522. $module.transition(settings.transition, settings.duration);
  20523. }
  20524. }
  20525. };
  20526. settings.onTopPassedReverse = function() {
  20527. module.debug('Element returned to position, removing fixed', $module);
  20528. module.hide.placeholder();
  20529. module.remove.fixed();
  20530. };
  20531. }
  20532. },
  20533. create: {
  20534. placeholder: function() {
  20535. module.verbose('Creating fixed position placeholder');
  20536. $placeholder = $module
  20537. .clone(false)
  20538. .css('display', 'none')
  20539. .addClass(className.placeholder)
  20540. .insertAfter($module)
  20541. ;
  20542. }
  20543. },
  20544. show: {
  20545. placeholder: function() {
  20546. module.verbose('Showing placeholder');
  20547. $placeholder
  20548. .css('display', 'block')
  20549. .css('visibility', 'hidden')
  20550. ;
  20551. }
  20552. },
  20553. hide: {
  20554. placeholder: function() {
  20555. module.verbose('Hiding placeholder');
  20556. $placeholder
  20557. .css('display', 'none')
  20558. .css('visibility', '')
  20559. ;
  20560. }
  20561. },
  20562. set: {
  20563. fixed: function() {
  20564. module.verbose('Setting element to fixed position');
  20565. $module
  20566. .addClass(className.fixed)
  20567. .css({
  20568. position : 'fixed',
  20569. top : settings.offset + 'px',
  20570. left : 'auto',
  20571. zIndex : settings.zIndex
  20572. })
  20573. ;
  20574. settings.onFixed.call(element);
  20575. },
  20576. image: function(src, callback) {
  20577. $module
  20578. .attr('src', src)
  20579. ;
  20580. if(settings.transition) {
  20581. if( $.fn.transition !== undefined) {
  20582. if($module.hasClass(className.visible)) {
  20583. module.debug('Transition already occurred on this image, skipping animation');
  20584. return;
  20585. }
  20586. $module.transition(settings.transition, settings.duration, callback);
  20587. }
  20588. else {
  20589. $module.fadeIn(settings.duration, callback);
  20590. }
  20591. }
  20592. else {
  20593. $module.show();
  20594. }
  20595. }
  20596. },
  20597. is: {
  20598. onScreen: function() {
  20599. var
  20600. calculations = module.get.elementCalculations()
  20601. ;
  20602. return calculations.onScreen;
  20603. },
  20604. offScreen: function() {
  20605. var
  20606. calculations = module.get.elementCalculations()
  20607. ;
  20608. return calculations.offScreen;
  20609. },
  20610. visible: function() {
  20611. if(module.cache && module.cache.element) {
  20612. return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
  20613. }
  20614. return false;
  20615. },
  20616. verticallyScrollableContext: function() {
  20617. var
  20618. overflowY = ($context.get(0) !== window)
  20619. ? $context.css('overflow-y')
  20620. : false
  20621. ;
  20622. return (overflowY == 'auto' || overflowY == 'scroll');
  20623. },
  20624. horizontallyScrollableContext: function() {
  20625. var
  20626. overflowX = ($context.get(0) !== window)
  20627. ? $context.css('overflow-x')
  20628. : false
  20629. ;
  20630. return (overflowX == 'auto' || overflowX == 'scroll');
  20631. }
  20632. },
  20633. refresh: function() {
  20634. module.debug('Refreshing constants (width/height)');
  20635. if(settings.type == 'fixed') {
  20636. module.resetFixed();
  20637. }
  20638. module.reset();
  20639. module.save.position();
  20640. if(settings.checkOnRefresh) {
  20641. module.checkVisibility();
  20642. }
  20643. settings.onRefresh.call(element);
  20644. },
  20645. resetFixed: function () {
  20646. module.remove.fixed();
  20647. module.remove.occurred();
  20648. },
  20649. reset: function() {
  20650. module.verbose('Resetting all cached values');
  20651. if( $.isPlainObject(module.cache) ) {
  20652. module.cache.screen = {};
  20653. module.cache.element = {};
  20654. }
  20655. },
  20656. checkVisibility: function(scroll) {
  20657. module.verbose('Checking visibility of element', module.cache.element);
  20658. if( !disabled && module.is.visible() ) {
  20659. // save scroll position
  20660. module.save.scroll(scroll);
  20661. // update calculations derived from scroll
  20662. module.save.calculations();
  20663. // percentage
  20664. module.passed();
  20665. // reverse (must be first)
  20666. module.passingReverse();
  20667. module.topVisibleReverse();
  20668. module.bottomVisibleReverse();
  20669. module.topPassedReverse();
  20670. module.bottomPassedReverse();
  20671. // one time
  20672. module.onScreen();
  20673. module.offScreen();
  20674. module.passing();
  20675. module.topVisible();
  20676. module.bottomVisible();
  20677. module.topPassed();
  20678. module.bottomPassed();
  20679. // on update callback
  20680. if(settings.onUpdate) {
  20681. settings.onUpdate.call(element, module.get.elementCalculations());
  20682. }
  20683. }
  20684. },
  20685. passed: function(amount, newCallback) {
  20686. var
  20687. calculations = module.get.elementCalculations(),
  20688. amountInPixels
  20689. ;
  20690. // assign callback
  20691. if(amount && newCallback) {
  20692. settings.onPassed[amount] = newCallback;
  20693. }
  20694. else if(amount !== undefined) {
  20695. return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
  20696. }
  20697. else if(calculations.passing) {
  20698. $.each(settings.onPassed, function(amount, callback) {
  20699. if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
  20700. module.execute(callback, amount);
  20701. }
  20702. else if(!settings.once) {
  20703. module.remove.occurred(callback);
  20704. }
  20705. });
  20706. }
  20707. },
  20708. onScreen: function(newCallback) {
  20709. var
  20710. calculations = module.get.elementCalculations(),
  20711. callback = newCallback || settings.onOnScreen,
  20712. callbackName = 'onScreen'
  20713. ;
  20714. if(newCallback) {
  20715. module.debug('Adding callback for onScreen', newCallback);
  20716. settings.onOnScreen = newCallback;
  20717. }
  20718. if(calculations.onScreen) {
  20719. module.execute(callback, callbackName);
  20720. }
  20721. else if(!settings.once) {
  20722. module.remove.occurred(callbackName);
  20723. }
  20724. if(newCallback !== undefined) {
  20725. return calculations.onOnScreen;
  20726. }
  20727. },
  20728. offScreen: function(newCallback) {
  20729. var
  20730. calculations = module.get.elementCalculations(),
  20731. callback = newCallback || settings.onOffScreen,
  20732. callbackName = 'offScreen'
  20733. ;
  20734. if(newCallback) {
  20735. module.debug('Adding callback for offScreen', newCallback);
  20736. settings.onOffScreen = newCallback;
  20737. }
  20738. if(calculations.offScreen) {
  20739. module.execute(callback, callbackName);
  20740. }
  20741. else if(!settings.once) {
  20742. module.remove.occurred(callbackName);
  20743. }
  20744. if(newCallback !== undefined) {
  20745. return calculations.onOffScreen;
  20746. }
  20747. },
  20748. passing: function(newCallback) {
  20749. var
  20750. calculations = module.get.elementCalculations(),
  20751. callback = newCallback || settings.onPassing,
  20752. callbackName = 'passing'
  20753. ;
  20754. if(newCallback) {
  20755. module.debug('Adding callback for passing', newCallback);
  20756. settings.onPassing = newCallback;
  20757. }
  20758. if(calculations.passing) {
  20759. module.execute(callback, callbackName);
  20760. }
  20761. else if(!settings.once) {
  20762. module.remove.occurred(callbackName);
  20763. }
  20764. if(newCallback !== undefined) {
  20765. return calculations.passing;
  20766. }
  20767. },
  20768. topVisible: function(newCallback) {
  20769. var
  20770. calculations = module.get.elementCalculations(),
  20771. callback = newCallback || settings.onTopVisible,
  20772. callbackName = 'topVisible'
  20773. ;
  20774. if(newCallback) {
  20775. module.debug('Adding callback for top visible', newCallback);
  20776. settings.onTopVisible = newCallback;
  20777. }
  20778. if(calculations.topVisible) {
  20779. module.execute(callback, callbackName);
  20780. }
  20781. else if(!settings.once) {
  20782. module.remove.occurred(callbackName);
  20783. }
  20784. if(newCallback === undefined) {
  20785. return calculations.topVisible;
  20786. }
  20787. },
  20788. bottomVisible: function(newCallback) {
  20789. var
  20790. calculations = module.get.elementCalculations(),
  20791. callback = newCallback || settings.onBottomVisible,
  20792. callbackName = 'bottomVisible'
  20793. ;
  20794. if(newCallback) {
  20795. module.debug('Adding callback for bottom visible', newCallback);
  20796. settings.onBottomVisible = newCallback;
  20797. }
  20798. if(calculations.bottomVisible) {
  20799. module.execute(callback, callbackName);
  20800. }
  20801. else if(!settings.once) {
  20802. module.remove.occurred(callbackName);
  20803. }
  20804. if(newCallback === undefined) {
  20805. return calculations.bottomVisible;
  20806. }
  20807. },
  20808. topPassed: function(newCallback) {
  20809. var
  20810. calculations = module.get.elementCalculations(),
  20811. callback = newCallback || settings.onTopPassed,
  20812. callbackName = 'topPassed'
  20813. ;
  20814. if(newCallback) {
  20815. module.debug('Adding callback for top passed', newCallback);
  20816. settings.onTopPassed = newCallback;
  20817. }
  20818. if(calculations.topPassed) {
  20819. module.execute(callback, callbackName);
  20820. }
  20821. else if(!settings.once) {
  20822. module.remove.occurred(callbackName);
  20823. }
  20824. if(newCallback === undefined) {
  20825. return calculations.topPassed;
  20826. }
  20827. },
  20828. bottomPassed: function(newCallback) {
  20829. var
  20830. calculations = module.get.elementCalculations(),
  20831. callback = newCallback || settings.onBottomPassed,
  20832. callbackName = 'bottomPassed'
  20833. ;
  20834. if(newCallback) {
  20835. module.debug('Adding callback for bottom passed', newCallback);
  20836. settings.onBottomPassed = newCallback;
  20837. }
  20838. if(calculations.bottomPassed) {
  20839. module.execute(callback, callbackName);
  20840. }
  20841. else if(!settings.once) {
  20842. module.remove.occurred(callbackName);
  20843. }
  20844. if(newCallback === undefined) {
  20845. return calculations.bottomPassed;
  20846. }
  20847. },
  20848. passingReverse: function(newCallback) {
  20849. var
  20850. calculations = module.get.elementCalculations(),
  20851. callback = newCallback || settings.onPassingReverse,
  20852. callbackName = 'passingReverse'
  20853. ;
  20854. if(newCallback) {
  20855. module.debug('Adding callback for passing reverse', newCallback);
  20856. settings.onPassingReverse = newCallback;
  20857. }
  20858. if(!calculations.passing) {
  20859. if(module.get.occurred('passing')) {
  20860. module.execute(callback, callbackName);
  20861. }
  20862. }
  20863. else if(!settings.once) {
  20864. module.remove.occurred(callbackName);
  20865. }
  20866. if(newCallback !== undefined) {
  20867. return !calculations.passing;
  20868. }
  20869. },
  20870. topVisibleReverse: function(newCallback) {
  20871. var
  20872. calculations = module.get.elementCalculations(),
  20873. callback = newCallback || settings.onTopVisibleReverse,
  20874. callbackName = 'topVisibleReverse'
  20875. ;
  20876. if(newCallback) {
  20877. module.debug('Adding callback for top visible reverse', newCallback);
  20878. settings.onTopVisibleReverse = newCallback;
  20879. }
  20880. if(!calculations.topVisible) {
  20881. if(module.get.occurred('topVisible')) {
  20882. module.execute(callback, callbackName);
  20883. }
  20884. }
  20885. else if(!settings.once) {
  20886. module.remove.occurred(callbackName);
  20887. }
  20888. if(newCallback === undefined) {
  20889. return !calculations.topVisible;
  20890. }
  20891. },
  20892. bottomVisibleReverse: function(newCallback) {
  20893. var
  20894. calculations = module.get.elementCalculations(),
  20895. callback = newCallback || settings.onBottomVisibleReverse,
  20896. callbackName = 'bottomVisibleReverse'
  20897. ;
  20898. if(newCallback) {
  20899. module.debug('Adding callback for bottom visible reverse', newCallback);
  20900. settings.onBottomVisibleReverse = newCallback;
  20901. }
  20902. if(!calculations.bottomVisible) {
  20903. if(module.get.occurred('bottomVisible')) {
  20904. module.execute(callback, callbackName);
  20905. }
  20906. }
  20907. else if(!settings.once) {
  20908. module.remove.occurred(callbackName);
  20909. }
  20910. if(newCallback === undefined) {
  20911. return !calculations.bottomVisible;
  20912. }
  20913. },
  20914. topPassedReverse: function(newCallback) {
  20915. var
  20916. calculations = module.get.elementCalculations(),
  20917. callback = newCallback || settings.onTopPassedReverse,
  20918. callbackName = 'topPassedReverse'
  20919. ;
  20920. if(newCallback) {
  20921. module.debug('Adding callback for top passed reverse', newCallback);
  20922. settings.onTopPassedReverse = newCallback;
  20923. }
  20924. if(!calculations.topPassed) {
  20925. if(module.get.occurred('topPassed')) {
  20926. module.execute(callback, callbackName);
  20927. }
  20928. }
  20929. else if(!settings.once) {
  20930. module.remove.occurred(callbackName);
  20931. }
  20932. if(newCallback === undefined) {
  20933. return !calculations.onTopPassed;
  20934. }
  20935. },
  20936. bottomPassedReverse: function(newCallback) {
  20937. var
  20938. calculations = module.get.elementCalculations(),
  20939. callback = newCallback || settings.onBottomPassedReverse,
  20940. callbackName = 'bottomPassedReverse'
  20941. ;
  20942. if(newCallback) {
  20943. module.debug('Adding callback for bottom passed reverse', newCallback);
  20944. settings.onBottomPassedReverse = newCallback;
  20945. }
  20946. if(!calculations.bottomPassed) {
  20947. if(module.get.occurred('bottomPassed')) {
  20948. module.execute(callback, callbackName);
  20949. }
  20950. }
  20951. else if(!settings.once) {
  20952. module.remove.occurred(callbackName);
  20953. }
  20954. if(newCallback === undefined) {
  20955. return !calculations.bottomPassed;
  20956. }
  20957. },
  20958. execute: function(callback, callbackName) {
  20959. var
  20960. calculations = module.get.elementCalculations(),
  20961. screen = module.get.screenCalculations()
  20962. ;
  20963. callback = callback || false;
  20964. if(callback) {
  20965. if(settings.continuous) {
  20966. module.debug('Callback being called continuously', callbackName, calculations);
  20967. callback.call(element, calculations, screen);
  20968. }
  20969. else if(!module.get.occurred(callbackName)) {
  20970. module.debug('Conditions met', callbackName, calculations);
  20971. callback.call(element, calculations, screen);
  20972. }
  20973. }
  20974. module.save.occurred(callbackName);
  20975. },
  20976. remove: {
  20977. fixed: function() {
  20978. module.debug('Removing fixed position');
  20979. $module
  20980. .removeClass(className.fixed)
  20981. .css({
  20982. position : '',
  20983. top : '',
  20984. left : '',
  20985. zIndex : ''
  20986. })
  20987. ;
  20988. settings.onUnfixed.call(element);
  20989. },
  20990. placeholder: function() {
  20991. module.debug('Removing placeholder content');
  20992. if($placeholder) {
  20993. $placeholder.remove();
  20994. }
  20995. },
  20996. occurred: function(callback) {
  20997. if(callback) {
  20998. var
  20999. occurred = module.cache.occurred
  21000. ;
  21001. if(occurred[callback] !== undefined && occurred[callback] === true) {
  21002. module.debug('Callback can now be called again', callback);
  21003. module.cache.occurred[callback] = false;
  21004. }
  21005. }
  21006. else {
  21007. module.cache.occurred = {};
  21008. }
  21009. }
  21010. },
  21011. save: {
  21012. calculations: function() {
  21013. module.verbose('Saving all calculations necessary to determine positioning');
  21014. module.save.direction();
  21015. module.save.screenCalculations();
  21016. module.save.elementCalculations();
  21017. },
  21018. occurred: function(callback) {
  21019. if(callback) {
  21020. if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
  21021. module.verbose('Saving callback occurred', callback);
  21022. module.cache.occurred[callback] = true;
  21023. }
  21024. }
  21025. },
  21026. scroll: function(scrollPosition) {
  21027. scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
  21028. module.cache.scroll = scrollPosition;
  21029. },
  21030. direction: function() {
  21031. var
  21032. scroll = module.get.scroll(),
  21033. lastScroll = module.get.lastScroll(),
  21034. direction
  21035. ;
  21036. if(scroll > lastScroll && lastScroll) {
  21037. direction = 'down';
  21038. }
  21039. else if(scroll < lastScroll && lastScroll) {
  21040. direction = 'up';
  21041. }
  21042. else {
  21043. direction = 'static';
  21044. }
  21045. module.cache.direction = direction;
  21046. return module.cache.direction;
  21047. },
  21048. elementPosition: function() {
  21049. var
  21050. element = module.cache.element,
  21051. screen = module.get.screenSize()
  21052. ;
  21053. module.verbose('Saving element position');
  21054. // (quicker than $.extend)
  21055. element.fits = (element.height < screen.height);
  21056. element.offset = $module.offset();
  21057. element.width = $module.outerWidth();
  21058. element.height = $module.outerHeight();
  21059. // compensate for scroll in context
  21060. if(module.is.verticallyScrollableContext()) {
  21061. element.offset.top += $context.scrollTop() - $context.offset().top;
  21062. }
  21063. if(module.is.horizontallyScrollableContext()) {
  21064. element.offset.left += $context.scrollLeft - $context.offset().left;
  21065. }
  21066. // store
  21067. module.cache.element = element;
  21068. return element;
  21069. },
  21070. elementCalculations: function() {
  21071. var
  21072. screen = module.get.screenCalculations(),
  21073. element = module.get.elementPosition()
  21074. ;
  21075. // offset
  21076. if(settings.includeMargin) {
  21077. element.margin = {};
  21078. element.margin.top = parseInt($module.css('margin-top'), 10);
  21079. element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
  21080. element.top = element.offset.top - element.margin.top;
  21081. element.bottom = element.offset.top + element.height + element.margin.bottom;
  21082. }
  21083. else {
  21084. element.top = element.offset.top;
  21085. element.bottom = element.offset.top + element.height;
  21086. }
  21087. // visibility
  21088. element.topPassed = (screen.top >= element.top);
  21089. element.bottomPassed = (screen.top >= element.bottom);
  21090. element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
  21091. element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
  21092. element.pixelsPassed = 0;
  21093. element.percentagePassed = 0;
  21094. // meta calculations
  21095. element.onScreen = (element.topVisible && !element.bottomPassed);
  21096. element.passing = (element.topPassed && !element.bottomPassed);
  21097. element.offScreen = (!element.onScreen);
  21098. // passing calculations
  21099. if(element.passing) {
  21100. element.pixelsPassed = (screen.top - element.top);
  21101. element.percentagePassed = (screen.top - element.top) / element.height;
  21102. }
  21103. module.cache.element = element;
  21104. module.verbose('Updated element calculations', element);
  21105. return element;
  21106. },
  21107. screenCalculations: function() {
  21108. var
  21109. scroll = module.get.scroll()
  21110. ;
  21111. module.save.direction();
  21112. module.cache.screen.top = scroll;
  21113. module.cache.screen.bottom = scroll + module.cache.screen.height;
  21114. return module.cache.screen;
  21115. },
  21116. screenSize: function() {
  21117. module.verbose('Saving window position');
  21118. module.cache.screen = {
  21119. height: $context.height()
  21120. };
  21121. },
  21122. position: function() {
  21123. module.save.screenSize();
  21124. module.save.elementPosition();
  21125. }
  21126. },
  21127. get: {
  21128. pixelsPassed: function(amount) {
  21129. var
  21130. element = module.get.elementCalculations()
  21131. ;
  21132. if(amount.search('%') > -1) {
  21133. return ( element.height * (parseInt(amount, 10) / 100) );
  21134. }
  21135. return parseInt(amount, 10);
  21136. },
  21137. occurred: function(callback) {
  21138. return (module.cache.occurred !== undefined)
  21139. ? module.cache.occurred[callback] || false
  21140. : false
  21141. ;
  21142. },
  21143. direction: function() {
  21144. if(module.cache.direction === undefined) {
  21145. module.save.direction();
  21146. }
  21147. return module.cache.direction;
  21148. },
  21149. elementPosition: function() {
  21150. if(module.cache.element === undefined) {
  21151. module.save.elementPosition();
  21152. }
  21153. return module.cache.element;
  21154. },
  21155. elementCalculations: function() {
  21156. if(module.cache.element === undefined) {
  21157. module.save.elementCalculations();
  21158. }
  21159. return module.cache.element;
  21160. },
  21161. screenCalculations: function() {
  21162. if(module.cache.screen === undefined) {
  21163. module.save.screenCalculations();
  21164. }
  21165. return module.cache.screen;
  21166. },
  21167. screenSize: function() {
  21168. if(module.cache.screen === undefined) {
  21169. module.save.screenSize();
  21170. }
  21171. return module.cache.screen;
  21172. },
  21173. scroll: function() {
  21174. if(module.cache.scroll === undefined) {
  21175. module.save.scroll();
  21176. }
  21177. return module.cache.scroll;
  21178. },
  21179. lastScroll: function() {
  21180. if(module.cache.screen === undefined) {
  21181. module.debug('First scroll event, no last scroll could be found');
  21182. return false;
  21183. }
  21184. return module.cache.screen.top;
  21185. }
  21186. },
  21187. setting: function(name, value) {
  21188. if( $.isPlainObject(name) ) {
  21189. $.extend(true, settings, name);
  21190. }
  21191. else if(value !== undefined) {
  21192. settings[name] = value;
  21193. }
  21194. else {
  21195. return settings[name];
  21196. }
  21197. },
  21198. internal: function(name, value) {
  21199. if( $.isPlainObject(name) ) {
  21200. $.extend(true, module, name);
  21201. }
  21202. else if(value !== undefined) {
  21203. module[name] = value;
  21204. }
  21205. else {
  21206. return module[name];
  21207. }
  21208. },
  21209. debug: function() {
  21210. if(!settings.silent && settings.debug) {
  21211. if(settings.performance) {
  21212. module.performance.log(arguments);
  21213. }
  21214. else {
  21215. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21216. module.debug.apply(console, arguments);
  21217. }
  21218. }
  21219. },
  21220. verbose: function() {
  21221. if(!settings.silent && settings.verbose && settings.debug) {
  21222. if(settings.performance) {
  21223. module.performance.log(arguments);
  21224. }
  21225. else {
  21226. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21227. module.verbose.apply(console, arguments);
  21228. }
  21229. }
  21230. },
  21231. error: function() {
  21232. if(!settings.silent) {
  21233. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  21234. module.error.apply(console, arguments);
  21235. }
  21236. },
  21237. performance: {
  21238. log: function(message) {
  21239. var
  21240. currentTime,
  21241. executionTime,
  21242. previousTime
  21243. ;
  21244. if(settings.performance) {
  21245. currentTime = new Date().getTime();
  21246. previousTime = time || currentTime;
  21247. executionTime = currentTime - previousTime;
  21248. time = currentTime;
  21249. performance.push({
  21250. 'Name' : message[0],
  21251. 'Arguments' : [].slice.call(message, 1) || '',
  21252. 'Element' : element,
  21253. 'Execution Time' : executionTime
  21254. });
  21255. }
  21256. clearTimeout(module.performance.timer);
  21257. module.performance.timer = setTimeout(module.performance.display, 500);
  21258. },
  21259. display: function() {
  21260. var
  21261. title = settings.name + ':',
  21262. totalTime = 0
  21263. ;
  21264. time = false;
  21265. clearTimeout(module.performance.timer);
  21266. $.each(performance, function(index, data) {
  21267. totalTime += data['Execution Time'];
  21268. });
  21269. title += ' ' + totalTime + 'ms';
  21270. if(moduleSelector) {
  21271. title += ' \'' + moduleSelector + '\'';
  21272. }
  21273. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  21274. console.groupCollapsed(title);
  21275. if(console.table) {
  21276. console.table(performance);
  21277. }
  21278. else {
  21279. $.each(performance, function(index, data) {
  21280. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  21281. });
  21282. }
  21283. console.groupEnd();
  21284. }
  21285. performance = [];
  21286. }
  21287. },
  21288. invoke: function(query, passedArguments, context) {
  21289. var
  21290. object = instance,
  21291. maxDepth,
  21292. found,
  21293. response
  21294. ;
  21295. passedArguments = passedArguments || queryArguments;
  21296. context = element || context;
  21297. if(typeof query == 'string' && object !== undefined) {
  21298. query = query.split(/[\. ]/);
  21299. maxDepth = query.length - 1;
  21300. $.each(query, function(depth, value) {
  21301. var camelCaseValue = (depth != maxDepth)
  21302. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  21303. : query
  21304. ;
  21305. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  21306. object = object[camelCaseValue];
  21307. }
  21308. else if( object[camelCaseValue] !== undefined ) {
  21309. found = object[camelCaseValue];
  21310. return false;
  21311. }
  21312. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  21313. object = object[value];
  21314. }
  21315. else if( object[value] !== undefined ) {
  21316. found = object[value];
  21317. return false;
  21318. }
  21319. else {
  21320. module.error(error.method, query);
  21321. return false;
  21322. }
  21323. });
  21324. }
  21325. if ( $.isFunction( found ) ) {
  21326. response = found.apply(context, passedArguments);
  21327. }
  21328. else if(found !== undefined) {
  21329. response = found;
  21330. }
  21331. if($.isArray(returnedValue)) {
  21332. returnedValue.push(response);
  21333. }
  21334. else if(returnedValue !== undefined) {
  21335. returnedValue = [returnedValue, response];
  21336. }
  21337. else if(response !== undefined) {
  21338. returnedValue = response;
  21339. }
  21340. return found;
  21341. }
  21342. };
  21343. if(methodInvoked) {
  21344. if(instance === undefined) {
  21345. module.initialize();
  21346. }
  21347. instance.save.scroll();
  21348. instance.save.calculations();
  21349. module.invoke(query);
  21350. }
  21351. else {
  21352. if(instance !== undefined) {
  21353. instance.invoke('destroy');
  21354. }
  21355. module.initialize();
  21356. }
  21357. })
  21358. ;
  21359. return (returnedValue !== undefined)
  21360. ? returnedValue
  21361. : this
  21362. ;
  21363. };
  21364. $.fn.visibility.settings = {
  21365. name : 'Visibility',
  21366. namespace : 'visibility',
  21367. debug : false,
  21368. verbose : false,
  21369. performance : true,
  21370. // whether to use mutation observers to follow changes
  21371. observeChanges : true,
  21372. // check position immediately on init
  21373. initialCheck : true,
  21374. // whether to refresh calculations after all page images load
  21375. refreshOnLoad : true,
  21376. // whether to refresh calculations after page resize event
  21377. refreshOnResize : true,
  21378. // should call callbacks on refresh event (resize, etc)
  21379. checkOnRefresh : true,
  21380. // callback should only occur one time
  21381. once : true,
  21382. // callback should fire continuously whe evaluates to true
  21383. continuous : false,
  21384. // offset to use with scroll top
  21385. offset : 0,
  21386. // whether to include margin in elements position
  21387. includeMargin : false,
  21388. // scroll context for visibility checks
  21389. context : window,
  21390. // visibility check delay in ms (defaults to animationFrame)
  21391. throttle : false,
  21392. // special visibility type (image, fixed)
  21393. type : false,
  21394. // z-index to use with visibility 'fixed'
  21395. zIndex : '10',
  21396. // image only animation settings
  21397. transition : 'fade in',
  21398. duration : 1000,
  21399. // array of callbacks for percentage
  21400. onPassed : {},
  21401. // standard callbacks
  21402. onOnScreen : false,
  21403. onOffScreen : false,
  21404. onPassing : false,
  21405. onTopVisible : false,
  21406. onBottomVisible : false,
  21407. onTopPassed : false,
  21408. onBottomPassed : false,
  21409. // reverse callbacks
  21410. onPassingReverse : false,
  21411. onTopVisibleReverse : false,
  21412. onBottomVisibleReverse : false,
  21413. onTopPassedReverse : false,
  21414. onBottomPassedReverse : false,
  21415. // special callbacks for image
  21416. onLoad : function() {},
  21417. onAllLoaded : function() {},
  21418. // special callbacks for fixed position
  21419. onFixed : function() {},
  21420. onUnfixed : function() {},
  21421. // utility callbacks
  21422. onUpdate : false, // disabled by default for performance
  21423. onRefresh : function(){},
  21424. metadata : {
  21425. src: 'src'
  21426. },
  21427. className: {
  21428. fixed : 'fixed',
  21429. placeholder : 'placeholder',
  21430. visible : 'visible'
  21431. },
  21432. error : {
  21433. method : 'The method you called is not defined.',
  21434. visible : 'Element is hidden, you must call refresh after element becomes visible'
  21435. }
  21436. };
  21437. })( jQuery, window, document );