You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

semantic.js 915KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938
  1. /*
  2. * # Fomantic UI - 2.8.2
  3. * https://github.com/fomantic/Fomantic-UI
  4. * http://fomantic-ui.com/
  5. *
  6. * Copyright 2014 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. /*!
  12. * # Fomantic-UI - Site
  13. * http://github.com/fomantic/Fomantic-UI/
  14. *
  15. *
  16. * Released under the MIT license
  17. * http://opensource.org/licenses/MIT
  18. *
  19. */
  20. ;(function ($, window, document, undefined) {
  21. $.isFunction = $.isFunction || function(obj) {
  22. return typeof obj === "function" && typeof obj.nodeType !== "number";
  23. };
  24. $.site = $.fn.site = function(parameters) {
  25. var
  26. time = new Date().getTime(),
  27. performance = [],
  28. query = arguments[0],
  29. methodInvoked = (typeof query == 'string'),
  30. queryArguments = [].slice.call(arguments, 1),
  31. settings = ( $.isPlainObject(parameters) )
  32. ? $.extend(true, {}, $.site.settings, parameters)
  33. : $.extend({}, $.site.settings),
  34. namespace = settings.namespace,
  35. error = settings.error,
  36. moduleNamespace = 'module-' + namespace,
  37. $document = $(document),
  38. $module = $document,
  39. element = this,
  40. instance = $module.data(moduleNamespace),
  41. module,
  42. returnedValue
  43. ;
  44. module = {
  45. initialize: function() {
  46. module.instantiate();
  47. },
  48. instantiate: function() {
  49. module.verbose('Storing instance of site', module);
  50. instance = module;
  51. $module
  52. .data(moduleNamespace, module)
  53. ;
  54. },
  55. normalize: function() {
  56. module.fix.console();
  57. module.fix.requestAnimationFrame();
  58. },
  59. fix: {
  60. console: function() {
  61. module.debug('Normalizing window.console');
  62. if (console === undefined || console.log === undefined) {
  63. module.verbose('Console not available, normalizing events');
  64. module.disable.console();
  65. }
  66. if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
  67. module.verbose('Console group not available, normalizing events');
  68. window.console.group = function() {};
  69. window.console.groupEnd = function() {};
  70. window.console.groupCollapsed = function() {};
  71. }
  72. if (typeof console.markTimeline == 'undefined') {
  73. module.verbose('Mark timeline not available, normalizing events');
  74. window.console.markTimeline = function() {};
  75. }
  76. },
  77. consoleClear: function() {
  78. module.debug('Disabling programmatic console clearing');
  79. window.console.clear = function() {};
  80. },
  81. requestAnimationFrame: function() {
  82. module.debug('Normalizing requestAnimationFrame');
  83. if(window.requestAnimationFrame === undefined) {
  84. module.debug('RequestAnimationFrame not available, normalizing event');
  85. window.requestAnimationFrame = window.requestAnimationFrame
  86. || window.mozRequestAnimationFrame
  87. || window.webkitRequestAnimationFrame
  88. || window.msRequestAnimationFrame
  89. || function(callback) { setTimeout(callback, 0); }
  90. ;
  91. }
  92. }
  93. },
  94. moduleExists: function(name) {
  95. return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
  96. },
  97. enabled: {
  98. modules: function(modules) {
  99. var
  100. enabledModules = []
  101. ;
  102. modules = modules || settings.modules;
  103. $.each(modules, function(index, name) {
  104. if(module.moduleExists(name)) {
  105. enabledModules.push(name);
  106. }
  107. });
  108. return enabledModules;
  109. }
  110. },
  111. disabled: {
  112. modules: function(modules) {
  113. var
  114. disabledModules = []
  115. ;
  116. modules = modules || settings.modules;
  117. $.each(modules, function(index, name) {
  118. if(!module.moduleExists(name)) {
  119. disabledModules.push(name);
  120. }
  121. });
  122. return disabledModules;
  123. }
  124. },
  125. change: {
  126. setting: function(setting, value, modules, modifyExisting) {
  127. modules = (typeof modules === 'string')
  128. ? (modules === 'all')
  129. ? settings.modules
  130. : [modules]
  131. : modules || settings.modules
  132. ;
  133. modifyExisting = (modifyExisting !== undefined)
  134. ? modifyExisting
  135. : true
  136. ;
  137. $.each(modules, function(index, name) {
  138. var
  139. namespace = (module.moduleExists(name))
  140. ? $.fn[name].settings.namespace || false
  141. : true,
  142. $existingModules
  143. ;
  144. if(module.moduleExists(name)) {
  145. module.verbose('Changing default setting', setting, value, name);
  146. $.fn[name].settings[setting] = value;
  147. if(modifyExisting && namespace) {
  148. $existingModules = $(':data(module-' + namespace + ')');
  149. if($existingModules.length > 0) {
  150. module.verbose('Modifying existing settings', $existingModules);
  151. $existingModules[name]('setting', setting, value);
  152. }
  153. }
  154. }
  155. });
  156. },
  157. settings: function(newSettings, modules, modifyExisting) {
  158. modules = (typeof modules === 'string')
  159. ? [modules]
  160. : modules || settings.modules
  161. ;
  162. modifyExisting = (modifyExisting !== undefined)
  163. ? modifyExisting
  164. : true
  165. ;
  166. $.each(modules, function(index, name) {
  167. var
  168. $existingModules
  169. ;
  170. if(module.moduleExists(name)) {
  171. module.verbose('Changing default setting', newSettings, name);
  172. $.extend(true, $.fn[name].settings, newSettings);
  173. if(modifyExisting && namespace) {
  174. $existingModules = $(':data(module-' + namespace + ')');
  175. if($existingModules.length > 0) {
  176. module.verbose('Modifying existing settings', $existingModules);
  177. $existingModules[name]('setting', newSettings);
  178. }
  179. }
  180. }
  181. });
  182. }
  183. },
  184. enable: {
  185. console: function() {
  186. module.console(true);
  187. },
  188. debug: function(modules, modifyExisting) {
  189. modules = modules || settings.modules;
  190. module.debug('Enabling debug for modules', modules);
  191. module.change.setting('debug', true, modules, modifyExisting);
  192. },
  193. verbose: function(modules, modifyExisting) {
  194. modules = modules || settings.modules;
  195. module.debug('Enabling verbose debug for modules', modules);
  196. module.change.setting('verbose', true, modules, modifyExisting);
  197. }
  198. },
  199. disable: {
  200. console: function() {
  201. module.console(false);
  202. },
  203. debug: function(modules, modifyExisting) {
  204. modules = modules || settings.modules;
  205. module.debug('Disabling debug for modules', modules);
  206. module.change.setting('debug', false, modules, modifyExisting);
  207. },
  208. verbose: function(modules, modifyExisting) {
  209. modules = modules || settings.modules;
  210. module.debug('Disabling verbose debug for modules', modules);
  211. module.change.setting('verbose', false, modules, modifyExisting);
  212. }
  213. },
  214. console: function(enable) {
  215. if(enable) {
  216. if(instance.cache.console === undefined) {
  217. module.error(error.console);
  218. return;
  219. }
  220. module.debug('Restoring console function');
  221. window.console = instance.cache.console;
  222. }
  223. else {
  224. module.debug('Disabling console function');
  225. instance.cache.console = window.console;
  226. window.console = {
  227. clear : function(){},
  228. error : function(){},
  229. group : function(){},
  230. groupCollapsed : function(){},
  231. groupEnd : function(){},
  232. info : function(){},
  233. log : function(){},
  234. markTimeline : function(){},
  235. warn : function(){}
  236. };
  237. }
  238. },
  239. destroy: function() {
  240. module.verbose('Destroying previous site for', $module);
  241. $module
  242. .removeData(moduleNamespace)
  243. ;
  244. },
  245. cache: {},
  246. setting: function(name, value) {
  247. if( $.isPlainObject(name) ) {
  248. $.extend(true, settings, name);
  249. }
  250. else if(value !== undefined) {
  251. settings[name] = value;
  252. }
  253. else {
  254. return settings[name];
  255. }
  256. },
  257. internal: function(name, value) {
  258. if( $.isPlainObject(name) ) {
  259. $.extend(true, module, name);
  260. }
  261. else if(value !== undefined) {
  262. module[name] = value;
  263. }
  264. else {
  265. return module[name];
  266. }
  267. },
  268. debug: function() {
  269. if(settings.debug) {
  270. if(settings.performance) {
  271. module.performance.log(arguments);
  272. }
  273. else {
  274. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  275. module.debug.apply(console, arguments);
  276. }
  277. }
  278. },
  279. verbose: function() {
  280. if(settings.verbose && settings.debug) {
  281. if(settings.performance) {
  282. module.performance.log(arguments);
  283. }
  284. else {
  285. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  286. module.verbose.apply(console, arguments);
  287. }
  288. }
  289. },
  290. error: function() {
  291. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  292. module.error.apply(console, arguments);
  293. },
  294. performance: {
  295. log: function(message) {
  296. var
  297. currentTime,
  298. executionTime,
  299. previousTime
  300. ;
  301. if(settings.performance) {
  302. currentTime = new Date().getTime();
  303. previousTime = time || currentTime;
  304. executionTime = currentTime - previousTime;
  305. time = currentTime;
  306. performance.push({
  307. 'Element' : element,
  308. 'Name' : message[0],
  309. 'Arguments' : [].slice.call(message, 1) || '',
  310. 'Execution Time' : executionTime
  311. });
  312. }
  313. clearTimeout(module.performance.timer);
  314. module.performance.timer = setTimeout(module.performance.display, 500);
  315. },
  316. display: function() {
  317. var
  318. title = settings.name + ':',
  319. totalTime = 0
  320. ;
  321. time = false;
  322. clearTimeout(module.performance.timer);
  323. $.each(performance, function(index, data) {
  324. totalTime += data['Execution Time'];
  325. });
  326. title += ' ' + totalTime + 'ms';
  327. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  328. console.groupCollapsed(title);
  329. if(console.table) {
  330. console.table(performance);
  331. }
  332. else {
  333. $.each(performance, function(index, data) {
  334. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  335. });
  336. }
  337. console.groupEnd();
  338. }
  339. performance = [];
  340. }
  341. },
  342. invoke: function(query, passedArguments, context) {
  343. var
  344. object = instance,
  345. maxDepth,
  346. found,
  347. response
  348. ;
  349. passedArguments = passedArguments || queryArguments;
  350. context = element || context;
  351. if(typeof query == 'string' && object !== undefined) {
  352. query = query.split(/[\. ]/);
  353. maxDepth = query.length - 1;
  354. $.each(query, function(depth, value) {
  355. var camelCaseValue = (depth != maxDepth)
  356. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  357. : query
  358. ;
  359. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  360. object = object[camelCaseValue];
  361. }
  362. else if( object[camelCaseValue] !== undefined ) {
  363. found = object[camelCaseValue];
  364. return false;
  365. }
  366. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  367. object = object[value];
  368. }
  369. else if( object[value] !== undefined ) {
  370. found = object[value];
  371. return false;
  372. }
  373. else {
  374. module.error(error.method, query);
  375. return false;
  376. }
  377. });
  378. }
  379. if ( $.isFunction( found ) ) {
  380. response = found.apply(context, passedArguments);
  381. }
  382. else if(found !== undefined) {
  383. response = found;
  384. }
  385. if(Array.isArray(returnedValue)) {
  386. returnedValue.push(response);
  387. }
  388. else if(returnedValue !== undefined) {
  389. returnedValue = [returnedValue, response];
  390. }
  391. else if(response !== undefined) {
  392. returnedValue = response;
  393. }
  394. return found;
  395. }
  396. };
  397. if(methodInvoked) {
  398. if(instance === undefined) {
  399. module.initialize();
  400. }
  401. module.invoke(query);
  402. }
  403. else {
  404. if(instance !== undefined) {
  405. module.destroy();
  406. }
  407. module.initialize();
  408. }
  409. return (returnedValue !== undefined)
  410. ? returnedValue
  411. : this
  412. ;
  413. };
  414. $.site.settings = {
  415. name : 'Site',
  416. namespace : 'site',
  417. error : {
  418. console : 'Console cannot be restored, most likely it was overwritten outside of module',
  419. method : 'The method you called is not defined.'
  420. },
  421. debug : false,
  422. verbose : false,
  423. performance : true,
  424. modules: [
  425. 'accordion',
  426. 'api',
  427. 'calendar',
  428. 'checkbox',
  429. 'dimmer',
  430. 'dropdown',
  431. 'embed',
  432. 'form',
  433. 'modal',
  434. 'nag',
  435. 'popup',
  436. 'slider',
  437. 'rating',
  438. 'shape',
  439. 'sidebar',
  440. 'state',
  441. 'sticky',
  442. 'tab',
  443. 'toast',
  444. 'transition',
  445. 'visibility',
  446. 'visit'
  447. ],
  448. siteNamespace : 'site',
  449. namespaceStub : {
  450. cache : {},
  451. config : {},
  452. sections : {},
  453. section : {},
  454. utilities : {}
  455. }
  456. };
  457. // allows for selection of elements with data attributes
  458. $.extend($.expr[ ":" ], {
  459. data: ($.expr.createPseudo)
  460. ? $.expr.createPseudo(function(dataName) {
  461. return function(elem) {
  462. return !!$.data(elem, dataName);
  463. };
  464. })
  465. : function(elem, i, match) {
  466. // support: jQuery < 1.8
  467. return !!$.data(elem, match[ 3 ]);
  468. }
  469. });
  470. })( jQuery, window, document );
  471. /*!
  472. * # Fomantic-UI - Form Validation
  473. * http://github.com/fomantic/Fomantic-UI/
  474. *
  475. *
  476. * Released under the MIT license
  477. * http://opensource.org/licenses/MIT
  478. *
  479. */
  480. ;(function ($, window, document, undefined) {
  481. 'use strict';
  482. $.isFunction = $.isFunction || function(obj) {
  483. return typeof obj === "function" && typeof obj.nodeType !== "number";
  484. };
  485. window = (typeof window != 'undefined' && window.Math == Math)
  486. ? window
  487. : (typeof self != 'undefined' && self.Math == Math)
  488. ? self
  489. : Function('return this')()
  490. ;
  491. $.fn.form = function(parameters) {
  492. var
  493. $allModules = $(this),
  494. moduleSelector = $allModules.selector || '',
  495. time = new Date().getTime(),
  496. performance = [],
  497. query = arguments[0],
  498. legacyParameters = arguments[1],
  499. methodInvoked = (typeof query == 'string'),
  500. queryArguments = [].slice.call(arguments, 1),
  501. returnedValue
  502. ;
  503. $allModules
  504. .each(function() {
  505. var
  506. $module = $(this),
  507. element = this,
  508. formErrors = [],
  509. keyHeldDown = false,
  510. // set at run-time
  511. $field,
  512. $group,
  513. $message,
  514. $prompt,
  515. $submit,
  516. $clear,
  517. $reset,
  518. settings,
  519. validation,
  520. metadata,
  521. selector,
  522. className,
  523. regExp,
  524. error,
  525. namespace,
  526. moduleNamespace,
  527. eventNamespace,
  528. submitting = false,
  529. dirty = false,
  530. history = ['clean', 'clean'],
  531. instance,
  532. module
  533. ;
  534. module = {
  535. initialize: function() {
  536. // settings grabbed at run time
  537. module.get.settings();
  538. if(methodInvoked) {
  539. if(instance === undefined) {
  540. module.instantiate();
  541. }
  542. module.invoke(query);
  543. }
  544. else {
  545. if(instance !== undefined) {
  546. instance.invoke('destroy');
  547. }
  548. module.verbose('Initializing form validation', $module, settings);
  549. module.bindEvents();
  550. module.set.defaults();
  551. module.instantiate();
  552. }
  553. },
  554. instantiate: function() {
  555. module.verbose('Storing instance of module', module);
  556. instance = module;
  557. $module
  558. .data(moduleNamespace, module)
  559. ;
  560. },
  561. destroy: function() {
  562. module.verbose('Destroying previous module', instance);
  563. module.removeEvents();
  564. $module
  565. .removeData(moduleNamespace)
  566. ;
  567. },
  568. refresh: function() {
  569. module.verbose('Refreshing selector cache');
  570. $field = $module.find(selector.field);
  571. $group = $module.find(selector.group);
  572. $message = $module.find(selector.message);
  573. $prompt = $module.find(selector.prompt);
  574. $submit = $module.find(selector.submit);
  575. $clear = $module.find(selector.clear);
  576. $reset = $module.find(selector.reset);
  577. },
  578. submit: function() {
  579. module.verbose('Submitting form', $module);
  580. submitting = true;
  581. $module.submit();
  582. },
  583. attachEvents: function(selector, action) {
  584. action = action || 'submit';
  585. $(selector).on('click' + eventNamespace, function(event) {
  586. module[action]();
  587. event.preventDefault();
  588. });
  589. },
  590. bindEvents: function() {
  591. module.verbose('Attaching form events');
  592. $module
  593. .on('submit' + eventNamespace, module.validate.form)
  594. .on('blur' + eventNamespace, selector.field, module.event.field.blur)
  595. .on('click' + eventNamespace, selector.submit, module.submit)
  596. .on('click' + eventNamespace, selector.reset, module.reset)
  597. .on('click' + eventNamespace, selector.clear, module.clear)
  598. ;
  599. if(settings.keyboardShortcuts) {
  600. $module.on('keydown' + eventNamespace, selector.field, module.event.field.keydown);
  601. }
  602. $field.each(function(index, el) {
  603. var
  604. $input = $(el),
  605. type = $input.prop('type'),
  606. inputEvent = module.get.changeEvent(type, $input)
  607. ;
  608. $input.on(inputEvent + eventNamespace, module.event.field.change);
  609. });
  610. // Dirty events
  611. if (settings.preventLeaving) {
  612. $(window).on('beforeunload' + eventNamespace, module.event.beforeUnload);
  613. }
  614. $field.on('change click keyup keydown blur', function(e) {
  615. $(this).triggerHandler(e.type + ".dirty");
  616. });
  617. $field.on('change.dirty click.dirty keyup.dirty keydown.dirty blur.dirty', module.determine.isDirty);
  618. $module.on('dirty' + eventNamespace, function(e) {
  619. settings.onDirty.call();
  620. });
  621. $module.on('clean' + eventNamespace, function(e) {
  622. settings.onClean.call();
  623. })
  624. },
  625. clear: function() {
  626. $field.each(function (index, el) {
  627. var
  628. $field = $(el),
  629. $element = $field.parent(),
  630. $fieldGroup = $field.closest($group),
  631. $prompt = $fieldGroup.find(selector.prompt),
  632. $calendar = $field.closest(selector.uiCalendar),
  633. defaultValue = $field.data(metadata.defaultValue) || '',
  634. isCheckbox = $element.is(selector.uiCheckbox),
  635. isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
  636. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  637. isErrored = $fieldGroup.hasClass(className.error)
  638. ;
  639. if(isErrored) {
  640. module.verbose('Resetting error on field', $fieldGroup);
  641. $fieldGroup.removeClass(className.error);
  642. $prompt.remove();
  643. }
  644. if(isDropdown) {
  645. module.verbose('Resetting dropdown value', $element, defaultValue);
  646. $element.dropdown('clear', true);
  647. }
  648. else if(isCheckbox) {
  649. $field.prop('checked', false);
  650. }
  651. else if (isCalendar) {
  652. $calendar.calendar('clear');
  653. }
  654. else {
  655. module.verbose('Resetting field value', $field, defaultValue);
  656. $field.val('');
  657. }
  658. });
  659. },
  660. reset: function() {
  661. $field.each(function (index, el) {
  662. var
  663. $field = $(el),
  664. $element = $field.parent(),
  665. $fieldGroup = $field.closest($group),
  666. $calendar = $field.closest(selector.uiCalendar),
  667. $prompt = $fieldGroup.find(selector.prompt),
  668. defaultValue = $field.data(metadata.defaultValue),
  669. isCheckbox = $element.is(selector.uiCheckbox),
  670. isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
  671. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  672. isErrored = $fieldGroup.hasClass(className.error)
  673. ;
  674. if(defaultValue === undefined) {
  675. return;
  676. }
  677. if(isErrored) {
  678. module.verbose('Resetting error on field', $fieldGroup);
  679. $fieldGroup.removeClass(className.error);
  680. $prompt.remove();
  681. }
  682. if(isDropdown) {
  683. module.verbose('Resetting dropdown value', $element, defaultValue);
  684. $element.dropdown('restore defaults', true);
  685. }
  686. else if(isCheckbox) {
  687. module.verbose('Resetting checkbox value', $element, defaultValue);
  688. $field.prop('checked', defaultValue);
  689. }
  690. else if (isCalendar) {
  691. $calendar.calendar('set date', defaultValue);
  692. }
  693. else {
  694. module.verbose('Resetting field value', $field, defaultValue);
  695. $field.val(defaultValue);
  696. }
  697. });
  698. module.determine.isDirty();
  699. },
  700. determine: {
  701. isValid: function() {
  702. var
  703. allValid = true
  704. ;
  705. $.each(validation, function(fieldName, field) {
  706. if( !( module.validate.field(field, fieldName, true) ) ) {
  707. allValid = false;
  708. }
  709. });
  710. return allValid;
  711. },
  712. isDirty: function(e) {
  713. var formIsDirty = false;
  714. $field.each(function(index, el) {
  715. var
  716. $el = $(el),
  717. isCheckbox = ($el.filter(selector.checkbox).length > 0),
  718. isDirty
  719. ;
  720. if (isCheckbox) {
  721. isDirty = module.is.checkboxDirty($el);
  722. } else {
  723. isDirty = module.is.fieldDirty($el);
  724. }
  725. $el.data(settings.metadata.isDirty, isDirty);
  726. formIsDirty |= isDirty;
  727. });
  728. if (formIsDirty) {
  729. module.set.dirty();
  730. } else {
  731. module.set.clean();
  732. }
  733. if (e && e.namespace === 'dirty') {
  734. e.stopImmediatePropagation();
  735. e.preventDefault();
  736. }
  737. }
  738. },
  739. is: {
  740. bracketedRule: function(rule) {
  741. return (rule.type && rule.type.match(settings.regExp.bracket));
  742. },
  743. shorthandFields: function(fields) {
  744. var
  745. fieldKeys = Object.keys(fields),
  746. firstRule = fields[fieldKeys[0]]
  747. ;
  748. return module.is.shorthandRules(firstRule);
  749. },
  750. // duck type rule test
  751. shorthandRules: function(rules) {
  752. return (typeof rules == 'string' || Array.isArray(rules));
  753. },
  754. empty: function($field) {
  755. if(!$field || $field.length === 0) {
  756. return true;
  757. }
  758. else if($field.is(selector.checkbox)) {
  759. return !$field.is(':checked');
  760. }
  761. else {
  762. return module.is.blank($field);
  763. }
  764. },
  765. blank: function($field) {
  766. return $.trim($field.val()) === '';
  767. },
  768. valid: function(field) {
  769. var
  770. allValid = true
  771. ;
  772. if(field) {
  773. module.verbose('Checking if field is valid', field);
  774. return module.validate.field(validation[field], field, false);
  775. }
  776. else {
  777. module.verbose('Checking if form is valid');
  778. $.each(validation, function(fieldName, field) {
  779. if( !module.is.valid(fieldName) ) {
  780. allValid = false;
  781. }
  782. });
  783. return allValid;
  784. }
  785. },
  786. dirty: function() {
  787. return dirty;
  788. },
  789. clean: function() {
  790. return !dirty;
  791. },
  792. fieldDirty: function($el) {
  793. var initialValue = $el.data(metadata.defaultValue);
  794. // Explicitly check for null/undefined here as value may be `false`, so ($el.data(dataInitialValue) || '') would not work
  795. if (initialValue == null) { initialValue = ''; }
  796. var currentValue = $el.val();
  797. if (currentValue == null) { currentValue = ''; }
  798. // Boolean values can be encoded as "true/false" or "True/False" depending on underlying frameworks so we need a case insensitive comparison
  799. var boolRegex = /^(true|false)$/i;
  800. var isBoolValue = boolRegex.test(initialValue) && boolRegex.test(currentValue);
  801. if (isBoolValue) {
  802. var regex = new RegExp("^" + initialValue + "$", "i");
  803. return !regex.test(currentValue);
  804. }
  805. return currentValue !== initialValue;
  806. },
  807. checkboxDirty: function($el) {
  808. var initialValue = $el.data(metadata.defaultValue);
  809. var currentValue = $el.is(":checked");
  810. return initialValue !== currentValue;
  811. },
  812. justDirty: function() {
  813. return (history[0] === 'dirty');
  814. },
  815. justClean: function() {
  816. return (history[0] === 'clean');
  817. }
  818. },
  819. removeEvents: function() {
  820. $module.off(eventNamespace);
  821. $field.off(eventNamespace);
  822. $submit.off(eventNamespace);
  823. $field.off(eventNamespace);
  824. },
  825. event: {
  826. field: {
  827. keydown: function(event) {
  828. var
  829. $field = $(this),
  830. key = event.which,
  831. isInput = $field.is(selector.input),
  832. isCheckbox = $field.is(selector.checkbox),
  833. isInDropdown = ($field.closest(selector.uiDropdown).length > 0),
  834. keyCode = {
  835. enter : 13,
  836. escape : 27
  837. }
  838. ;
  839. if( key == keyCode.escape) {
  840. module.verbose('Escape key pressed blurring field');
  841. $field
  842. .blur()
  843. ;
  844. }
  845. if(!event.ctrlKey && key == keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
  846. if(!keyHeldDown) {
  847. $field.one('keyup' + eventNamespace, module.event.field.keyup);
  848. module.submit();
  849. module.debug('Enter pressed on input submitting form');
  850. }
  851. keyHeldDown = true;
  852. }
  853. },
  854. keyup: function() {
  855. keyHeldDown = false;
  856. },
  857. blur: function(event) {
  858. var
  859. $field = $(this),
  860. $fieldGroup = $field.closest($group),
  861. validationRules = module.get.validation($field)
  862. ;
  863. if( $fieldGroup.hasClass(className.error) ) {
  864. module.debug('Revalidating field', $field, validationRules);
  865. if(validationRules) {
  866. module.validate.field( validationRules );
  867. }
  868. }
  869. else if(settings.on == 'blur') {
  870. if(validationRules) {
  871. module.validate.field( validationRules );
  872. }
  873. }
  874. },
  875. change: function(event) {
  876. var
  877. $field = $(this),
  878. $fieldGroup = $field.closest($group),
  879. validationRules = module.get.validation($field)
  880. ;
  881. if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
  882. clearTimeout(module.timer);
  883. module.timer = setTimeout(function() {
  884. module.debug('Revalidating field', $field, module.get.validation($field));
  885. module.validate.field( validationRules );
  886. }, settings.delay);
  887. }
  888. }
  889. },
  890. beforeUnload: function(event) {
  891. if (module.is.dirty() && !submitting) {
  892. var event = event || window.event;
  893. // For modern browsers
  894. if (event) {
  895. event.returnValue = settings.text.leavingMessage;
  896. }
  897. // For olders...
  898. return settings.text.leavingMessage;
  899. }
  900. }
  901. },
  902. get: {
  903. ancillaryValue: function(rule) {
  904. if(!rule.type || (!rule.value && !module.is.bracketedRule(rule))) {
  905. return false;
  906. }
  907. return (rule.value !== undefined)
  908. ? rule.value
  909. : rule.type.match(settings.regExp.bracket)[1] + ''
  910. ;
  911. },
  912. ruleName: function(rule) {
  913. if( module.is.bracketedRule(rule) ) {
  914. return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
  915. }
  916. return rule.type;
  917. },
  918. changeEvent: function(type, $input) {
  919. if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
  920. return 'change';
  921. }
  922. else {
  923. return module.get.inputEvent();
  924. }
  925. },
  926. inputEvent: function() {
  927. return (document.createElement('input').oninput !== undefined)
  928. ? 'input'
  929. : (document.createElement('input').onpropertychange !== undefined)
  930. ? 'propertychange'
  931. : 'keyup'
  932. ;
  933. },
  934. fieldsFromShorthand: function(fields) {
  935. var
  936. fullFields = {}
  937. ;
  938. $.each(fields, function(name, rules) {
  939. if(typeof rules == 'string') {
  940. rules = [rules];
  941. }
  942. fullFields[name] = {
  943. rules: []
  944. };
  945. $.each(rules, function(index, rule) {
  946. fullFields[name].rules.push({ type: rule });
  947. });
  948. });
  949. return fullFields;
  950. },
  951. prompt: function(rule, field) {
  952. var
  953. ruleName = module.get.ruleName(rule),
  954. ancillary = module.get.ancillaryValue(rule),
  955. $field = module.get.field(field.identifier),
  956. value = $field.val(),
  957. prompt = $.isFunction(rule.prompt)
  958. ? rule.prompt(value)
  959. : rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
  960. requiresValue = (prompt.search('{value}') !== -1),
  961. requiresName = (prompt.search('{name}') !== -1),
  962. $label,
  963. name
  964. ;
  965. if(requiresValue) {
  966. prompt = prompt.replace('{value}', $field.val());
  967. }
  968. if(requiresName) {
  969. $label = $field.closest(selector.group).find('label').eq(0);
  970. name = ($label.length == 1)
  971. ? $label.text()
  972. : $field.prop('placeholder') || settings.text.unspecifiedField
  973. ;
  974. prompt = prompt.replace('{name}', name);
  975. }
  976. prompt = prompt.replace('{identifier}', field.identifier);
  977. prompt = prompt.replace('{ruleValue}', ancillary);
  978. if(!rule.prompt) {
  979. module.verbose('Using default validation prompt for type', prompt, ruleName);
  980. }
  981. return prompt;
  982. },
  983. settings: function() {
  984. if($.isPlainObject(parameters)) {
  985. var
  986. keys = Object.keys(parameters),
  987. isLegacySettings = (keys.length > 0)
  988. ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
  989. : false
  990. ;
  991. if(isLegacySettings) {
  992. // 1.x (ducktyped)
  993. settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
  994. validation = $.extend({}, $.fn.form.settings.defaults, parameters);
  995. module.error(settings.error.oldSyntax, element);
  996. module.verbose('Extending settings from legacy parameters', validation, settings);
  997. }
  998. else {
  999. // 2.x
  1000. if(parameters.fields && module.is.shorthandFields(parameters.fields)) {
  1001. parameters.fields = module.get.fieldsFromShorthand(parameters.fields);
  1002. }
  1003. settings = $.extend(true, {}, $.fn.form.settings, parameters);
  1004. validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
  1005. module.verbose('Extending settings', validation, settings);
  1006. }
  1007. }
  1008. else {
  1009. settings = $.fn.form.settings;
  1010. validation = $.fn.form.settings.defaults;
  1011. module.verbose('Using default form validation', validation, settings);
  1012. }
  1013. // shorthand
  1014. namespace = settings.namespace;
  1015. metadata = settings.metadata;
  1016. selector = settings.selector;
  1017. className = settings.className;
  1018. regExp = settings.regExp;
  1019. error = settings.error;
  1020. moduleNamespace = 'module-' + namespace;
  1021. eventNamespace = '.' + namespace;
  1022. // grab instance
  1023. instance = $module.data(moduleNamespace);
  1024. // refresh selector cache
  1025. module.refresh();
  1026. },
  1027. field: function(identifier) {
  1028. module.verbose('Finding field with identifier', identifier);
  1029. identifier = module.escape.string(identifier);
  1030. var t;
  1031. if((t=$field.filter('#' + identifier)).length > 0 ) {
  1032. return t;
  1033. }
  1034. if((t=$field.filter('[name="' + identifier +'"]')).length > 0 ) {
  1035. return t;
  1036. }
  1037. if((t=$field.filter('[name="' + identifier +'[]"]')).length > 0 ) {
  1038. return t;
  1039. }
  1040. if((t=$field.filter('[data-' + metadata.validate + '="'+ identifier +'"]')).length > 0 ) {
  1041. return t;
  1042. }
  1043. return $('<input/>');
  1044. },
  1045. fields: function(fields) {
  1046. var
  1047. $fields = $()
  1048. ;
  1049. $.each(fields, function(index, name) {
  1050. $fields = $fields.add( module.get.field(name) );
  1051. });
  1052. return $fields;
  1053. },
  1054. validation: function($field) {
  1055. var
  1056. fieldValidation,
  1057. identifier
  1058. ;
  1059. if(!validation) {
  1060. return false;
  1061. }
  1062. $.each(validation, function(fieldName, field) {
  1063. identifier = field.identifier || fieldName;
  1064. $.each(module.get.field(identifier), function(index, groupField) {
  1065. if(groupField == $field[0]) {
  1066. field.identifier = identifier;
  1067. fieldValidation = field;
  1068. return false;
  1069. }
  1070. });
  1071. });
  1072. return fieldValidation || false;
  1073. },
  1074. value: function (field) {
  1075. var
  1076. fields = [],
  1077. results
  1078. ;
  1079. fields.push(field);
  1080. results = module.get.values.call(element, fields);
  1081. return results[field];
  1082. },
  1083. values: function (fields) {
  1084. var
  1085. $fields = Array.isArray(fields)
  1086. ? module.get.fields(fields)
  1087. : $field,
  1088. values = {}
  1089. ;
  1090. $fields.each(function(index, field) {
  1091. var
  1092. $field = $(field),
  1093. $calendar = $field.closest(selector.uiCalendar),
  1094. name = $field.prop('name'),
  1095. value = $field.val(),
  1096. isCheckbox = $field.is(selector.checkbox),
  1097. isRadio = $field.is(selector.radio),
  1098. isMultiple = (name.indexOf('[]') !== -1),
  1099. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  1100. isChecked = (isCheckbox)
  1101. ? $field.is(':checked')
  1102. : false
  1103. ;
  1104. if(name) {
  1105. if(isMultiple) {
  1106. name = name.replace('[]', '');
  1107. if(!values[name]) {
  1108. values[name] = [];
  1109. }
  1110. if(isCheckbox) {
  1111. if(isChecked) {
  1112. values[name].push(value || true);
  1113. }
  1114. else {
  1115. values[name].push(false);
  1116. }
  1117. }
  1118. else {
  1119. values[name].push(value);
  1120. }
  1121. }
  1122. else {
  1123. if(isRadio) {
  1124. if(values[name] === undefined || values[name] == false) {
  1125. values[name] = (isChecked)
  1126. ? value || true
  1127. : false
  1128. ;
  1129. }
  1130. }
  1131. else if(isCheckbox) {
  1132. if(isChecked) {
  1133. values[name] = value || true;
  1134. }
  1135. else {
  1136. values[name] = false;
  1137. }
  1138. }
  1139. else if(isCalendar) {
  1140. var date = $calendar.calendar('get date');
  1141. if (date !== null) {
  1142. if (settings.dateHandling == 'date') {
  1143. values[name] = date;
  1144. } else if(settings.dateHandling == 'input') {
  1145. values[name] = $calendar.calendar('get input date')
  1146. } else if (settings.dateHandling == 'formatter') {
  1147. var type = $calendar.calendar('setting', 'type');
  1148. switch(type) {
  1149. case 'date':
  1150. values[name] = settings.formatter.date(date);
  1151. break;
  1152. case 'datetime':
  1153. values[name] = settings.formatter.datetime(date);
  1154. break;
  1155. case 'time':
  1156. values[name] = settings.formatter.time(date);
  1157. break;
  1158. case 'month':
  1159. values[name] = settings.formatter.month(date);
  1160. break;
  1161. case 'year':
  1162. values[name] = settings.formatter.year(date);
  1163. break;
  1164. default:
  1165. module.debug('Wrong calendar mode', $calendar, type);
  1166. values[name] = '';
  1167. }
  1168. }
  1169. } else {
  1170. values[name] = '';
  1171. }
  1172. } else {
  1173. values[name] = value;
  1174. }
  1175. }
  1176. }
  1177. });
  1178. return values;
  1179. },
  1180. dirtyFields: function() {
  1181. return $field.filter(function(index, e) {
  1182. return $(e).data(metadata.isDirty);
  1183. });
  1184. }
  1185. },
  1186. has: {
  1187. field: function(identifier) {
  1188. module.verbose('Checking for existence of a field with identifier', identifier);
  1189. identifier = module.escape.string(identifier);
  1190. if(typeof identifier !== 'string') {
  1191. module.error(error.identifier, identifier);
  1192. }
  1193. if($field.filter('#' + identifier).length > 0 ) {
  1194. return true;
  1195. }
  1196. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  1197. return true;
  1198. }
  1199. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  1200. return true;
  1201. }
  1202. return false;
  1203. }
  1204. },
  1205. can: {
  1206. useElement: function(element){
  1207. if ($.fn[element] !== undefined) {
  1208. return true;
  1209. }
  1210. module.error(error.noElement.replace('{element}',element));
  1211. return false;
  1212. }
  1213. },
  1214. escape: {
  1215. string: function(text) {
  1216. text = String(text);
  1217. return text.replace(regExp.escape, '\\$&');
  1218. }
  1219. },
  1220. add: {
  1221. // alias
  1222. rule: function(name, rules) {
  1223. module.add.field(name, rules);
  1224. },
  1225. field: function(name, rules) {
  1226. var
  1227. newValidation = {}
  1228. ;
  1229. if(module.is.shorthandRules(rules)) {
  1230. rules = Array.isArray(rules)
  1231. ? rules
  1232. : [rules]
  1233. ;
  1234. newValidation[name] = {
  1235. rules: []
  1236. };
  1237. $.each(rules, function(index, rule) {
  1238. newValidation[name].rules.push({ type: rule });
  1239. });
  1240. }
  1241. else {
  1242. newValidation[name] = rules;
  1243. }
  1244. validation = $.extend({}, validation, newValidation);
  1245. module.debug('Adding rules', newValidation, validation);
  1246. },
  1247. fields: function(fields) {
  1248. var
  1249. newValidation
  1250. ;
  1251. if(fields && module.is.shorthandFields(fields)) {
  1252. newValidation = module.get.fieldsFromShorthand(fields);
  1253. }
  1254. else {
  1255. newValidation = fields;
  1256. }
  1257. validation = $.extend({}, validation, newValidation);
  1258. },
  1259. prompt: function(identifier, errors, internal) {
  1260. var
  1261. $field = module.get.field(identifier),
  1262. $fieldGroup = $field.closest($group),
  1263. $prompt = $fieldGroup.children(selector.prompt),
  1264. promptExists = ($prompt.length !== 0)
  1265. ;
  1266. errors = (typeof errors == 'string')
  1267. ? [errors]
  1268. : errors
  1269. ;
  1270. module.verbose('Adding field error state', identifier);
  1271. if(!internal) {
  1272. $fieldGroup
  1273. .addClass(className.error)
  1274. ;
  1275. }
  1276. if(settings.inline) {
  1277. if(!promptExists) {
  1278. $prompt = settings.templates.prompt(errors, className.label);
  1279. $prompt
  1280. .appendTo($fieldGroup)
  1281. ;
  1282. }
  1283. $prompt
  1284. .html(errors[0])
  1285. ;
  1286. if(!promptExists) {
  1287. if(settings.transition && module.can.useElement('transition') && $module.transition('is supported')) {
  1288. module.verbose('Displaying error with css transition', settings.transition);
  1289. $prompt.transition(settings.transition + ' in', settings.duration);
  1290. }
  1291. else {
  1292. module.verbose('Displaying error with fallback javascript animation');
  1293. $prompt
  1294. .fadeIn(settings.duration)
  1295. ;
  1296. }
  1297. }
  1298. else {
  1299. module.verbose('Inline errors are disabled, no inline error added', identifier);
  1300. }
  1301. }
  1302. },
  1303. errors: function(errors) {
  1304. module.debug('Adding form error messages', errors);
  1305. module.set.error();
  1306. $message
  1307. .html( settings.templates.error(errors) )
  1308. ;
  1309. }
  1310. },
  1311. remove: {
  1312. rule: function(field, rule) {
  1313. var
  1314. rules = Array.isArray(rule)
  1315. ? rule
  1316. : [rule]
  1317. ;
  1318. if(validation[field] === undefined || !Array.isArray(validation[field].rules)) {
  1319. return;
  1320. }
  1321. if(rule === undefined) {
  1322. module.debug('Removed all rules');
  1323. validation[field].rules = [];
  1324. return;
  1325. }
  1326. $.each(validation[field].rules, function(index, rule) {
  1327. if(rule && rules.indexOf(rule.type) !== -1) {
  1328. module.debug('Removed rule', rule.type);
  1329. validation[field].rules.splice(index, 1);
  1330. }
  1331. });
  1332. },
  1333. field: function(field) {
  1334. var
  1335. fields = Array.isArray(field)
  1336. ? field
  1337. : [field]
  1338. ;
  1339. $.each(fields, function(index, field) {
  1340. module.remove.rule(field);
  1341. });
  1342. },
  1343. // alias
  1344. rules: function(field, rules) {
  1345. if(Array.isArray(field)) {
  1346. $.each(field, function(index, field) {
  1347. module.remove.rule(field, rules);
  1348. });
  1349. }
  1350. else {
  1351. module.remove.rule(field, rules);
  1352. }
  1353. },
  1354. fields: function(fields) {
  1355. module.remove.field(fields);
  1356. },
  1357. prompt: function(identifier) {
  1358. var
  1359. $field = module.get.field(identifier),
  1360. $fieldGroup = $field.closest($group),
  1361. $prompt = $fieldGroup.children(selector.prompt)
  1362. ;
  1363. $fieldGroup
  1364. .removeClass(className.error)
  1365. ;
  1366. if(settings.inline && $prompt.is(':visible')) {
  1367. module.verbose('Removing prompt for field', identifier);
  1368. if(settings.transition && module.can.useElement('transition') && $module.transition('is supported')) {
  1369. $prompt.transition(settings.transition + ' out', settings.duration, function() {
  1370. $prompt.remove();
  1371. });
  1372. }
  1373. else {
  1374. $prompt
  1375. .fadeOut(settings.duration, function(){
  1376. $prompt.remove();
  1377. })
  1378. ;
  1379. }
  1380. }
  1381. }
  1382. },
  1383. set: {
  1384. success: function() {
  1385. $module
  1386. .removeClass(className.error)
  1387. .addClass(className.success)
  1388. ;
  1389. },
  1390. defaults: function () {
  1391. $field.each(function (index, el) {
  1392. var
  1393. $el = $(el),
  1394. $parent = $el.parent(),
  1395. isCheckbox = ($el.filter(selector.checkbox).length > 0),
  1396. isDropdown = $parent.is(selector.uiDropdown) && module.can.useElement('dropdown'),
  1397. $calendar = $el.closest(selector.uiCalendar),
  1398. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  1399. value = (isCheckbox)
  1400. ? $el.is(':checked')
  1401. : $el.val()
  1402. ;
  1403. if (isDropdown) {
  1404. $parent.dropdown('save defaults');
  1405. }
  1406. else if (isCalendar) {
  1407. $calendar.calendar('refresh');
  1408. }
  1409. $el.data(metadata.defaultValue, value);
  1410. $el.data(metadata.isDirty, false);
  1411. });
  1412. },
  1413. error: function() {
  1414. $module
  1415. .removeClass(className.success)
  1416. .addClass(className.error)
  1417. ;
  1418. },
  1419. value: function (field, value) {
  1420. var
  1421. fields = {}
  1422. ;
  1423. fields[field] = value;
  1424. return module.set.values.call(element, fields);
  1425. },
  1426. values: function (fields) {
  1427. if($.isEmptyObject(fields)) {
  1428. return;
  1429. }
  1430. $.each(fields, function(key, value) {
  1431. var
  1432. $field = module.get.field(key),
  1433. $element = $field.parent(),
  1434. $calendar = $field.closest(selector.uiCalendar),
  1435. isMultiple = Array.isArray(value),
  1436. isCheckbox = $element.is(selector.uiCheckbox) && module.can.useElement('checkbox'),
  1437. isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
  1438. isRadio = ($field.is(selector.radio) && isCheckbox),
  1439. isCalendar = ($calendar.length > 0 && module.can.useElement('calendar')),
  1440. fieldExists = ($field.length > 0),
  1441. $multipleField
  1442. ;
  1443. if(fieldExists) {
  1444. if(isMultiple && isCheckbox) {
  1445. module.verbose('Selecting multiple', value, $field);
  1446. $element.checkbox('uncheck');
  1447. $.each(value, function(index, value) {
  1448. $multipleField = $field.filter('[value="' + value + '"]');
  1449. $element = $multipleField.parent();
  1450. if($multipleField.length > 0) {
  1451. $element.checkbox('check');
  1452. }
  1453. });
  1454. }
  1455. else if(isRadio) {
  1456. module.verbose('Selecting radio value', value, $field);
  1457. $field.filter('[value="' + value + '"]')
  1458. .parent(selector.uiCheckbox)
  1459. .checkbox('check')
  1460. ;
  1461. }
  1462. else if(isCheckbox) {
  1463. module.verbose('Setting checkbox value', value, $element);
  1464. if(value === true || value === 1) {
  1465. $element.checkbox('check');
  1466. }
  1467. else {
  1468. $element.checkbox('uncheck');
  1469. }
  1470. }
  1471. else if(isDropdown) {
  1472. module.verbose('Setting dropdown value', value, $element);
  1473. $element.dropdown('set selected', value);
  1474. }
  1475. else if (isCalendar) {
  1476. $calendar.calendar('set date',value);
  1477. }
  1478. else {
  1479. module.verbose('Setting field value', value, $field);
  1480. $field.val(value);
  1481. }
  1482. }
  1483. });
  1484. },
  1485. dirty: function() {
  1486. module.verbose('Setting state dirty');
  1487. dirty = true;
  1488. history[0] = history[1];
  1489. history[1] = 'dirty';
  1490. if (module.is.justClean()) {
  1491. $module.trigger('dirty');
  1492. }
  1493. },
  1494. clean: function() {
  1495. module.verbose('Setting state clean');
  1496. dirty = false;
  1497. history[0] = history[1];
  1498. history[1] = 'clean';
  1499. if (module.is.justDirty()) {
  1500. $module.trigger('clean');
  1501. }
  1502. },
  1503. asClean: function() {
  1504. module.set.defaults();
  1505. module.set.clean();
  1506. },
  1507. asDirty: function() {
  1508. module.set.defaults();
  1509. module.set.dirty();
  1510. }
  1511. },
  1512. validate: {
  1513. form: function(event, ignoreCallbacks) {
  1514. var values = module.get.values();
  1515. // input keydown event will fire submit repeatedly by browser default
  1516. if(keyHeldDown) {
  1517. return false;
  1518. }
  1519. // reset errors
  1520. formErrors = [];
  1521. if( module.determine.isValid() ) {
  1522. module.debug('Form has no validation errors, submitting');
  1523. module.set.success();
  1524. if(ignoreCallbacks !== true) {
  1525. return settings.onSuccess.call(element, event, values);
  1526. }
  1527. }
  1528. else {
  1529. module.debug('Form has errors');
  1530. module.set.error();
  1531. if(!settings.inline) {
  1532. module.add.errors(formErrors);
  1533. }
  1534. // prevent ajax submit
  1535. if(event && $module.data('moduleApi') !== undefined) {
  1536. event.stopImmediatePropagation();
  1537. }
  1538. if(ignoreCallbacks !== true) {
  1539. return settings.onFailure.call(element, formErrors, values);
  1540. }
  1541. }
  1542. },
  1543. // takes a validation object and returns whether field passes validation
  1544. field: function(field, fieldName, showErrors) {
  1545. showErrors = (showErrors !== undefined)
  1546. ? showErrors
  1547. : true
  1548. ;
  1549. if(typeof field == 'string') {
  1550. module.verbose('Validating field', field);
  1551. fieldName = field;
  1552. field = validation[field];
  1553. }
  1554. var
  1555. identifier = field.identifier || fieldName,
  1556. $field = module.get.field(identifier),
  1557. $dependsField = (field.depends)
  1558. ? module.get.field(field.depends)
  1559. : false,
  1560. fieldValid = true,
  1561. fieldErrors = []
  1562. ;
  1563. if(!field.identifier) {
  1564. module.debug('Using field name as identifier', identifier);
  1565. field.identifier = identifier;
  1566. }
  1567. var isDisabled = true;
  1568. $.each($field, function(){
  1569. if(!$(this).prop('disabled')) {
  1570. isDisabled = false;
  1571. return false;
  1572. }
  1573. });
  1574. if(isDisabled) {
  1575. module.debug('Field is disabled. Skipping', identifier);
  1576. }
  1577. else if(field.optional && module.is.blank($field)){
  1578. module.debug('Field is optional and blank. Skipping', identifier);
  1579. }
  1580. else if(field.depends && module.is.empty($dependsField)) {
  1581. module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
  1582. }
  1583. else if(field.rules !== undefined) {
  1584. $field.closest($group).removeClass(className.error);
  1585. $.each(field.rules, function(index, rule) {
  1586. if( module.has.field(identifier)) {
  1587. var invalidFields = module.validate.rule(field, rule,true) || [];
  1588. if (invalidFields.length>0){
  1589. module.debug('Field is invalid', identifier, rule.type);
  1590. fieldErrors.push(module.get.prompt(rule, field));
  1591. fieldValid = false;
  1592. if(showErrors){
  1593. $(invalidFields).closest($group).addClass(className.error);
  1594. }
  1595. }
  1596. }
  1597. });
  1598. }
  1599. if(fieldValid) {
  1600. if(showErrors) {
  1601. module.remove.prompt(identifier, fieldErrors);
  1602. settings.onValid.call($field);
  1603. }
  1604. }
  1605. else {
  1606. if(showErrors) {
  1607. formErrors = formErrors.concat(fieldErrors);
  1608. module.add.prompt(identifier, fieldErrors, true);
  1609. settings.onInvalid.call($field, fieldErrors);
  1610. }
  1611. return false;
  1612. }
  1613. return true;
  1614. },
  1615. // takes validation rule and returns whether field passes rule
  1616. rule: function(field, rule, internal) {
  1617. var
  1618. $field = module.get.field(field.identifier),
  1619. ancillary = module.get.ancillaryValue(rule),
  1620. ruleName = module.get.ruleName(rule),
  1621. ruleFunction = settings.rules[ruleName],
  1622. invalidFields = [],
  1623. isCheckbox = $field.is(selector.checkbox),
  1624. isValid = function(field){
  1625. var value = (isCheckbox ? $(field).filter(':checked').val() : $(field).val());
  1626. // cast to string avoiding encoding special values
  1627. value = (value === undefined || value === '' || value === null)
  1628. ? ''
  1629. : (settings.shouldTrim) ? $.trim(value + '') : String(value + '')
  1630. ;
  1631. return ruleFunction.call(field, value, ancillary, $module);
  1632. }
  1633. ;
  1634. if( !$.isFunction(ruleFunction) ) {
  1635. module.error(error.noRule, ruleName);
  1636. return;
  1637. }
  1638. if(isCheckbox) {
  1639. if (!isValid($field)) {
  1640. invalidFields = $field;
  1641. }
  1642. } else {
  1643. $.each($field, function (index, field) {
  1644. if (!isValid(field)) {
  1645. invalidFields.push(field);
  1646. }
  1647. });
  1648. }
  1649. return internal ? invalidFields : !(invalidFields.length>0);
  1650. }
  1651. },
  1652. setting: function(name, value) {
  1653. if( $.isPlainObject(name) ) {
  1654. $.extend(true, settings, name);
  1655. }
  1656. else if(value !== undefined) {
  1657. settings[name] = value;
  1658. }
  1659. else {
  1660. return settings[name];
  1661. }
  1662. },
  1663. internal: function(name, value) {
  1664. if( $.isPlainObject(name) ) {
  1665. $.extend(true, module, name);
  1666. }
  1667. else if(value !== undefined) {
  1668. module[name] = value;
  1669. }
  1670. else {
  1671. return module[name];
  1672. }
  1673. },
  1674. debug: function() {
  1675. if(!settings.silent && settings.debug) {
  1676. if(settings.performance) {
  1677. module.performance.log(arguments);
  1678. }
  1679. else {
  1680. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1681. module.debug.apply(console, arguments);
  1682. }
  1683. }
  1684. },
  1685. verbose: function() {
  1686. if(!settings.silent && settings.verbose && settings.debug) {
  1687. if(settings.performance) {
  1688. module.performance.log(arguments);
  1689. }
  1690. else {
  1691. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1692. module.verbose.apply(console, arguments);
  1693. }
  1694. }
  1695. },
  1696. error: function() {
  1697. if(!settings.silent) {
  1698. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  1699. module.error.apply(console, arguments);
  1700. }
  1701. },
  1702. performance: {
  1703. log: function(message) {
  1704. var
  1705. currentTime,
  1706. executionTime,
  1707. previousTime
  1708. ;
  1709. if(settings.performance) {
  1710. currentTime = new Date().getTime();
  1711. previousTime = time || currentTime;
  1712. executionTime = currentTime - previousTime;
  1713. time = currentTime;
  1714. performance.push({
  1715. 'Name' : message[0],
  1716. 'Arguments' : [].slice.call(message, 1) || '',
  1717. 'Element' : element,
  1718. 'Execution Time' : executionTime
  1719. });
  1720. }
  1721. clearTimeout(module.performance.timer);
  1722. module.performance.timer = setTimeout(module.performance.display, 500);
  1723. },
  1724. display: function() {
  1725. var
  1726. title = settings.name + ':',
  1727. totalTime = 0
  1728. ;
  1729. time = false;
  1730. clearTimeout(module.performance.timer);
  1731. $.each(performance, function(index, data) {
  1732. totalTime += data['Execution Time'];
  1733. });
  1734. title += ' ' + totalTime + 'ms';
  1735. if(moduleSelector) {
  1736. title += ' \'' + moduleSelector + '\'';
  1737. }
  1738. if($allModules.length > 1) {
  1739. title += ' ' + '(' + $allModules.length + ')';
  1740. }
  1741. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  1742. console.groupCollapsed(title);
  1743. if(console.table) {
  1744. console.table(performance);
  1745. }
  1746. else {
  1747. $.each(performance, function(index, data) {
  1748. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  1749. });
  1750. }
  1751. console.groupEnd();
  1752. }
  1753. performance = [];
  1754. }
  1755. },
  1756. invoke: function(query, passedArguments, context) {
  1757. var
  1758. object = instance,
  1759. maxDepth,
  1760. found,
  1761. response
  1762. ;
  1763. passedArguments = passedArguments || queryArguments;
  1764. context = element || context;
  1765. if(typeof query == 'string' && object !== undefined) {
  1766. query = query.split(/[\. ]/);
  1767. maxDepth = query.length - 1;
  1768. $.each(query, function(depth, value) {
  1769. var camelCaseValue = (depth != maxDepth)
  1770. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  1771. : query
  1772. ;
  1773. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  1774. object = object[camelCaseValue];
  1775. }
  1776. else if( object[camelCaseValue] !== undefined ) {
  1777. found = object[camelCaseValue];
  1778. return false;
  1779. }
  1780. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  1781. object = object[value];
  1782. }
  1783. else if( object[value] !== undefined ) {
  1784. found = object[value];
  1785. return false;
  1786. }
  1787. else {
  1788. return false;
  1789. }
  1790. });
  1791. }
  1792. if( $.isFunction( found ) ) {
  1793. response = found.apply(context, passedArguments);
  1794. }
  1795. else if(found !== undefined) {
  1796. response = found;
  1797. }
  1798. if(Array.isArray(returnedValue)) {
  1799. returnedValue.push(response);
  1800. }
  1801. else if(returnedValue !== undefined) {
  1802. returnedValue = [returnedValue, response];
  1803. }
  1804. else if(response !== undefined) {
  1805. returnedValue = response;
  1806. }
  1807. return found;
  1808. }
  1809. };
  1810. module.initialize();
  1811. })
  1812. ;
  1813. return (returnedValue !== undefined)
  1814. ? returnedValue
  1815. : this
  1816. ;
  1817. };
  1818. $.fn.form.settings = {
  1819. name : 'Form',
  1820. namespace : 'form',
  1821. debug : false,
  1822. verbose : false,
  1823. performance : true,
  1824. fields : false,
  1825. keyboardShortcuts : true,
  1826. on : 'submit',
  1827. inline : false,
  1828. delay : 200,
  1829. revalidate : true,
  1830. shouldTrim : true,
  1831. transition : 'scale',
  1832. duration : 200,
  1833. preventLeaving : false,
  1834. dateHandling : 'date', // 'date', 'input', 'formatter'
  1835. onValid : function() {},
  1836. onInvalid : function() {},
  1837. onSuccess : function() { return true; },
  1838. onFailure : function() { return false; },
  1839. onDirty : function() {},
  1840. onClean : function() {},
  1841. metadata : {
  1842. defaultValue : 'default',
  1843. validate : 'validate',
  1844. isDirty : 'isDirty'
  1845. },
  1846. regExp: {
  1847. htmlID : /^[a-zA-Z][\w:.-]*$/g,
  1848. bracket : /\[(.*)\]/i,
  1849. decimal : /^\d+\.?\d*$/,
  1850. email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
  1851. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|:,=@]/g,
  1852. flags : /^\/(.*)\/(.*)?/,
  1853. integer : /^\-?\d+$/,
  1854. number : /^\-?\d*(\.\d+)?$/,
  1855. url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
  1856. },
  1857. text: {
  1858. unspecifiedRule : 'Please enter a valid value',
  1859. unspecifiedField : 'This field',
  1860. leavingMessage : 'There are unsaved changes on this page which will be discarded if you continue.'
  1861. },
  1862. prompt: {
  1863. empty : '{name} must have a value',
  1864. checked : '{name} must be checked',
  1865. email : '{name} must be a valid e-mail',
  1866. url : '{name} must be a valid url',
  1867. regExp : '{name} is not formatted correctly',
  1868. integer : '{name} must be an integer',
  1869. decimal : '{name} must be a decimal number',
  1870. number : '{name} must be set to a number',
  1871. is : '{name} must be "{ruleValue}"',
  1872. isExactly : '{name} must be exactly "{ruleValue}"',
  1873. not : '{name} cannot be set to "{ruleValue}"',
  1874. notExactly : '{name} cannot be set to exactly "{ruleValue}"',
  1875. contain : '{name} must contain "{ruleValue}"',
  1876. containExactly : '{name} must contain exactly "{ruleValue}"',
  1877. doesntContain : '{name} cannot contain "{ruleValue}"',
  1878. doesntContainExactly : '{name} cannot contain exactly "{ruleValue}"',
  1879. minLength : '{name} must be at least {ruleValue} characters',
  1880. length : '{name} must be at least {ruleValue} characters',
  1881. exactLength : '{name} must be exactly {ruleValue} characters',
  1882. maxLength : '{name} cannot be longer than {ruleValue} characters',
  1883. match : '{name} must match {ruleValue} field',
  1884. different : '{name} must have a different value than {ruleValue} field',
  1885. creditCard : '{name} must be a valid credit card number',
  1886. minCount : '{name} must have at least {ruleValue} choices',
  1887. exactCount : '{name} must have exactly {ruleValue} choices',
  1888. maxCount : '{name} must have {ruleValue} or less choices'
  1889. },
  1890. selector : {
  1891. checkbox : 'input[type="checkbox"], input[type="radio"]',
  1892. clear : '.clear',
  1893. field : 'input, textarea, select',
  1894. group : '.field',
  1895. input : 'input',
  1896. message : '.error.message',
  1897. prompt : '.prompt.label',
  1898. radio : 'input[type="radio"]',
  1899. reset : '.reset:not([type="reset"])',
  1900. submit : '.submit:not([type="submit"])',
  1901. uiCheckbox : '.ui.checkbox',
  1902. uiDropdown : '.ui.dropdown',
  1903. uiCalendar : '.ui.calendar'
  1904. },
  1905. className : {
  1906. error : 'error',
  1907. label : 'ui basic red pointing prompt label',
  1908. pressed : 'down',
  1909. success : 'success'
  1910. },
  1911. error: {
  1912. identifier : 'You must specify a string identifier for each field',
  1913. method : 'The method you called is not defined.',
  1914. noRule : 'There is no rule matching the one you specified',
  1915. oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.',
  1916. noElement : 'This module requires ui {element}'
  1917. },
  1918. templates: {
  1919. // template that produces error message
  1920. error: function(errors) {
  1921. var
  1922. html = '<ul class="list">'
  1923. ;
  1924. $.each(errors, function(index, value) {
  1925. html += '<li>' + value + '</li>';
  1926. });
  1927. html += '</ul>';
  1928. return $(html);
  1929. },
  1930. // template that produces label
  1931. prompt: function(errors, labelClasses) {
  1932. return $('<div/>')
  1933. .addClass(labelClasses)
  1934. .html(errors[0])
  1935. ;
  1936. }
  1937. },
  1938. formatter: {
  1939. date: function(date) {
  1940. return Intl.DateTimeFormat('en-GB').format(date);
  1941. },
  1942. datetime: function(date) {
  1943. return Intl.DateTimeFormat('en-GB', {
  1944. year: "numeric",
  1945. month: "2-digit",
  1946. day: "2-digit",
  1947. hour: '2-digit',
  1948. minute: '2-digit',
  1949. second: '2-digit'
  1950. }).format(date);
  1951. },
  1952. time: function(date) {
  1953. return Intl.DateTimeFormat('en-GB', {
  1954. hour: '2-digit',
  1955. minute: '2-digit',
  1956. second: '2-digit'
  1957. }).format(date);
  1958. },
  1959. month: function(date) {
  1960. return Intl.DateTimeFormat('en-GB', {
  1961. month: '2-digit',
  1962. year: 'numeric'
  1963. }).format(date);
  1964. },
  1965. year: function(date) {
  1966. return Intl.DateTimeFormat('en-GB', {
  1967. year: 'numeric'
  1968. }).format(date);
  1969. }
  1970. },
  1971. rules: {
  1972. // is not empty or blank string
  1973. empty: function(value) {
  1974. return !(value === undefined || '' === value || Array.isArray(value) && value.length === 0);
  1975. },
  1976. // checkbox checked
  1977. checked: function() {
  1978. return ($(this).filter(':checked').length > 0);
  1979. },
  1980. // is most likely an email
  1981. email: function(value){
  1982. return $.fn.form.settings.regExp.email.test(value);
  1983. },
  1984. // value is most likely url
  1985. url: function(value) {
  1986. return $.fn.form.settings.regExp.url.test(value);
  1987. },
  1988. // matches specified regExp
  1989. regExp: function(value, regExp) {
  1990. if(regExp instanceof RegExp) {
  1991. return value.match(regExp);
  1992. }
  1993. var
  1994. regExpParts = regExp.match($.fn.form.settings.regExp.flags),
  1995. flags
  1996. ;
  1997. // regular expression specified as /baz/gi (flags)
  1998. if(regExpParts) {
  1999. regExp = (regExpParts.length >= 2)
  2000. ? regExpParts[1]
  2001. : regExp
  2002. ;
  2003. flags = (regExpParts.length >= 3)
  2004. ? regExpParts[2]
  2005. : ''
  2006. ;
  2007. }
  2008. return value.match( new RegExp(regExp, flags) );
  2009. },
  2010. // is valid integer or matches range
  2011. integer: function(value, range) {
  2012. var
  2013. intRegExp = $.fn.form.settings.regExp.integer,
  2014. min,
  2015. max,
  2016. parts
  2017. ;
  2018. if( !range || ['', '..'].indexOf(range) !== -1) {
  2019. // do nothing
  2020. }
  2021. else if(range.indexOf('..') == -1) {
  2022. if(intRegExp.test(range)) {
  2023. min = max = range - 0;
  2024. }
  2025. }
  2026. else {
  2027. parts = range.split('..', 2);
  2028. if(intRegExp.test(parts[0])) {
  2029. min = parts[0] - 0;
  2030. }
  2031. if(intRegExp.test(parts[1])) {
  2032. max = parts[1] - 0;
  2033. }
  2034. }
  2035. return (
  2036. intRegExp.test(value) &&
  2037. (min === undefined || value >= min) &&
  2038. (max === undefined || value <= max)
  2039. );
  2040. },
  2041. // is valid number (with decimal)
  2042. decimal: function(value) {
  2043. return $.fn.form.settings.regExp.decimal.test(value);
  2044. },
  2045. // is valid number
  2046. number: function(value) {
  2047. return $.fn.form.settings.regExp.number.test(value);
  2048. },
  2049. // is value (case insensitive)
  2050. is: function(value, text) {
  2051. text = (typeof text == 'string')
  2052. ? text.toLowerCase()
  2053. : text
  2054. ;
  2055. value = (typeof value == 'string')
  2056. ? value.toLowerCase()
  2057. : value
  2058. ;
  2059. return (value == text);
  2060. },
  2061. // is value
  2062. isExactly: function(value, text) {
  2063. return (value == text);
  2064. },
  2065. // value is not another value (case insensitive)
  2066. not: function(value, notValue) {
  2067. value = (typeof value == 'string')
  2068. ? value.toLowerCase()
  2069. : value
  2070. ;
  2071. notValue = (typeof notValue == 'string')
  2072. ? notValue.toLowerCase()
  2073. : notValue
  2074. ;
  2075. return (value != notValue);
  2076. },
  2077. // value is not another value (case sensitive)
  2078. notExactly: function(value, notValue) {
  2079. return (value != notValue);
  2080. },
  2081. // value contains text (insensitive)
  2082. contains: function(value, text) {
  2083. // escape regex characters
  2084. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  2085. return (value.search( new RegExp(text, 'i') ) !== -1);
  2086. },
  2087. // value contains text (case sensitive)
  2088. containsExactly: function(value, text) {
  2089. // escape regex characters
  2090. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  2091. return (value.search( new RegExp(text) ) !== -1);
  2092. },
  2093. // value contains text (insensitive)
  2094. doesntContain: function(value, text) {
  2095. // escape regex characters
  2096. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  2097. return (value.search( new RegExp(text, 'i') ) === -1);
  2098. },
  2099. // value contains text (case sensitive)
  2100. doesntContainExactly: function(value, text) {
  2101. // escape regex characters
  2102. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  2103. return (value.search( new RegExp(text) ) === -1);
  2104. },
  2105. // is at least string length
  2106. minLength: function(value, requiredLength) {
  2107. return (value !== undefined)
  2108. ? (value.length >= requiredLength)
  2109. : false
  2110. ;
  2111. },
  2112. // see rls notes for 2.0.6 (this is a duplicate of minLength)
  2113. length: function(value, requiredLength) {
  2114. return (value !== undefined)
  2115. ? (value.length >= requiredLength)
  2116. : false
  2117. ;
  2118. },
  2119. // is exactly length
  2120. exactLength: function(value, requiredLength) {
  2121. return (value !== undefined)
  2122. ? (value.length == requiredLength)
  2123. : false
  2124. ;
  2125. },
  2126. // is less than length
  2127. maxLength: function(value, maxLength) {
  2128. return (value !== undefined)
  2129. ? (value.length <= maxLength)
  2130. : false
  2131. ;
  2132. },
  2133. // matches another field
  2134. match: function(value, identifier, $module) {
  2135. var
  2136. matchingValue,
  2137. matchingElement
  2138. ;
  2139. if((matchingElement = $module.find('[data-validate="'+ identifier +'"]')).length > 0 ) {
  2140. matchingValue = matchingElement.val();
  2141. }
  2142. else if((matchingElement = $module.find('#' + identifier)).length > 0) {
  2143. matchingValue = matchingElement.val();
  2144. }
  2145. else if((matchingElement = $module.find('[name="' + identifier +'"]')).length > 0) {
  2146. matchingValue = matchingElement.val();
  2147. }
  2148. else if((matchingElement = $module.find('[name="' + identifier +'[]"]')).length > 0 ) {
  2149. matchingValue = matchingElement;
  2150. }
  2151. return (matchingValue !== undefined)
  2152. ? ( value.toString() == matchingValue.toString() )
  2153. : false
  2154. ;
  2155. },
  2156. // different than another field
  2157. different: function(value, identifier, $module) {
  2158. // use either id or name of field
  2159. var
  2160. matchingValue,
  2161. matchingElement
  2162. ;
  2163. if((matchingElement = $module.find('[data-validate="'+ identifier +'"]')).length > 0 ) {
  2164. matchingValue = matchingElement.val();
  2165. }
  2166. else if((matchingElement = $module.find('#' + identifier)).length > 0) {
  2167. matchingValue = matchingElement.val();
  2168. }
  2169. else if((matchingElement = $module.find('[name="' + identifier +'"]')).length > 0) {
  2170. matchingValue = matchingElement.val();
  2171. }
  2172. else if((matchingElement = $module.find('[name="' + identifier +'[]"]')).length > 0 ) {
  2173. matchingValue = matchingElement;
  2174. }
  2175. return (matchingValue !== undefined)
  2176. ? ( value.toString() !== matchingValue.toString() )
  2177. : false
  2178. ;
  2179. },
  2180. creditCard: function(cardNumber, cardTypes) {
  2181. var
  2182. cards = {
  2183. visa: {
  2184. pattern : /^4/,
  2185. length : [16]
  2186. },
  2187. amex: {
  2188. pattern : /^3[47]/,
  2189. length : [15]
  2190. },
  2191. mastercard: {
  2192. pattern : /^5[1-5]/,
  2193. length : [16]
  2194. },
  2195. discover: {
  2196. 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)/,
  2197. length : [16]
  2198. },
  2199. unionPay: {
  2200. pattern : /^(62|88)/,
  2201. length : [16, 17, 18, 19]
  2202. },
  2203. jcb: {
  2204. pattern : /^35(2[89]|[3-8][0-9])/,
  2205. length : [16]
  2206. },
  2207. maestro: {
  2208. pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
  2209. length : [12, 13, 14, 15, 16, 17, 18, 19]
  2210. },
  2211. dinersClub: {
  2212. pattern : /^(30[0-5]|^36)/,
  2213. length : [14]
  2214. },
  2215. laser: {
  2216. pattern : /^(6304|670[69]|6771)/,
  2217. length : [16, 17, 18, 19]
  2218. },
  2219. visaElectron: {
  2220. pattern : /^(4026|417500|4508|4844|491(3|7))/,
  2221. length : [16]
  2222. }
  2223. },
  2224. valid = {},
  2225. validCard = false,
  2226. requiredTypes = (typeof cardTypes == 'string')
  2227. ? cardTypes.split(',')
  2228. : false,
  2229. unionPay,
  2230. validation
  2231. ;
  2232. if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
  2233. return;
  2234. }
  2235. // allow dashes in card
  2236. cardNumber = cardNumber.replace(/[\-]/g, '');
  2237. // verify card types
  2238. if(requiredTypes) {
  2239. $.each(requiredTypes, function(index, type){
  2240. // verify each card type
  2241. validation = cards[type];
  2242. if(validation) {
  2243. valid = {
  2244. length : ($.inArray(cardNumber.length, validation.length) !== -1),
  2245. pattern : (cardNumber.search(validation.pattern) !== -1)
  2246. };
  2247. if(valid.length && valid.pattern) {
  2248. validCard = true;
  2249. }
  2250. }
  2251. });
  2252. if(!validCard) {
  2253. return false;
  2254. }
  2255. }
  2256. // skip luhn for UnionPay
  2257. unionPay = {
  2258. number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
  2259. pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
  2260. };
  2261. if(unionPay.number && unionPay.pattern) {
  2262. return true;
  2263. }
  2264. // verify luhn, adapted from <https://gist.github.com/2134376>
  2265. var
  2266. length = cardNumber.length,
  2267. multiple = 0,
  2268. producedValue = [
  2269. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
  2270. [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
  2271. ],
  2272. sum = 0
  2273. ;
  2274. while (length--) {
  2275. sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
  2276. multiple ^= 1;
  2277. }
  2278. return (sum % 10 === 0 && sum > 0);
  2279. },
  2280. minCount: function(value, minCount) {
  2281. if(minCount == 0) {
  2282. return true;
  2283. }
  2284. if(minCount == 1) {
  2285. return (value !== '');
  2286. }
  2287. return (value.split(',').length >= minCount);
  2288. },
  2289. exactCount: function(value, exactCount) {
  2290. if(exactCount == 0) {
  2291. return (value === '');
  2292. }
  2293. if(exactCount == 1) {
  2294. return (value !== '' && value.search(',') === -1);
  2295. }
  2296. return (value.split(',').length == exactCount);
  2297. },
  2298. maxCount: function(value, maxCount) {
  2299. if(maxCount == 0) {
  2300. return false;
  2301. }
  2302. if(maxCount == 1) {
  2303. return (value.search(',') === -1);
  2304. }
  2305. return (value.split(',').length <= maxCount);
  2306. }
  2307. }
  2308. };
  2309. })( jQuery, window, document );
  2310. /*!
  2311. * # Fomantic-UI - Accordion
  2312. * http://github.com/fomantic/Fomantic-UI/
  2313. *
  2314. *
  2315. * Released under the MIT license
  2316. * http://opensource.org/licenses/MIT
  2317. *
  2318. */
  2319. ;(function ($, window, document, undefined) {
  2320. 'use strict';
  2321. $.isFunction = $.isFunction || function(obj) {
  2322. return typeof obj === "function" && typeof obj.nodeType !== "number";
  2323. };
  2324. window = (typeof window != 'undefined' && window.Math == Math)
  2325. ? window
  2326. : (typeof self != 'undefined' && self.Math == Math)
  2327. ? self
  2328. : Function('return this')()
  2329. ;
  2330. $.fn.accordion = function(parameters) {
  2331. var
  2332. $allModules = $(this),
  2333. time = new Date().getTime(),
  2334. performance = [],
  2335. query = arguments[0],
  2336. methodInvoked = (typeof query == 'string'),
  2337. queryArguments = [].slice.call(arguments, 1),
  2338. returnedValue
  2339. ;
  2340. $allModules
  2341. .each(function() {
  2342. var
  2343. settings = ( $.isPlainObject(parameters) )
  2344. ? $.extend(true, {}, $.fn.accordion.settings, parameters)
  2345. : $.extend({}, $.fn.accordion.settings),
  2346. className = settings.className,
  2347. namespace = settings.namespace,
  2348. selector = settings.selector,
  2349. error = settings.error,
  2350. eventNamespace = '.' + namespace,
  2351. moduleNamespace = 'module-' + namespace,
  2352. moduleSelector = $allModules.selector || '',
  2353. $module = $(this),
  2354. $title = $module.find(selector.title),
  2355. $content = $module.find(selector.content),
  2356. element = this,
  2357. instance = $module.data(moduleNamespace),
  2358. observer,
  2359. module
  2360. ;
  2361. module = {
  2362. initialize: function() {
  2363. module.debug('Initializing', $module);
  2364. module.bind.events();
  2365. if(settings.observeChanges) {
  2366. module.observeChanges();
  2367. }
  2368. module.instantiate();
  2369. },
  2370. instantiate: function() {
  2371. instance = module;
  2372. $module
  2373. .data(moduleNamespace, module)
  2374. ;
  2375. },
  2376. destroy: function() {
  2377. module.debug('Destroying previous instance', $module);
  2378. $module
  2379. .off(eventNamespace)
  2380. .removeData(moduleNamespace)
  2381. ;
  2382. },
  2383. refresh: function() {
  2384. $title = $module.find(selector.title);
  2385. $content = $module.find(selector.content);
  2386. },
  2387. observeChanges: function() {
  2388. if('MutationObserver' in window) {
  2389. observer = new MutationObserver(function(mutations) {
  2390. module.debug('DOM tree modified, updating selector cache');
  2391. module.refresh();
  2392. });
  2393. observer.observe(element, {
  2394. childList : true,
  2395. subtree : true
  2396. });
  2397. module.debug('Setting up mutation observer', observer);
  2398. }
  2399. },
  2400. bind: {
  2401. events: function() {
  2402. module.debug('Binding delegated events');
  2403. $module
  2404. .on(settings.on + eventNamespace, selector.trigger, module.event.click)
  2405. ;
  2406. }
  2407. },
  2408. event: {
  2409. click: function() {
  2410. module.toggle.call(this);
  2411. }
  2412. },
  2413. toggle: function(query) {
  2414. var
  2415. $activeTitle = (query !== undefined)
  2416. ? (typeof query === 'number')
  2417. ? $title.eq(query)
  2418. : $(query).closest(selector.title)
  2419. : $(this).closest(selector.title),
  2420. $activeContent = $activeTitle.next($content),
  2421. isAnimating = $activeContent.hasClass(className.animating),
  2422. isActive = $activeContent.hasClass(className.active),
  2423. isOpen = (isActive && !isAnimating),
  2424. isOpening = (!isActive && isAnimating)
  2425. ;
  2426. module.debug('Toggling visibility of content', $activeTitle);
  2427. if(isOpen || isOpening) {
  2428. if(settings.collapsible) {
  2429. module.close.call($activeTitle);
  2430. }
  2431. else {
  2432. module.debug('Cannot close accordion content collapsing is disabled');
  2433. }
  2434. }
  2435. else {
  2436. module.open.call($activeTitle);
  2437. }
  2438. },
  2439. open: function(query) {
  2440. var
  2441. $activeTitle = (query !== undefined)
  2442. ? (typeof query === 'number')
  2443. ? $title.eq(query)
  2444. : $(query).closest(selector.title)
  2445. : $(this).closest(selector.title),
  2446. $activeContent = $activeTitle.next($content),
  2447. isAnimating = $activeContent.hasClass(className.animating),
  2448. isActive = $activeContent.hasClass(className.active),
  2449. isOpen = (isActive || isAnimating)
  2450. ;
  2451. if(isOpen) {
  2452. module.debug('Accordion already open, skipping', $activeContent);
  2453. return;
  2454. }
  2455. module.debug('Opening accordion content', $activeTitle);
  2456. settings.onOpening.call($activeContent);
  2457. settings.onChanging.call($activeContent);
  2458. if(settings.exclusive) {
  2459. module.closeOthers.call($activeTitle);
  2460. }
  2461. $activeTitle
  2462. .addClass(className.active)
  2463. ;
  2464. $activeContent
  2465. .stop(true, true)
  2466. .addClass(className.animating)
  2467. ;
  2468. if(settings.animateChildren) {
  2469. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2470. $activeContent
  2471. .children()
  2472. .transition({
  2473. animation : 'fade in',
  2474. queue : false,
  2475. useFailSafe : true,
  2476. debug : settings.debug,
  2477. verbose : settings.verbose,
  2478. duration : settings.duration,
  2479. skipInlineHidden : true,
  2480. onComplete: function() {
  2481. $activeContent.children().removeClass(className.transition);
  2482. }
  2483. })
  2484. ;
  2485. }
  2486. else {
  2487. $activeContent
  2488. .children()
  2489. .stop(true, true)
  2490. .animate({
  2491. opacity: 1
  2492. }, settings.duration, module.resetOpacity)
  2493. ;
  2494. }
  2495. }
  2496. $activeContent
  2497. .slideDown(settings.duration, settings.easing, function() {
  2498. $activeContent
  2499. .removeClass(className.animating)
  2500. .addClass(className.active)
  2501. ;
  2502. module.reset.display.call(this);
  2503. settings.onOpen.call(this);
  2504. settings.onChange.call(this);
  2505. })
  2506. ;
  2507. },
  2508. close: function(query) {
  2509. var
  2510. $activeTitle = (query !== undefined)
  2511. ? (typeof query === 'number')
  2512. ? $title.eq(query)
  2513. : $(query).closest(selector.title)
  2514. : $(this).closest(selector.title),
  2515. $activeContent = $activeTitle.next($content),
  2516. isAnimating = $activeContent.hasClass(className.animating),
  2517. isActive = $activeContent.hasClass(className.active),
  2518. isOpening = (!isActive && isAnimating),
  2519. isClosing = (isActive && isAnimating)
  2520. ;
  2521. if((isActive || isOpening) && !isClosing) {
  2522. module.debug('Closing accordion content', $activeContent);
  2523. settings.onClosing.call($activeContent);
  2524. settings.onChanging.call($activeContent);
  2525. $activeTitle
  2526. .removeClass(className.active)
  2527. ;
  2528. $activeContent
  2529. .stop(true, true)
  2530. .addClass(className.animating)
  2531. ;
  2532. if(settings.animateChildren) {
  2533. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2534. $activeContent
  2535. .children()
  2536. .transition({
  2537. animation : 'fade out',
  2538. queue : false,
  2539. useFailSafe : true,
  2540. debug : settings.debug,
  2541. verbose : settings.verbose,
  2542. duration : settings.duration,
  2543. skipInlineHidden : true
  2544. })
  2545. ;
  2546. }
  2547. else {
  2548. $activeContent
  2549. .children()
  2550. .stop(true, true)
  2551. .animate({
  2552. opacity: 0
  2553. }, settings.duration, module.resetOpacity)
  2554. ;
  2555. }
  2556. }
  2557. $activeContent
  2558. .slideUp(settings.duration, settings.easing, function() {
  2559. $activeContent
  2560. .removeClass(className.animating)
  2561. .removeClass(className.active)
  2562. ;
  2563. module.reset.display.call(this);
  2564. settings.onClose.call(this);
  2565. settings.onChange.call(this);
  2566. })
  2567. ;
  2568. }
  2569. },
  2570. closeOthers: function(index) {
  2571. var
  2572. $activeTitle = (index !== undefined)
  2573. ? $title.eq(index)
  2574. : $(this).closest(selector.title),
  2575. $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
  2576. $activeAccordion = $activeTitle.closest(selector.accordion),
  2577. activeSelector = selector.title + '.' + className.active + ':visible',
  2578. activeContent = selector.content + '.' + className.active + ':visible',
  2579. $openTitles,
  2580. $nestedTitles,
  2581. $openContents
  2582. ;
  2583. if(settings.closeNested) {
  2584. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2585. $openContents = $openTitles.next($content);
  2586. }
  2587. else {
  2588. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2589. $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
  2590. $openTitles = $openTitles.not($nestedTitles);
  2591. $openContents = $openTitles.next($content);
  2592. }
  2593. if( ($openTitles.length > 0) ) {
  2594. module.debug('Exclusive enabled, closing other content', $openTitles);
  2595. $openTitles
  2596. .removeClass(className.active)
  2597. ;
  2598. $openContents
  2599. .removeClass(className.animating)
  2600. .stop(true, true)
  2601. ;
  2602. if(settings.animateChildren) {
  2603. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2604. $openContents
  2605. .children()
  2606. .transition({
  2607. animation : 'fade out',
  2608. useFailSafe : true,
  2609. debug : settings.debug,
  2610. verbose : settings.verbose,
  2611. duration : settings.duration,
  2612. skipInlineHidden : true
  2613. })
  2614. ;
  2615. }
  2616. else {
  2617. $openContents
  2618. .children()
  2619. .stop(true, true)
  2620. .animate({
  2621. opacity: 0
  2622. }, settings.duration, module.resetOpacity)
  2623. ;
  2624. }
  2625. }
  2626. $openContents
  2627. .slideUp(settings.duration , settings.easing, function() {
  2628. $(this).removeClass(className.active);
  2629. module.reset.display.call(this);
  2630. })
  2631. ;
  2632. }
  2633. },
  2634. reset: {
  2635. display: function() {
  2636. module.verbose('Removing inline display from element', this);
  2637. $(this).css('display', '');
  2638. if( $(this).attr('style') === '') {
  2639. $(this)
  2640. .attr('style', '')
  2641. .removeAttr('style')
  2642. ;
  2643. }
  2644. },
  2645. opacity: function() {
  2646. module.verbose('Removing inline opacity from element', this);
  2647. $(this).css('opacity', '');
  2648. if( $(this).attr('style') === '') {
  2649. $(this)
  2650. .attr('style', '')
  2651. .removeAttr('style')
  2652. ;
  2653. }
  2654. },
  2655. },
  2656. setting: function(name, value) {
  2657. module.debug('Changing setting', name, value);
  2658. if( $.isPlainObject(name) ) {
  2659. $.extend(true, settings, name);
  2660. }
  2661. else if(value !== undefined) {
  2662. if($.isPlainObject(settings[name])) {
  2663. $.extend(true, settings[name], value);
  2664. }
  2665. else {
  2666. settings[name] = value;
  2667. }
  2668. }
  2669. else {
  2670. return settings[name];
  2671. }
  2672. },
  2673. internal: function(name, value) {
  2674. module.debug('Changing internal', name, value);
  2675. if(value !== undefined) {
  2676. if( $.isPlainObject(name) ) {
  2677. $.extend(true, module, name);
  2678. }
  2679. else {
  2680. module[name] = value;
  2681. }
  2682. }
  2683. else {
  2684. return module[name];
  2685. }
  2686. },
  2687. debug: function() {
  2688. if(!settings.silent && settings.debug) {
  2689. if(settings.performance) {
  2690. module.performance.log(arguments);
  2691. }
  2692. else {
  2693. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2694. module.debug.apply(console, arguments);
  2695. }
  2696. }
  2697. },
  2698. verbose: function() {
  2699. if(!settings.silent && settings.verbose && settings.debug) {
  2700. if(settings.performance) {
  2701. module.performance.log(arguments);
  2702. }
  2703. else {
  2704. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2705. module.verbose.apply(console, arguments);
  2706. }
  2707. }
  2708. },
  2709. error: function() {
  2710. if(!settings.silent) {
  2711. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  2712. module.error.apply(console, arguments);
  2713. }
  2714. },
  2715. performance: {
  2716. log: function(message) {
  2717. var
  2718. currentTime,
  2719. executionTime,
  2720. previousTime
  2721. ;
  2722. if(settings.performance) {
  2723. currentTime = new Date().getTime();
  2724. previousTime = time || currentTime;
  2725. executionTime = currentTime - previousTime;
  2726. time = currentTime;
  2727. performance.push({
  2728. 'Name' : message[0],
  2729. 'Arguments' : [].slice.call(message, 1) || '',
  2730. 'Element' : element,
  2731. 'Execution Time' : executionTime
  2732. });
  2733. }
  2734. clearTimeout(module.performance.timer);
  2735. module.performance.timer = setTimeout(module.performance.display, 500);
  2736. },
  2737. display: function() {
  2738. var
  2739. title = settings.name + ':',
  2740. totalTime = 0
  2741. ;
  2742. time = false;
  2743. clearTimeout(module.performance.timer);
  2744. $.each(performance, function(index, data) {
  2745. totalTime += data['Execution Time'];
  2746. });
  2747. title += ' ' + totalTime + 'ms';
  2748. if(moduleSelector) {
  2749. title += ' \'' + moduleSelector + '\'';
  2750. }
  2751. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  2752. console.groupCollapsed(title);
  2753. if(console.table) {
  2754. console.table(performance);
  2755. }
  2756. else {
  2757. $.each(performance, function(index, data) {
  2758. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  2759. });
  2760. }
  2761. console.groupEnd();
  2762. }
  2763. performance = [];
  2764. }
  2765. },
  2766. invoke: function(query, passedArguments, context) {
  2767. var
  2768. object = instance,
  2769. maxDepth,
  2770. found,
  2771. response
  2772. ;
  2773. passedArguments = passedArguments || queryArguments;
  2774. context = element || context;
  2775. if(typeof query == 'string' && object !== undefined) {
  2776. query = query.split(/[\. ]/);
  2777. maxDepth = query.length - 1;
  2778. $.each(query, function(depth, value) {
  2779. var camelCaseValue = (depth != maxDepth)
  2780. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  2781. : query
  2782. ;
  2783. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  2784. object = object[camelCaseValue];
  2785. }
  2786. else if( object[camelCaseValue] !== undefined ) {
  2787. found = object[camelCaseValue];
  2788. return false;
  2789. }
  2790. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  2791. object = object[value];
  2792. }
  2793. else if( object[value] !== undefined ) {
  2794. found = object[value];
  2795. return false;
  2796. }
  2797. else {
  2798. module.error(error.method, query);
  2799. return false;
  2800. }
  2801. });
  2802. }
  2803. if ( $.isFunction( found ) ) {
  2804. response = found.apply(context, passedArguments);
  2805. }
  2806. else if(found !== undefined) {
  2807. response = found;
  2808. }
  2809. if(Array.isArray(returnedValue)) {
  2810. returnedValue.push(response);
  2811. }
  2812. else if(returnedValue !== undefined) {
  2813. returnedValue = [returnedValue, response];
  2814. }
  2815. else if(response !== undefined) {
  2816. returnedValue = response;
  2817. }
  2818. return found;
  2819. }
  2820. };
  2821. if(methodInvoked) {
  2822. if(instance === undefined) {
  2823. module.initialize();
  2824. }
  2825. module.invoke(query);
  2826. }
  2827. else {
  2828. if(instance !== undefined) {
  2829. instance.invoke('destroy');
  2830. }
  2831. module.initialize();
  2832. }
  2833. })
  2834. ;
  2835. return (returnedValue !== undefined)
  2836. ? returnedValue
  2837. : this
  2838. ;
  2839. };
  2840. $.fn.accordion.settings = {
  2841. name : 'Accordion',
  2842. namespace : 'accordion',
  2843. silent : false,
  2844. debug : false,
  2845. verbose : false,
  2846. performance : true,
  2847. on : 'click', // event on title that opens accordion
  2848. observeChanges : true, // whether accordion should automatically refresh on DOM insertion
  2849. exclusive : true, // whether a single accordion content panel should be open at once
  2850. collapsible : true, // whether accordion content can be closed
  2851. closeNested : false, // whether nested content should be closed when a panel is closed
  2852. animateChildren : true, // whether children opacity should be animated
  2853. duration : 350, // duration of animation
  2854. easing : 'easeOutQuad', // easing equation for animation
  2855. onOpening : function(){}, // callback before open animation
  2856. onClosing : function(){}, // callback before closing animation
  2857. onChanging : function(){}, // callback before closing or opening animation
  2858. onOpen : function(){}, // callback after open animation
  2859. onClose : function(){}, // callback after closing animation
  2860. onChange : function(){}, // callback after closing or opening animation
  2861. error: {
  2862. method : 'The method you called is not defined'
  2863. },
  2864. className : {
  2865. active : 'active',
  2866. animating : 'animating',
  2867. transition: 'transition'
  2868. },
  2869. selector : {
  2870. accordion : '.accordion',
  2871. title : '.title',
  2872. trigger : '.title',
  2873. content : '.content'
  2874. }
  2875. };
  2876. // Adds easing
  2877. $.extend( $.easing, {
  2878. easeOutQuad: function (x, t, b, c, d) {
  2879. return -c *(t/=d)*(t-2) + b;
  2880. }
  2881. });
  2882. })( jQuery, window, document );
  2883. /*!
  2884. * # Fomantic-UI - Calendar
  2885. * http://github.com/fomantic/Fomantic-UI/
  2886. *
  2887. *
  2888. * Released under the MIT license
  2889. * http://opensource.org/licenses/MIT
  2890. *
  2891. */
  2892. ;(function ($, window, document, undefined) {
  2893. 'use strict';
  2894. $.isFunction = $.isFunction || function(obj) {
  2895. return typeof obj === "function" && typeof obj.nodeType !== "number";
  2896. };
  2897. window = (typeof window != 'undefined' && window.Math == Math)
  2898. ? window
  2899. : (typeof self != 'undefined' && self.Math == Math)
  2900. ? self
  2901. : Function('return this')()
  2902. ;
  2903. $.fn.calendar = function(parameters) {
  2904. var
  2905. $allModules = $(this),
  2906. moduleSelector = $allModules.selector || '',
  2907. time = new Date().getTime(),
  2908. performance = [],
  2909. query = arguments[0],
  2910. methodInvoked = (typeof query == 'string'),
  2911. queryArguments = [].slice.call(arguments, 1),
  2912. returnedValue,
  2913. timeGapTable = {
  2914. '5': {'row': 4, 'column': 3 },
  2915. '10': {'row': 3, 'column': 2 },
  2916. '15': {'row': 2, 'column': 2 },
  2917. '20': {'row': 3, 'column': 1 },
  2918. '30': {'row': 2, 'column': 1 }
  2919. }
  2920. ;
  2921. $allModules
  2922. .each(function () {
  2923. var
  2924. settings = ( $.isPlainObject(parameters) )
  2925. ? $.extend(true, {}, $.fn.calendar.settings, parameters)
  2926. : $.extend({}, $.fn.calendar.settings),
  2927. className = settings.className,
  2928. namespace = settings.namespace,
  2929. selector = settings.selector,
  2930. formatter = settings.formatter,
  2931. parser = settings.parser,
  2932. metadata = settings.metadata,
  2933. timeGap = timeGapTable[settings.minTimeGap],
  2934. error = settings.error,
  2935. eventNamespace = '.' + namespace,
  2936. moduleNamespace = 'module-' + namespace,
  2937. $module = $(this),
  2938. $input = $module.find(selector.input),
  2939. $container = $module.find(selector.popup),
  2940. $activator = $module.find(selector.activator),
  2941. element = this,
  2942. instance = $module.data(moduleNamespace),
  2943. isTouch,
  2944. isTouchDown = false,
  2945. focusDateUsedForRange = false,
  2946. module
  2947. ;
  2948. module = {
  2949. initialize: function () {
  2950. module.debug('Initializing calendar for', element, $module);
  2951. isTouch = module.get.isTouch();
  2952. module.setup.config();
  2953. module.setup.popup();
  2954. module.setup.inline();
  2955. module.setup.input();
  2956. module.setup.date();
  2957. module.create.calendar();
  2958. module.bind.events();
  2959. module.instantiate();
  2960. },
  2961. instantiate: function () {
  2962. module.verbose('Storing instance of calendar');
  2963. instance = module;
  2964. $module.data(moduleNamespace, instance);
  2965. },
  2966. destroy: function () {
  2967. module.verbose('Destroying previous calendar for', element);
  2968. $module.removeData(moduleNamespace);
  2969. module.unbind.events();
  2970. },
  2971. setup: {
  2972. config: function () {
  2973. if (module.get.minDate() !== null) {
  2974. module.set.minDate($module.data(metadata.minDate));
  2975. }
  2976. if (module.get.maxDate() !== null) {
  2977. module.set.maxDate($module.data(metadata.maxDate));
  2978. }
  2979. module.setting('type', module.get.type());
  2980. },
  2981. popup: function () {
  2982. if (settings.inline) {
  2983. return;
  2984. }
  2985. if (!$activator.length) {
  2986. $activator = $module.children().first();
  2987. if (!$activator.length) {
  2988. return;
  2989. }
  2990. }
  2991. if ($.fn.popup === undefined) {
  2992. module.error(error.popup);
  2993. return;
  2994. }
  2995. if (!$container.length) {
  2996. //prepend the popup element to the activator's parent so that it has less chance of messing with
  2997. //the styling (eg input action button needs to be the last child to have correct border radius)
  2998. var $activatorParent = $activator.parent(),
  2999. domPositionFunction = $activatorParent.closest(selector.append).length !== 0 ? 'appendTo' : 'prependTo';
  3000. $container = $('<div/>').addClass(className.popup)[domPositionFunction]($activatorParent);
  3001. }
  3002. $container.addClass(className.calendar);
  3003. var onVisible = settings.onVisible;
  3004. var onHidden = settings.onHidden;
  3005. if (!$input.length) {
  3006. //no input, $container has to handle focus/blur
  3007. $container.attr('tabindex', '0');
  3008. onVisible = function () {
  3009. module.focus();
  3010. return settings.onVisible.apply($container, arguments);
  3011. };
  3012. onHidden = function () {
  3013. module.blur();
  3014. return settings.onHidden.apply($container, arguments);
  3015. };
  3016. }
  3017. var onShow = function () {
  3018. //reset the focus date onShow
  3019. module.set.focusDate(module.get.date());
  3020. module.set.mode(settings.startMode);
  3021. return settings.onShow.apply($container, arguments);
  3022. };
  3023. var on = settings.on || ($input.length ? 'focus' : 'click');
  3024. var options = $.extend({}, settings.popupOptions, {
  3025. popup: $container,
  3026. on: on,
  3027. hoverable: on === 'hover',
  3028. onShow: onShow,
  3029. onVisible: onVisible,
  3030. onHide: settings.onHide,
  3031. onHidden: onHidden
  3032. });
  3033. module.popup(options);
  3034. },
  3035. inline: function () {
  3036. if ($activator.length && !settings.inline) {
  3037. return;
  3038. }
  3039. $container = $('<div/>').addClass(className.calendar).appendTo($module);
  3040. if (!$input.length) {
  3041. $container.attr('tabindex', '0');
  3042. }
  3043. },
  3044. input: function () {
  3045. if (settings.touchReadonly && $input.length && isTouch) {
  3046. $input.prop('readonly', true);
  3047. }
  3048. },
  3049. date: function () {
  3050. var date;
  3051. if (settings.initialDate) {
  3052. date = parser.date(settings.initialDate, settings);
  3053. } else if ($module.data(metadata.date) !== undefined) {
  3054. date = parser.date($module.data(metadata.date), settings);
  3055. } else if ($input.length) {
  3056. date = parser.date($input.val(), settings);
  3057. }
  3058. module.set.date(date, settings.formatInput, false);
  3059. }
  3060. },
  3061. create: {
  3062. calendar: function () {
  3063. var i, r, c, p, row, cell, pageGrid;
  3064. var mode = module.get.mode();
  3065. var today = new Date();
  3066. var date = module.get.date();
  3067. var focusDate = module.get.focusDate();
  3068. var display = focusDate || date || settings.initialDate || today;
  3069. display = module.helper.dateInRange(display);
  3070. if (!focusDate) {
  3071. focusDate = display;
  3072. module.set.focusDate(focusDate, false, false);
  3073. }
  3074. var isYear = mode === 'year';
  3075. var isMonth = mode === 'month';
  3076. var isDay = mode === 'day';
  3077. var isHour = mode === 'hour';
  3078. var isMinute = mode === 'minute';
  3079. var isTimeOnly = settings.type === 'time';
  3080. var multiMonth = Math.max(settings.multiMonth, 1);
  3081. var monthOffset = !isDay ? 0 : module.get.monthOffset();
  3082. var minute = display.getMinutes();
  3083. var hour = display.getHours();
  3084. var day = display.getDate();
  3085. var startMonth = display.getMonth() + monthOffset;
  3086. var year = display.getFullYear();
  3087. var columns = isDay ? settings.showWeekNumbers ? 8 : 7 : isHour ? 4 : timeGap['column'];
  3088. var rows = isDay || isHour ? 6 : timeGap['row'];
  3089. var pages = isDay ? multiMonth : 1;
  3090. var container = $container;
  3091. var tooltipPosition = container.hasClass("left") ? "right center" : "left center";
  3092. container.empty();
  3093. if (pages > 1) {
  3094. pageGrid = $('<div/>').addClass(className.grid).appendTo(container);
  3095. }
  3096. for (p = 0; p < pages; p++) {
  3097. if (pages > 1) {
  3098. var pageColumn = $('<div/>').addClass(className.column).appendTo(pageGrid);
  3099. container = pageColumn;
  3100. }
  3101. var month = startMonth + p;
  3102. var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
  3103. if (!settings.constantHeight && isDay) {
  3104. var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
  3105. rows = Math.ceil(requiredCells / 7);
  3106. }
  3107. var yearChange = isYear ? 10 : isMonth ? 1 : 0;
  3108. var monthChange = isDay ? 1 : 0;
  3109. var dayChange = isHour || isMinute ? 1 : 0;
  3110. var prevNextDay = isHour || isMinute ? day : 1;
  3111. var prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour);
  3112. var nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour);
  3113. var prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) :
  3114. isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1);
  3115. var nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) :
  3116. isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1);
  3117. var tempMode = mode;
  3118. if (isDay && settings.showWeekNumbers){
  3119. tempMode += ' andweek';
  3120. }
  3121. var table = $('<table/>').addClass(className.table).addClass(tempMode).appendTo(container);
  3122. var textColumns = columns;
  3123. //no header for time-only mode
  3124. if (!isTimeOnly) {
  3125. var thead = $('<thead/>').appendTo(table);
  3126. row = $('<tr/>').appendTo(thead);
  3127. cell = $('<th/>').attr('colspan', '' + columns).appendTo(row);
  3128. var headerDate = isYear || isMonth ? new Date(year, 0, 1) :
  3129. isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute);
  3130. var headerText = $('<span/>').addClass(className.link).appendTo(cell);
  3131. headerText.text(formatter.header(headerDate, mode, settings));
  3132. var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') :
  3133. isDay ? (settings.disableMonth ? 'year' : 'month') : 'day';
  3134. headerText.data(metadata.mode, newMode);
  3135. if (p === 0) {
  3136. var prev = $('<span/>').addClass(className.prev).appendTo(cell);
  3137. prev.data(metadata.focusDate, prevDate);
  3138. prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
  3139. $('<i/>').addClass(className.prevIcon).appendTo(prev);
  3140. }
  3141. if (p === pages - 1) {
  3142. var next = $('<span/>').addClass(className.next).appendTo(cell);
  3143. next.data(metadata.focusDate, nextDate);
  3144. next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
  3145. $('<i/>').addClass(className.nextIcon).appendTo(next);
  3146. }
  3147. if (isDay) {
  3148. row = $('<tr/>').appendTo(thead);
  3149. if(settings.showWeekNumbers) {
  3150. cell = $('<th/>').appendTo(row);
  3151. cell.text(settings.text.weekNo);
  3152. cell.addClass(className.weekCell);
  3153. textColumns--;
  3154. }
  3155. for (i = 0; i < textColumns; i++) {
  3156. cell = $('<th/>').appendTo(row);
  3157. cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
  3158. }
  3159. }
  3160. }
  3161. var tbody = $('<tbody/>').appendTo(table);
  3162. i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
  3163. for (r = 0; r < rows; r++) {
  3164. row = $('<tr/>').appendTo(tbody);
  3165. if(isDay && settings.showWeekNumbers){
  3166. cell = $('<th/>').appendTo(row);
  3167. cell.text(module.get.weekOfYear(year,month,i+1-settings.firstDayOfWeek));
  3168. cell.addClass(className.weekCell);
  3169. }
  3170. for (c = 0; c < textColumns; c++, i++) {
  3171. var cellDate = isYear ? new Date(i, month, 1, hour, minute) :
  3172. isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) :
  3173. isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * settings.minTimeGap);
  3174. var cellText = isYear ? i :
  3175. isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() :
  3176. formatter.time(cellDate, settings, true);
  3177. cell = $('<td/>').addClass(className.cell).appendTo(row);
  3178. cell.text(cellText);
  3179. cell.data(metadata.date, cellDate);
  3180. var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
  3181. var disabled = (!settings.selectAdjacentDays && adjacent) || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode) || module.helper.isDisabled(cellDate, mode) || !module.helper.isEnabled(cellDate, mode);
  3182. if (disabled) {
  3183. var disabledDate = module.helper.findDayAsObject(cellDate, mode, settings.disabledDates);
  3184. if (disabledDate !== null && disabledDate[metadata.message]) {
  3185. cell.attr("data-tooltip", disabledDate[metadata.message]);
  3186. cell.attr("data-position", tooltipPosition);
  3187. }
  3188. } else {
  3189. var eventDate = module.helper.findDayAsObject(cellDate, mode, settings.eventDates);
  3190. if (eventDate !== null) {
  3191. cell.addClass(eventDate[metadata.class] || settings.eventClass);
  3192. if (eventDate[metadata.message]) {
  3193. cell.attr("data-tooltip", eventDate[metadata.message]);
  3194. cell.attr("data-position", tooltipPosition);
  3195. }
  3196. }
  3197. }
  3198. var active = module.helper.dateEqual(cellDate, date, mode);
  3199. var isToday = module.helper.dateEqual(cellDate, today, mode);
  3200. cell.toggleClass(className.adjacentCell, adjacent);
  3201. cell.toggleClass(className.disabledCell, disabled);
  3202. cell.toggleClass(className.activeCell, active && !adjacent);
  3203. if (!isHour && !isMinute) {
  3204. cell.toggleClass(className.todayCell, !adjacent && isToday);
  3205. }
  3206. // Allow for external modifications of each cell
  3207. var cellOptions = {
  3208. mode: mode,
  3209. adjacent: adjacent,
  3210. disabled: disabled,
  3211. active: active,
  3212. today: isToday
  3213. };
  3214. formatter.cell(cell, cellDate, cellOptions);
  3215. if (module.helper.dateEqual(cellDate, focusDate, mode)) {
  3216. //ensure that the focus date is exactly equal to the cell date
  3217. //so that, if selected, the correct value is set
  3218. module.set.focusDate(cellDate, false, false);
  3219. }
  3220. }
  3221. }
  3222. if (settings.today) {
  3223. var todayRow = $('<tr/>').appendTo(tbody);
  3224. var todayButton = $('<td/>').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
  3225. todayButton.text(formatter.today(settings));
  3226. todayButton.data(metadata.date, today);
  3227. }
  3228. module.update.focus(false, table);
  3229. }
  3230. }
  3231. },
  3232. update: {
  3233. focus: function (updateRange, container) {
  3234. container = container || $container;
  3235. var mode = module.get.mode();
  3236. var date = module.get.date();
  3237. var focusDate = module.get.focusDate();
  3238. var startDate = module.get.startDate();
  3239. var endDate = module.get.endDate();
  3240. var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
  3241. container.find('td').each(function () {
  3242. var cell = $(this);
  3243. var cellDate = cell.data(metadata.date);
  3244. if (!cellDate) {
  3245. return;
  3246. }
  3247. var disabled = cell.hasClass(className.disabledCell);
  3248. var active = cell.hasClass(className.activeCell);
  3249. var adjacent = cell.hasClass(className.adjacentCell);
  3250. var focused = module.helper.dateEqual(cellDate, focusDate, mode);
  3251. var inRange = !rangeDate ? false :
  3252. ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) ||
  3253. (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
  3254. cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && (!adjacent || (settings.selectAdjacentDays && adjacent)) && !disabled);
  3255. if (module.helper.isTodayButton(cell)) {
  3256. return;
  3257. }
  3258. cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
  3259. });
  3260. }
  3261. },
  3262. refresh: function () {
  3263. module.create.calendar();
  3264. },
  3265. bind: {
  3266. events: function () {
  3267. module.debug('Binding events');
  3268. $container.on('mousedown' + eventNamespace, module.event.mousedown);
  3269. $container.on('touchstart' + eventNamespace, module.event.mousedown);
  3270. $container.on('mouseup' + eventNamespace, module.event.mouseup);
  3271. $container.on('touchend' + eventNamespace, module.event.mouseup);
  3272. $container.on('mouseover' + eventNamespace, module.event.mouseover);
  3273. if ($input.length) {
  3274. $input.on('input' + eventNamespace, module.event.inputChange);
  3275. $input.on('focus' + eventNamespace, module.event.inputFocus);
  3276. $input.on('blur' + eventNamespace, module.event.inputBlur);
  3277. $input.on('click' + eventNamespace, module.event.inputClick);
  3278. $input.on('keydown' + eventNamespace, module.event.keydown);
  3279. } else {
  3280. $container.on('keydown' + eventNamespace, module.event.keydown);
  3281. }
  3282. }
  3283. },
  3284. unbind: {
  3285. events: function () {
  3286. module.debug('Unbinding events');
  3287. $container.off(eventNamespace);
  3288. if ($input.length) {
  3289. $input.off(eventNamespace);
  3290. }
  3291. }
  3292. },
  3293. event: {
  3294. mouseover: function (event) {
  3295. var target = $(event.target);
  3296. var date = target.data(metadata.date);
  3297. var mousedown = event.buttons === 1;
  3298. if (date) {
  3299. module.set.focusDate(date, false, true, mousedown);
  3300. }
  3301. },
  3302. mousedown: function (event) {
  3303. if ($input.length) {
  3304. //prevent the mousedown on the calendar causing the input to lose focus
  3305. event.preventDefault();
  3306. }
  3307. isTouchDown = event.type.indexOf('touch') >= 0;
  3308. var target = $(event.target);
  3309. var date = target.data(metadata.date);
  3310. if (date) {
  3311. module.set.focusDate(date, false, true, true);
  3312. }
  3313. },
  3314. mouseup: function (event) {
  3315. //ensure input has focus so that it receives keydown events for calendar navigation
  3316. module.focus();
  3317. event.preventDefault();
  3318. event.stopPropagation();
  3319. isTouchDown = false;
  3320. var target = $(event.target);
  3321. if (target.hasClass("disabled")) {
  3322. return;
  3323. }
  3324. var parent = target.parent();
  3325. if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
  3326. //clicked on a child element, switch to parent (used when clicking directly on prev/next <i> icon element)
  3327. target = parent;
  3328. }
  3329. var date = target.data(metadata.date);
  3330. var focusDate = target.data(metadata.focusDate);
  3331. var mode = target.data(metadata.mode);
  3332. if (date && settings.onSelect.call(element, date, module.get.mode()) !== false) {
  3333. var forceSet = target.hasClass(className.today);
  3334. module.selectDate(date, forceSet);
  3335. }
  3336. else if (focusDate) {
  3337. module.set.focusDate(focusDate);
  3338. }
  3339. else if (mode) {
  3340. module.set.mode(mode);
  3341. }
  3342. },
  3343. keydown: function (event) {
  3344. var keyCode = event.which;
  3345. if (keyCode === 27 || keyCode === 9) {
  3346. //esc || tab
  3347. module.popup('hide');
  3348. }
  3349. if (module.popup('is visible')) {
  3350. if (keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
  3351. //arrow keys
  3352. var mode = module.get.mode();
  3353. var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : mode === 'minute' ? timeGap['column'] : 3;
  3354. var increment = keyCode === 37 ? -1 : keyCode === 38 ? -bigIncrement : keyCode == 39 ? 1 : bigIncrement;
  3355. increment *= mode === 'minute' ? settings.minTimeGap : 1;
  3356. var focusDate = module.get.focusDate() || module.get.date() || new Date();
  3357. var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
  3358. var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
  3359. var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
  3360. var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
  3361. var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
  3362. var newFocusDate = new Date(year, month, day, hour, minute);
  3363. if (settings.type === 'time') {
  3364. newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
  3365. }
  3366. if (module.helper.isDateInRange(newFocusDate, mode)) {
  3367. module.set.focusDate(newFocusDate);
  3368. }
  3369. } else if (keyCode === 13) {
  3370. //enter
  3371. var mode = module.get.mode();
  3372. var date = module.get.focusDate();
  3373. if (date && !settings.isDisabled(date, mode) && !module.helper.isDisabled(date, mode) && module.helper.isEnabled(date, mode)) {
  3374. module.selectDate(date);
  3375. }
  3376. //disable form submission:
  3377. event.preventDefault();
  3378. event.stopPropagation();
  3379. }
  3380. }
  3381. if (keyCode === 38 || keyCode === 40) {
  3382. //arrow-up || arrow-down
  3383. event.preventDefault(); //don't scroll
  3384. module.popup('show');
  3385. }
  3386. },
  3387. inputChange: function () {
  3388. var val = $input.val();
  3389. var date = parser.date(val, settings);
  3390. module.set.date(date, false);
  3391. },
  3392. inputFocus: function () {
  3393. $container.addClass(className.active);
  3394. },
  3395. inputBlur: function () {
  3396. $container.removeClass(className.active);
  3397. if (settings.formatInput) {
  3398. var date = module.get.date();
  3399. var text = formatter.datetime(date, settings);
  3400. $input.val(text);
  3401. }
  3402. },
  3403. inputClick: function () {
  3404. module.popup('show');
  3405. }
  3406. },
  3407. get: {
  3408. weekOfYear: function(weekYear,weekMonth,weekDay) {
  3409. // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
  3410. var ms1d = 864e5, // milliseconds in a day
  3411. ms7d = 7 * ms1d; // milliseconds in a week
  3412. return function() { // return a closure so constants get calculated only once
  3413. var DC3 = Date.UTC(weekYear, weekMonth, weekDay + 3) / ms1d, // an Absolute Day Number
  3414. AWN = Math.floor(DC3 / 7), // an Absolute Week Number
  3415. Wyr = new Date(AWN * ms7d).getUTCFullYear();
  3416. return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
  3417. }();
  3418. },
  3419. date: function () {
  3420. return module.helper.sanitiseDate($module.data(metadata.date)) || null;
  3421. },
  3422. inputDate: function() {
  3423. return $input.val();
  3424. },
  3425. focusDate: function () {
  3426. return $module.data(metadata.focusDate) || null;
  3427. },
  3428. startDate: function () {
  3429. var startModule = module.get.calendarModule(settings.startCalendar);
  3430. return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
  3431. },
  3432. endDate: function () {
  3433. var endModule = module.get.calendarModule(settings.endCalendar);
  3434. return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
  3435. },
  3436. minDate: function() {
  3437. return $module.data(metadata.minDate) || null;
  3438. },
  3439. maxDate: function() {
  3440. return $module.data(metadata.maxDate) || null;
  3441. },
  3442. monthOffset: function () {
  3443. return $module.data(metadata.monthOffset) || 0;
  3444. },
  3445. mode: function () {
  3446. //only returns valid modes for the current settings
  3447. var mode = $module.data(metadata.mode) || settings.startMode;
  3448. var validModes = module.get.validModes();
  3449. if ($.inArray(mode, validModes) >= 0) {
  3450. return mode;
  3451. }
  3452. return settings.type === 'time' ? 'hour' :
  3453. settings.type === 'month' ? 'month' :
  3454. settings.type === 'year' ? 'year' : 'day';
  3455. },
  3456. type: function() {
  3457. return $module.data(metadata.type) || settings.type;
  3458. },
  3459. validModes: function () {
  3460. var validModes = [];
  3461. if (settings.type !== 'time') {
  3462. if (!settings.disableYear || settings.type === 'year') {
  3463. validModes.push('year');
  3464. }
  3465. if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
  3466. validModes.push('month');
  3467. }
  3468. if (settings.type.indexOf('date') >= 0) {
  3469. validModes.push('day');
  3470. }
  3471. }
  3472. if (settings.type.indexOf('time') >= 0) {
  3473. validModes.push('hour');
  3474. if (!settings.disableMinute) {
  3475. validModes.push('minute');
  3476. }
  3477. }
  3478. return validModes;
  3479. },
  3480. isTouch: function () {
  3481. try {
  3482. document.createEvent('TouchEvent');
  3483. return true;
  3484. }
  3485. catch (e) {
  3486. return false;
  3487. }
  3488. },
  3489. calendarModule: function (selector) {
  3490. if (!selector) {
  3491. return null;
  3492. }
  3493. if (!(selector instanceof $)) {
  3494. selector = $(selector).first();
  3495. }
  3496. //assume range related calendars are using the same namespace
  3497. return selector.data(moduleNamespace);
  3498. }
  3499. },
  3500. set: {
  3501. date: function (date, updateInput, fireChange) {
  3502. updateInput = updateInput !== false;
  3503. fireChange = fireChange !== false;
  3504. date = module.helper.sanitiseDate(date);
  3505. date = module.helper.dateInRange(date);
  3506. var mode = module.get.mode();
  3507. var text = formatter.datetime(date, settings);
  3508. if (fireChange && settings.onBeforeChange.call(element, date, text, mode) === false) {
  3509. return false;
  3510. }
  3511. module.set.focusDate(date);
  3512. if (settings.isDisabled(date, mode)) {
  3513. return false;
  3514. }
  3515. var endDate = module.get.endDate();
  3516. if (!!endDate && !!date && date > endDate) {
  3517. //selected date is greater than end date in range, so clear end date
  3518. module.set.endDate(undefined);
  3519. }
  3520. module.set.dataKeyValue(metadata.date, date);
  3521. if (updateInput && $input.length) {
  3522. $input.val(text);
  3523. }
  3524. if (fireChange) {
  3525. settings.onChange.call(element, date, text, mode);
  3526. }
  3527. },
  3528. startDate: function (date, refreshCalendar) {
  3529. date = module.helper.sanitiseDate(date);
  3530. var startModule = module.get.calendarModule(settings.startCalendar);
  3531. if (startModule) {
  3532. startModule.set.date(date);
  3533. }
  3534. module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
  3535. },
  3536. endDate: function (date, refreshCalendar) {
  3537. date = module.helper.sanitiseDate(date);
  3538. var endModule = module.get.calendarModule(settings.endCalendar);
  3539. if (endModule) {
  3540. endModule.set.date(date);
  3541. }
  3542. module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
  3543. },
  3544. focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
  3545. date = module.helper.sanitiseDate(date);
  3546. date = module.helper.dateInRange(date);
  3547. var isDay = module.get.mode() === 'day';
  3548. var oldFocusDate = module.get.focusDate();
  3549. if (isDay && date && oldFocusDate) {
  3550. var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
  3551. var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
  3552. if (monthDelta) {
  3553. var monthOffset = module.get.monthOffset() - monthDelta;
  3554. module.set.monthOffset(monthOffset, false);
  3555. }
  3556. }
  3557. var changed = module.set.dataKeyValue(metadata.focusDate, date, refreshCalendar);
  3558. updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
  3559. focusDateUsedForRange = updateRange;
  3560. if (updateFocus) {
  3561. module.update.focus(updateRange);
  3562. }
  3563. },
  3564. minDate: function (date) {
  3565. date = module.helper.sanitiseDate(date);
  3566. if (settings.maxDate !== null && settings.maxDate <= date) {
  3567. module.verbose('Unable to set minDate variable bigger that maxDate variable', date, settings.maxDate);
  3568. } else {
  3569. module.setting('minDate', date);
  3570. module.set.dataKeyValue(metadata.minDate, date);
  3571. }
  3572. },
  3573. maxDate: function (date) {
  3574. date = module.helper.sanitiseDate(date);
  3575. if (settings.minDate !== null && settings.minDate >= date) {
  3576. module.verbose('Unable to set maxDate variable lower that minDate variable', date, settings.minDate);
  3577. } else {
  3578. module.setting('maxDate', date);
  3579. module.set.dataKeyValue(metadata.maxDate, date);
  3580. }
  3581. },
  3582. monthOffset: function (monthOffset, refreshCalendar) {
  3583. var multiMonth = Math.max(settings.multiMonth, 1);
  3584. monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
  3585. module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
  3586. },
  3587. mode: function (mode, refreshCalendar) {
  3588. module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
  3589. },
  3590. dataKeyValue: function (key, value, refreshCalendar) {
  3591. var oldValue = $module.data(key);
  3592. var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects
  3593. if (value) {
  3594. $module.data(key, value);
  3595. } else {
  3596. $module.removeData(key);
  3597. }
  3598. refreshCalendar = refreshCalendar !== false && !equal;
  3599. if (refreshCalendar) {
  3600. module.refresh();
  3601. }
  3602. return !equal;
  3603. }
  3604. },
  3605. selectDate: function (date, forceSet) {
  3606. module.verbose('New date selection', date);
  3607. var mode = module.get.mode();
  3608. var complete = forceSet || mode === 'minute' ||
  3609. (settings.disableMinute && mode === 'hour') ||
  3610. (settings.type === 'date' && mode === 'day') ||
  3611. (settings.type === 'month' && mode === 'month') ||
  3612. (settings.type === 'year' && mode === 'year');
  3613. if (complete) {
  3614. var canceled = module.set.date(date) === false;
  3615. if (!canceled && settings.closable) {
  3616. module.popup('hide');
  3617. //if this is a range calendar, show the end date calendar popup and focus the input
  3618. var endModule = module.get.calendarModule(settings.endCalendar);
  3619. if (endModule) {
  3620. endModule.popup('show');
  3621. endModule.focus();
  3622. }
  3623. }
  3624. } else {
  3625. var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') :
  3626. mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute';
  3627. module.set.mode(newMode);
  3628. if (mode === 'hour' || (mode === 'day' && module.get.date())) {
  3629. //the user has chosen enough to consider a valid date/time has been chosen
  3630. module.set.date(date);
  3631. } else {
  3632. module.set.focusDate(date);
  3633. }
  3634. }
  3635. },
  3636. changeDate: function (date) {
  3637. module.set.date(date);
  3638. },
  3639. clear: function () {
  3640. module.set.date(undefined);
  3641. },
  3642. popup: function () {
  3643. return $activator.popup.apply($activator, arguments);
  3644. },
  3645. focus: function () {
  3646. if ($input.length) {
  3647. $input.focus();
  3648. } else {
  3649. $container.focus();
  3650. }
  3651. },
  3652. blur: function () {
  3653. if ($input.length) {
  3654. $input.blur();
  3655. } else {
  3656. $container.blur();
  3657. }
  3658. },
  3659. helper: {
  3660. isDisabled: function(date, mode) {
  3661. return mode === 'day' && ((settings.disabledDaysOfWeek.indexOf(date.getDay()) !== -1) || settings.disabledDates.some(function(d){
  3662. if(typeof d === 'string') {
  3663. d = module.helper.sanitiseDate(d);
  3664. }
  3665. if (d instanceof Date) {
  3666. return module.helper.dateEqual(date, d, mode);
  3667. }
  3668. if (d !== null && typeof d === 'object' && d[metadata.date]) {
  3669. return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
  3670. }
  3671. }));
  3672. },
  3673. isEnabled: function(date, mode) {
  3674. if (mode === 'day') {
  3675. return settings.enabledDates.length === 0 || settings.enabledDates.some(function(d){
  3676. if(typeof d === 'string') {
  3677. d = module.helper.sanitiseDate(d);
  3678. }
  3679. if (d instanceof Date) {
  3680. return module.helper.dateEqual(date, d, mode);
  3681. }
  3682. if (d !== null && typeof d === 'object' && d[metadata.date]) {
  3683. return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
  3684. }
  3685. });
  3686. } else {
  3687. return true;
  3688. }
  3689. },
  3690. findDayAsObject: function(date, mode, dates) {
  3691. if (mode === 'day') {
  3692. var i = 0, il = dates.length;
  3693. var d;
  3694. for (; i < il; i++) {
  3695. d = dates[i];
  3696. if(typeof d === 'string') {
  3697. d = module.helper.sanitiseDate(d);
  3698. }
  3699. if (d instanceof Date && module.helper.dateEqual(date, d, mode)) {
  3700. var dateObject = {};
  3701. dateObject[metadata.date] = d;
  3702. return dateObject;
  3703. }
  3704. else if (d !== null && typeof d === 'object' && d[metadata.date] && module.helper.dateEqual(date,module.helper.sanitiseDate(d[metadata.date]), mode) ) {
  3705. return d;
  3706. }
  3707. }
  3708. }
  3709. return null;
  3710. },
  3711. sanitiseDate: function (date) {
  3712. if (!date) {
  3713. return undefined;
  3714. }
  3715. if (!(date instanceof Date)) {
  3716. date = parser.date('' + date, settings);
  3717. }
  3718. if (!date || date === null || isNaN(date.getTime())) {
  3719. return undefined;
  3720. }
  3721. return date;
  3722. },
  3723. dateDiff: function (date1, date2, mode) {
  3724. mode = mode || 'day';
  3725. var isTimeOnly = settings.type === 'time';
  3726. var isYear = mode === 'year';
  3727. var isYearOrMonth = isYear || mode === 'month';
  3728. var isMinute = mode === 'minute';
  3729. var isHourOrMinute = isMinute || mode === 'hour';
  3730. //only care about a minute accuracy of settings.minTimeGap
  3731. date1 = new Date(
  3732. isTimeOnly ? 2000 : date1.getFullYear(),
  3733. isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
  3734. isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
  3735. !isHourOrMinute ? 0 : date1.getHours(),
  3736. !isMinute ? 0 : settings.minTimeGap * Math.floor(date1.getMinutes() / settings.minTimeGap));
  3737. date2 = new Date(
  3738. isTimeOnly ? 2000 : date2.getFullYear(),
  3739. isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
  3740. isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
  3741. !isHourOrMinute ? 0 : date2.getHours(),
  3742. !isMinute ? 0 : settings.minTimeGap * Math.floor(date2.getMinutes() / settings.minTimeGap));
  3743. return date2.getTime() - date1.getTime();
  3744. },
  3745. dateEqual: function (date1, date2, mode) {
  3746. return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
  3747. },
  3748. isDateInRange: function (date, mode, minDate, maxDate) {
  3749. if (!minDate && !maxDate) {
  3750. var startDate = module.get.startDate();
  3751. minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
  3752. maxDate = settings.maxDate;
  3753. }
  3754. minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
  3755. return !(!date ||
  3756. (minDate && module.helper.dateDiff(date, minDate, mode) > 0) ||
  3757. (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
  3758. },
  3759. dateInRange: function (date, minDate, maxDate) {
  3760. if (!minDate && !maxDate) {
  3761. var startDate = module.get.startDate();
  3762. minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
  3763. maxDate = settings.maxDate;
  3764. }
  3765. minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
  3766. var isTimeOnly = settings.type === 'time';
  3767. return !date ? date :
  3768. (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ?
  3769. (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) :
  3770. (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ?
  3771. (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) :
  3772. date;
  3773. },
  3774. mergeDateTime: function (date, time) {
  3775. return (!date || !time) ? time :
  3776. new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
  3777. },
  3778. isTodayButton: function(element) {
  3779. return element.text() === settings.text.today;
  3780. }
  3781. },
  3782. setting: function (name, value) {
  3783. module.debug('Changing setting', name, value);
  3784. if ($.isPlainObject(name)) {
  3785. $.extend(true, settings, name);
  3786. }
  3787. else if (value !== undefined) {
  3788. if ($.isPlainObject(settings[name])) {
  3789. $.extend(true, settings[name], value);
  3790. }
  3791. else {
  3792. settings[name] = value;
  3793. }
  3794. }
  3795. else {
  3796. return settings[name];
  3797. }
  3798. },
  3799. internal: function (name, value) {
  3800. if( $.isPlainObject(name) ) {
  3801. $.extend(true, module, name);
  3802. }
  3803. else if(value !== undefined) {
  3804. module[name] = value;
  3805. }
  3806. else {
  3807. return module[name];
  3808. }
  3809. },
  3810. debug: function () {
  3811. if (!settings.silent && settings.debug) {
  3812. if (settings.performance) {
  3813. module.performance.log(arguments);
  3814. }
  3815. else {
  3816. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3817. module.debug.apply(console, arguments);
  3818. }
  3819. }
  3820. },
  3821. verbose: function () {
  3822. if (!settings.silent && settings.verbose && settings.debug) {
  3823. if (settings.performance) {
  3824. module.performance.log(arguments);
  3825. }
  3826. else {
  3827. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3828. module.verbose.apply(console, arguments);
  3829. }
  3830. }
  3831. },
  3832. error: function () {
  3833. if (!settings.silent) {
  3834. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3835. module.error.apply(console, arguments);
  3836. }
  3837. },
  3838. performance: {
  3839. log: function (message) {
  3840. var
  3841. currentTime,
  3842. executionTime,
  3843. previousTime
  3844. ;
  3845. if (settings.performance) {
  3846. currentTime = new Date().getTime();
  3847. previousTime = time || currentTime;
  3848. executionTime = currentTime - previousTime;
  3849. time = currentTime;
  3850. performance.push({
  3851. 'Name': message[0],
  3852. 'Arguments': [].slice.call(message, 1) || '',
  3853. 'Element': element,
  3854. 'Execution Time': executionTime
  3855. });
  3856. }
  3857. clearTimeout(module.performance.timer);
  3858. module.performance.timer = setTimeout(module.performance.display, 500);
  3859. },
  3860. display: function () {
  3861. var
  3862. title = settings.name + ':',
  3863. totalTime = 0
  3864. ;
  3865. time = false;
  3866. clearTimeout(module.performance.timer);
  3867. $.each(performance, function (index, data) {
  3868. totalTime += data['Execution Time'];
  3869. });
  3870. title += ' ' + totalTime + 'ms';
  3871. if (moduleSelector) {
  3872. title += ' \'' + moduleSelector + '\'';
  3873. }
  3874. if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3875. console.groupCollapsed(title);
  3876. if (console.table) {
  3877. console.table(performance);
  3878. }
  3879. else {
  3880. $.each(performance, function (index, data) {
  3881. console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
  3882. });
  3883. }
  3884. console.groupEnd();
  3885. }
  3886. performance = [];
  3887. }
  3888. },
  3889. invoke: function (query, passedArguments, context) {
  3890. var
  3891. object = instance,
  3892. maxDepth,
  3893. found,
  3894. response
  3895. ;
  3896. passedArguments = passedArguments || queryArguments;
  3897. context = element || context;
  3898. if (typeof query == 'string' && object !== undefined) {
  3899. query = query.split(/[\. ]/);
  3900. maxDepth = query.length - 1;
  3901. $.each(query, function (depth, value) {
  3902. var camelCaseValue = (depth != maxDepth)
  3903. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3904. : query
  3905. ;
  3906. if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
  3907. object = object[camelCaseValue];
  3908. }
  3909. else if (object[camelCaseValue] !== undefined) {
  3910. found = object[camelCaseValue];
  3911. return false;
  3912. }
  3913. else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
  3914. object = object[value];
  3915. }
  3916. else if (object[value] !== undefined) {
  3917. found = object[value];
  3918. return false;
  3919. }
  3920. else {
  3921. module.error(error.method, query);
  3922. return false;
  3923. }
  3924. });
  3925. }
  3926. if ($.isFunction(found)) {
  3927. response = found.apply(context, passedArguments);
  3928. }
  3929. else if (found !== undefined) {
  3930. response = found;
  3931. }
  3932. if (Array.isArray(returnedValue)) {
  3933. returnedValue.push(response);
  3934. }
  3935. else if (returnedValue !== undefined) {
  3936. returnedValue = [returnedValue, response];
  3937. }
  3938. else if (response !== undefined) {
  3939. returnedValue = response;
  3940. }
  3941. return found;
  3942. }
  3943. };
  3944. if (methodInvoked) {
  3945. if (instance === undefined) {
  3946. module.initialize();
  3947. }
  3948. module.invoke(query);
  3949. }
  3950. else {
  3951. if (instance !== undefined) {
  3952. instance.invoke('destroy');
  3953. }
  3954. module.initialize();
  3955. }
  3956. })
  3957. ;
  3958. return (returnedValue !== undefined)
  3959. ? returnedValue
  3960. : this
  3961. ;
  3962. };
  3963. $.fn.calendar.settings = {
  3964. name : 'Calendar',
  3965. namespace : 'calendar',
  3966. silent: false,
  3967. debug: false,
  3968. verbose: false,
  3969. performance: false,
  3970. type : 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
  3971. firstDayOfWeek : 0, // day for first day column (0 = Sunday)
  3972. constantHeight : true, // add rows to shorter months to keep day calendar height consistent (6 rows)
  3973. today : false, // show a 'today/now' button at the bottom of the calendar
  3974. closable : true, // close the popup after selecting a date/time
  3975. monthFirst : true, // month before day when parsing/converting date from/to text
  3976. touchReadonly : true, // set input to readonly on touch devices
  3977. inline : false, // create the calendar inline instead of inside a popup
  3978. on : null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
  3979. initialDate : null, // date to display initially when no date is selected (null = now)
  3980. startMode : false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
  3981. minDate : null, // minimum date/time that can be selected, dates/times before are disabled
  3982. maxDate : null, // maximum date/time that can be selected, dates/times after are disabled
  3983. ampm : true, // show am/pm in time mode
  3984. disableYear : false, // disable year selection mode
  3985. disableMonth : false, // disable month selection mode
  3986. disableMinute : false, // disable minute selection mode
  3987. formatInput : true, // format the input text upon input blur and module creation
  3988. startCalendar : null, // jquery object or selector for another calendar that represents the start date of a date range
  3989. endCalendar : null, // jquery object or selector for another calendar that represents the end date of a date range
  3990. multiMonth : 1, // show multiple months when in 'day' mode
  3991. minTimeGap : 5,
  3992. showWeekNumbers : null, // show Number of Week at the very first column of a dayView
  3993. disabledDates : [], // specific day(s) which won't be selectable and contain additional information.
  3994. disabledDaysOfWeek : [], // day(s) which won't be selectable(s) (0 = Sunday)
  3995. enabledDates : [], // specific day(s) which will be selectable, all other days will be disabled
  3996. eventDates : [], // specific day(s) which will be shown in a different color and using tooltips
  3997. centuryBreak : 60, // starting short year until 99 where it will be assumed to belong to the last century
  3998. currentCentury : 2000, // century to be added to 2-digit years (00 to {centuryBreak}-1)
  3999. selectAdjacentDays : false, // The calendar can show dates from adjacent month. These adjacent month dates can also be made selectable.
  4000. // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
  4001. popupOptions: {
  4002. position: 'bottom left',
  4003. lastResort: 'bottom left',
  4004. prefer: 'opposite',
  4005. hideOnScroll: false
  4006. },
  4007. text: {
  4008. days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
  4009. months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  4010. monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  4011. today: 'Today',
  4012. now: 'Now',
  4013. am: 'AM',
  4014. pm: 'PM',
  4015. weekNo: 'Week'
  4016. },
  4017. formatter: {
  4018. header: function (date, mode, settings) {
  4019. return mode === 'year' ? settings.formatter.yearHeader(date, settings) :
  4020. mode === 'month' ? settings.formatter.monthHeader(date, settings) :
  4021. mode === 'day' ? settings.formatter.dayHeader(date, settings) :
  4022. mode === 'hour' ? settings.formatter.hourHeader(date, settings) :
  4023. settings.formatter.minuteHeader(date, settings);
  4024. },
  4025. yearHeader: function (date, settings) {
  4026. var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
  4027. return (decadeYear - 9) + ' - ' + (decadeYear + 2);
  4028. },
  4029. monthHeader: function (date, settings) {
  4030. return date.getFullYear();
  4031. },
  4032. dayHeader: function (date, settings) {
  4033. var month = settings.text.months[date.getMonth()];
  4034. var year = date.getFullYear();
  4035. return month + ' ' + year;
  4036. },
  4037. hourHeader: function (date, settings) {
  4038. return settings.formatter.date(date, settings);
  4039. },
  4040. minuteHeader: function (date, settings) {
  4041. return settings.formatter.date(date, settings);
  4042. },
  4043. dayColumnHeader: function (day, settings) {
  4044. return settings.text.days[day];
  4045. },
  4046. datetime: function (date, settings) {
  4047. if (!date) {
  4048. return '';
  4049. }
  4050. var day = settings.type === 'time' ? '' : settings.formatter.date(date, settings);
  4051. var time = settings.type.indexOf('time') < 0 ? '' : settings.formatter.time(date, settings, false);
  4052. var separator = settings.type === 'datetime' ? ' ' : '';
  4053. return day + separator + time;
  4054. },
  4055. date: function (date, settings) {
  4056. if (!date) {
  4057. return '';
  4058. }
  4059. var day = date.getDate();
  4060. var month = settings.text.months[date.getMonth()];
  4061. var year = date.getFullYear();
  4062. return settings.type === 'year' ? year :
  4063. settings.type === 'month' ? month + ' ' + year :
  4064. (settings.monthFirst ? month + ' ' + day : day + ' ' + month) + ', ' + year;
  4065. },
  4066. time: function (date, settings, forCalendar) {
  4067. if (!date) {
  4068. return '';
  4069. }
  4070. var hour = date.getHours();
  4071. var minute = date.getMinutes();
  4072. var ampm = '';
  4073. if (settings.ampm) {
  4074. ampm = ' ' + (hour < 12 ? settings.text.am : settings.text.pm);
  4075. hour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
  4076. }
  4077. return hour + ':' + (minute < 10 ? '0' : '') + minute + ampm;
  4078. },
  4079. today: function (settings) {
  4080. return settings.type === 'date' ? settings.text.today : settings.text.now;
  4081. },
  4082. cell: function (cell, date, cellOptions) {
  4083. }
  4084. },
  4085. parser: {
  4086. date: function (text, settings) {
  4087. if (text instanceof Date) {
  4088. return text;
  4089. }
  4090. if (!text) {
  4091. return null;
  4092. }
  4093. text = ('' + text).trim().toLowerCase();
  4094. if (text.length === 0) {
  4095. return null;
  4096. }
  4097. // Reverse date and month in some cases
  4098. text = settings.monthFirst ? text : text.replace(/[\/\-\.]/g,'/').replace(/([0-9]+)\/([0-9]+)/,'$2/$1');
  4099. var textDate = new Date(text);
  4100. if(!isNaN(textDate.getDate())) {
  4101. return textDate;
  4102. }
  4103. var i, j, k;
  4104. var minute = -1, hour = -1, day = -1, month = -1, year = -1;
  4105. var isAm = undefined;
  4106. var isTimeOnly = settings.type === 'time';
  4107. var isDateOnly = settings.type.indexOf('time') < 0;
  4108. var words = text.split(settings.regExp.dateWords), word;
  4109. var numbers = text.split(settings.regExp.dateNumbers), number;
  4110. var parts;
  4111. var monthString;
  4112. if (!isDateOnly) {
  4113. //am/pm
  4114. isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true :
  4115. $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
  4116. //time with ':'
  4117. for (i = 0; i < numbers.length; i++) {
  4118. number = numbers[i];
  4119. if (number.indexOf(':') >= 0) {
  4120. if (hour < 0 || minute < 0) {
  4121. parts = number.split(':');
  4122. for (k = 0; k < Math.min(2, parts.length); k++) {
  4123. j = parseInt(parts[k]);
  4124. if (isNaN(j)) {
  4125. j = 0;
  4126. }
  4127. if (k === 0) {
  4128. hour = j % 24;
  4129. } else {
  4130. minute = j % 60;
  4131. }
  4132. }
  4133. }
  4134. numbers.splice(i, 1);
  4135. }
  4136. }
  4137. }
  4138. if (!isTimeOnly) {
  4139. //textual month
  4140. for (i = 0; i < words.length; i++) {
  4141. word = words[i];
  4142. if (word.length <= 0) {
  4143. continue;
  4144. }
  4145. for (j = 0; j < settings.text.months.length; j++) {
  4146. monthString = settings.text.months[j];
  4147. monthString = monthString.substring(0, word.length).toLowerCase();
  4148. if (monthString === word) {
  4149. month = j + 1;
  4150. break;
  4151. }
  4152. }
  4153. if (month >= 0) {
  4154. break;
  4155. }
  4156. }
  4157. //year > settings.centuryBreak
  4158. for (i = 0; i < numbers.length; i++) {
  4159. j = parseInt(numbers[i]);
  4160. if (isNaN(j)) {
  4161. continue;
  4162. }
  4163. if (j >= settings.centuryBreak && i === numbers.length-1) {
  4164. if (j <= 99) {
  4165. j += settings.currentCentury - 100;
  4166. }
  4167. year = j;
  4168. numbers.splice(i, 1);
  4169. break;
  4170. }
  4171. }
  4172. //numeric month
  4173. if (month < 0) {
  4174. for (i = 0; i < numbers.length; i++) {
  4175. k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
  4176. j = parseInt(numbers[k]);
  4177. if (isNaN(j)) {
  4178. continue;
  4179. }
  4180. if (1 <= j && j <= 12) {
  4181. month = j;
  4182. numbers.splice(k, 1);
  4183. break;
  4184. }
  4185. }
  4186. }
  4187. //day
  4188. for (i = 0; i < numbers.length; i++) {
  4189. j = parseInt(numbers[i]);
  4190. if (isNaN(j)) {
  4191. continue;
  4192. }
  4193. if (1 <= j && j <= 31) {
  4194. day = j;
  4195. numbers.splice(i, 1);
  4196. break;
  4197. }
  4198. }
  4199. //year <= settings.centuryBreak
  4200. if (year < 0) {
  4201. for (i = numbers.length - 1; i >= 0; i--) {
  4202. j = parseInt(numbers[i]);
  4203. if (isNaN(j)) {
  4204. continue;
  4205. }
  4206. if (j <= 99) {
  4207. j += settings.currentCentury;
  4208. }
  4209. year = j;
  4210. numbers.splice(i, 1);
  4211. break;
  4212. }
  4213. }
  4214. }
  4215. if (!isDateOnly) {
  4216. //hour
  4217. if (hour < 0) {
  4218. for (i = 0; i < numbers.length; i++) {
  4219. j = parseInt(numbers[i]);
  4220. if (isNaN(j)) {
  4221. continue;
  4222. }
  4223. if (0 <= j && j <= 23) {
  4224. hour = j;
  4225. numbers.splice(i, 1);
  4226. break;
  4227. }
  4228. }
  4229. }
  4230. //minute
  4231. if (minute < 0) {
  4232. for (i = 0; i < numbers.length; i++) {
  4233. j = parseInt(numbers[i]);
  4234. if (isNaN(j)) {
  4235. continue;
  4236. }
  4237. if (0 <= j && j <= 59) {
  4238. minute = j;
  4239. numbers.splice(i, 1);
  4240. break;
  4241. }
  4242. }
  4243. }
  4244. }
  4245. if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
  4246. return null;
  4247. }
  4248. if (minute < 0) {
  4249. minute = 0;
  4250. }
  4251. if (hour < 0) {
  4252. hour = 0;
  4253. }
  4254. if (day < 0) {
  4255. day = 1;
  4256. }
  4257. if (month < 0) {
  4258. month = 1;
  4259. }
  4260. if (year < 0) {
  4261. year = new Date().getFullYear();
  4262. }
  4263. if (isAm !== undefined) {
  4264. if (isAm) {
  4265. if (hour === 12) {
  4266. hour = 0;
  4267. }
  4268. } else if (hour < 12) {
  4269. hour += 12;
  4270. }
  4271. }
  4272. var date = new Date(year, month - 1, day, hour, minute);
  4273. if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
  4274. //month or year don't match up, switch to last day of the month
  4275. date = new Date(year, month, 0, hour, minute);
  4276. }
  4277. return isNaN(date.getTime()) ? null : date;
  4278. }
  4279. },
  4280. // callback before date is changed, return false to cancel the change
  4281. onBeforeChange: function (date, text, mode) {
  4282. return true;
  4283. },
  4284. // callback when date changes
  4285. onChange: function (date, text, mode) {
  4286. },
  4287. // callback before show animation, return false to prevent show
  4288. onShow: function () {
  4289. },
  4290. // callback after show animation
  4291. onVisible: function () {
  4292. },
  4293. // callback before hide animation, return false to prevent hide
  4294. onHide: function () {
  4295. },
  4296. // callback after hide animation
  4297. onHidden: function () {
  4298. },
  4299. // callback before item is selected, return false to prevent selection
  4300. onSelect: function (date, mode) {
  4301. },
  4302. // is the given date disabled?
  4303. isDisabled: function (date, mode) {
  4304. return false;
  4305. },
  4306. selector: {
  4307. popup: '.ui.popup',
  4308. input: 'input',
  4309. activator: 'input',
  4310. append: '.inline.field,.inline.fields'
  4311. },
  4312. regExp: {
  4313. dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
  4314. dateNumbers: /[^\d:]+/g
  4315. },
  4316. error: {
  4317. popup: 'UI Popup, a required component is not included in this page',
  4318. method: 'The method you called is not defined.'
  4319. },
  4320. className: {
  4321. calendar: 'calendar',
  4322. active: 'active',
  4323. popup: 'ui popup',
  4324. grid: 'ui equal width grid',
  4325. column: 'column',
  4326. table: 'ui celled center aligned unstackable table',
  4327. prev: 'prev link',
  4328. next: 'next link',
  4329. prevIcon: 'chevron left icon',
  4330. nextIcon: 'chevron right icon',
  4331. link: 'link',
  4332. cell: 'link',
  4333. disabledCell: 'disabled',
  4334. weekCell: 'disabled',
  4335. adjacentCell: 'adjacent',
  4336. activeCell: 'active',
  4337. rangeCell: 'range',
  4338. focusCell: 'focus',
  4339. todayCell: 'today',
  4340. today: 'today link'
  4341. },
  4342. metadata: {
  4343. date: 'date',
  4344. focusDate: 'focusDate',
  4345. startDate: 'startDate',
  4346. endDate: 'endDate',
  4347. minDate: 'minDate',
  4348. maxDate: 'maxDate',
  4349. mode: 'mode',
  4350. type: 'type',
  4351. monthOffset: 'monthOffset',
  4352. message: 'message',
  4353. class: 'class'
  4354. },
  4355. eventClass: 'blue'
  4356. };
  4357. })(jQuery, window, document);
  4358. /*!
  4359. * # Fomantic-UI - Checkbox
  4360. * http://github.com/fomantic/Fomantic-UI/
  4361. *
  4362. *
  4363. * Released under the MIT license
  4364. * http://opensource.org/licenses/MIT
  4365. *
  4366. */
  4367. ;(function ($, window, document, undefined) {
  4368. 'use strict';
  4369. $.isFunction = $.isFunction || function(obj) {
  4370. return typeof obj === "function" && typeof obj.nodeType !== "number";
  4371. };
  4372. window = (typeof window != 'undefined' && window.Math == Math)
  4373. ? window
  4374. : (typeof self != 'undefined' && self.Math == Math)
  4375. ? self
  4376. : Function('return this')()
  4377. ;
  4378. $.fn.checkbox = function(parameters) {
  4379. var
  4380. $allModules = $(this),
  4381. moduleSelector = $allModules.selector || '',
  4382. time = new Date().getTime(),
  4383. performance = [],
  4384. query = arguments[0],
  4385. methodInvoked = (typeof query == 'string'),
  4386. queryArguments = [].slice.call(arguments, 1),
  4387. returnedValue
  4388. ;
  4389. $allModules
  4390. .each(function() {
  4391. var
  4392. settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
  4393. className = settings.className,
  4394. namespace = settings.namespace,
  4395. selector = settings.selector,
  4396. error = settings.error,
  4397. eventNamespace = '.' + namespace,
  4398. moduleNamespace = 'module-' + namespace,
  4399. $module = $(this),
  4400. $label = $(this).children(selector.label),
  4401. $input = $(this).children(selector.input),
  4402. input = $input[0],
  4403. initialLoad = false,
  4404. shortcutPressed = false,
  4405. instance = $module.data(moduleNamespace),
  4406. observer,
  4407. element = this,
  4408. module
  4409. ;
  4410. module = {
  4411. initialize: function() {
  4412. module.verbose('Initializing checkbox', settings);
  4413. module.create.label();
  4414. module.bind.events();
  4415. module.set.tabbable();
  4416. module.hide.input();
  4417. module.observeChanges();
  4418. module.instantiate();
  4419. module.setup();
  4420. },
  4421. instantiate: function() {
  4422. module.verbose('Storing instance of module', module);
  4423. instance = module;
  4424. $module
  4425. .data(moduleNamespace, module)
  4426. ;
  4427. },
  4428. destroy: function() {
  4429. module.verbose('Destroying module');
  4430. module.unbind.events();
  4431. module.show.input();
  4432. $module.removeData(moduleNamespace);
  4433. },
  4434. fix: {
  4435. reference: function() {
  4436. if( $module.is(selector.input) ) {
  4437. module.debug('Behavior called on <input> adjusting invoked element');
  4438. $module = $module.closest(selector.checkbox);
  4439. module.refresh();
  4440. }
  4441. }
  4442. },
  4443. setup: function() {
  4444. module.set.initialLoad();
  4445. if( module.is.indeterminate() ) {
  4446. module.debug('Initial value is indeterminate');
  4447. module.indeterminate();
  4448. }
  4449. else if( module.is.checked() ) {
  4450. module.debug('Initial value is checked');
  4451. module.check();
  4452. }
  4453. else {
  4454. module.debug('Initial value is unchecked');
  4455. module.uncheck();
  4456. }
  4457. module.remove.initialLoad();
  4458. },
  4459. refresh: function() {
  4460. $label = $module.children(selector.label);
  4461. $input = $module.children(selector.input);
  4462. input = $input[0];
  4463. },
  4464. hide: {
  4465. input: function() {
  4466. module.verbose('Modifying <input> z-index to be unselectable');
  4467. $input.addClass(className.hidden);
  4468. }
  4469. },
  4470. show: {
  4471. input: function() {
  4472. module.verbose('Modifying <input> z-index to be selectable');
  4473. $input.removeClass(className.hidden);
  4474. }
  4475. },
  4476. observeChanges: function() {
  4477. if('MutationObserver' in window) {
  4478. observer = new MutationObserver(function(mutations) {
  4479. module.debug('DOM tree modified, updating selector cache');
  4480. module.refresh();
  4481. });
  4482. observer.observe(element, {
  4483. childList : true,
  4484. subtree : true
  4485. });
  4486. module.debug('Setting up mutation observer', observer);
  4487. }
  4488. },
  4489. attachEvents: function(selector, event) {
  4490. var
  4491. $element = $(selector)
  4492. ;
  4493. event = $.isFunction(module[event])
  4494. ? module[event]
  4495. : module.toggle
  4496. ;
  4497. if($element.length > 0) {
  4498. module.debug('Attaching checkbox events to element', selector, event);
  4499. $element
  4500. .on('click' + eventNamespace, event)
  4501. ;
  4502. }
  4503. else {
  4504. module.error(error.notFound);
  4505. }
  4506. },
  4507. preventDefaultOnInputTarget: function() {
  4508. if(typeof event !== 'undefined' && $(event.target).is(selector.input)) {
  4509. module.verbose('Preventing default check action after manual check action');
  4510. event.preventDefault();
  4511. }
  4512. },
  4513. event: {
  4514. change: function(event) {
  4515. if( !module.should.ignoreCallbacks() ) {
  4516. settings.onChange.call(input);
  4517. }
  4518. },
  4519. click: function(event) {
  4520. var
  4521. $target = $(event.target)
  4522. ;
  4523. if( $target.is(selector.input) ) {
  4524. module.verbose('Using default check action on initialized checkbox');
  4525. return;
  4526. }
  4527. if( $target.is(selector.link) ) {
  4528. module.debug('Clicking link inside checkbox, skipping toggle');
  4529. return;
  4530. }
  4531. module.toggle();
  4532. $input.focus();
  4533. event.preventDefault();
  4534. },
  4535. keydown: function(event) {
  4536. var
  4537. key = event.which,
  4538. keyCode = {
  4539. enter : 13,
  4540. space : 32,
  4541. escape : 27,
  4542. left : 37,
  4543. up : 38,
  4544. right : 39,
  4545. down : 40
  4546. }
  4547. ;
  4548. var r = module.get.radios(),
  4549. rIndex = r.index($module),
  4550. rLen = r.length,
  4551. checkIndex = false;
  4552. if(key == keyCode.left || key == keyCode.up) {
  4553. checkIndex = (rIndex === 0 ? rLen : rIndex) - 1;
  4554. } else if(key == keyCode.right || key == keyCode.down) {
  4555. checkIndex = rIndex === rLen-1 ? 0 : rIndex+1;
  4556. }
  4557. if (!module.should.ignoreCallbacks() && checkIndex !== false) {
  4558. if(settings.beforeUnchecked.apply(input)===false) {
  4559. module.verbose('Option not allowed to be unchecked, cancelling key navigation');
  4560. return false;
  4561. }
  4562. if (settings.beforeChecked.apply($(r[checkIndex]).children(selector.input)[0])===false) {
  4563. module.verbose('Next option should not allow check, cancelling key navigation');
  4564. return false;
  4565. }
  4566. }
  4567. if(key == keyCode.escape) {
  4568. module.verbose('Escape key pressed blurring field');
  4569. $input.blur();
  4570. shortcutPressed = true;
  4571. }
  4572. else if(!event.ctrlKey && ( key == keyCode.space || (key == keyCode.enter && settings.enableEnterKey)) ) {
  4573. module.verbose('Enter/space key pressed, toggling checkbox');
  4574. module.toggle();
  4575. shortcutPressed = true;
  4576. }
  4577. else {
  4578. shortcutPressed = false;
  4579. }
  4580. },
  4581. keyup: function(event) {
  4582. if(shortcutPressed) {
  4583. event.preventDefault();
  4584. }
  4585. }
  4586. },
  4587. check: function() {
  4588. if( !module.should.allowCheck() ) {
  4589. return;
  4590. }
  4591. module.debug('Checking checkbox', $input);
  4592. module.set.checked();
  4593. if( !module.should.ignoreCallbacks() ) {
  4594. settings.onChecked.call(input);
  4595. module.trigger.change();
  4596. }
  4597. module.preventDefaultOnInputTarget();
  4598. },
  4599. uncheck: function() {
  4600. if( !module.should.allowUncheck() ) {
  4601. return;
  4602. }
  4603. module.debug('Unchecking checkbox');
  4604. module.set.unchecked();
  4605. if( !module.should.ignoreCallbacks() ) {
  4606. settings.onUnchecked.call(input);
  4607. module.trigger.change();
  4608. }
  4609. module.preventDefaultOnInputTarget();
  4610. },
  4611. indeterminate: function() {
  4612. if( module.should.allowIndeterminate() ) {
  4613. module.debug('Checkbox is already indeterminate');
  4614. return;
  4615. }
  4616. module.debug('Making checkbox indeterminate');
  4617. module.set.indeterminate();
  4618. if( !module.should.ignoreCallbacks() ) {
  4619. settings.onIndeterminate.call(input);
  4620. module.trigger.change();
  4621. }
  4622. },
  4623. determinate: function() {
  4624. if( module.should.allowDeterminate() ) {
  4625. module.debug('Checkbox is already determinate');
  4626. return;
  4627. }
  4628. module.debug('Making checkbox determinate');
  4629. module.set.determinate();
  4630. if( !module.should.ignoreCallbacks() ) {
  4631. settings.onDeterminate.call(input);
  4632. module.trigger.change();
  4633. }
  4634. },
  4635. enable: function() {
  4636. if( module.is.enabled() ) {
  4637. module.debug('Checkbox is already enabled');
  4638. return;
  4639. }
  4640. module.debug('Enabling checkbox');
  4641. module.set.enabled();
  4642. if( !module.should.ignoreCallbacks() ) {
  4643. settings.onEnable.call(input);
  4644. // preserve legacy callbacks
  4645. settings.onEnabled.call(input);
  4646. module.trigger.change();
  4647. }
  4648. },
  4649. disable: function() {
  4650. if( module.is.disabled() ) {
  4651. module.debug('Checkbox is already disabled');
  4652. return;
  4653. }
  4654. module.debug('Disabling checkbox');
  4655. module.set.disabled();
  4656. if( !module.should.ignoreCallbacks() ) {
  4657. settings.onDisable.call(input);
  4658. // preserve legacy callbacks
  4659. settings.onDisabled.call(input);
  4660. module.trigger.change();
  4661. }
  4662. },
  4663. get: {
  4664. radios: function() {
  4665. var
  4666. name = module.get.name()
  4667. ;
  4668. return $('input[name="' + name + '"]').closest(selector.checkbox);
  4669. },
  4670. otherRadios: function() {
  4671. return module.get.radios().not($module);
  4672. },
  4673. name: function() {
  4674. return $input.attr('name');
  4675. }
  4676. },
  4677. is: {
  4678. initialLoad: function() {
  4679. return initialLoad;
  4680. },
  4681. radio: function() {
  4682. return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
  4683. },
  4684. indeterminate: function() {
  4685. return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
  4686. },
  4687. checked: function() {
  4688. return $input.prop('checked') !== undefined && $input.prop('checked');
  4689. },
  4690. disabled: function() {
  4691. return $input.prop('disabled') !== undefined && $input.prop('disabled');
  4692. },
  4693. enabled: function() {
  4694. return !module.is.disabled();
  4695. },
  4696. determinate: function() {
  4697. return !module.is.indeterminate();
  4698. },
  4699. unchecked: function() {
  4700. return !module.is.checked();
  4701. }
  4702. },
  4703. should: {
  4704. allowCheck: function() {
  4705. if(module.is.determinate() && module.is.checked() && !module.is.initialLoad() ) {
  4706. module.debug('Should not allow check, checkbox is already checked');
  4707. return false;
  4708. }
  4709. if(!module.should.ignoreCallbacks() && settings.beforeChecked.apply(input) === false) {
  4710. module.debug('Should not allow check, beforeChecked cancelled');
  4711. return false;
  4712. }
  4713. return true;
  4714. },
  4715. allowUncheck: function() {
  4716. if(module.is.determinate() && module.is.unchecked() && !module.is.initialLoad() ) {
  4717. module.debug('Should not allow uncheck, checkbox is already unchecked');
  4718. return false;
  4719. }
  4720. if(!module.should.ignoreCallbacks() && settings.beforeUnchecked.apply(input) === false) {
  4721. module.debug('Should not allow uncheck, beforeUnchecked cancelled');
  4722. return false;
  4723. }
  4724. return true;
  4725. },
  4726. allowIndeterminate: function() {
  4727. if(module.is.indeterminate() && !module.is.initialLoad() ) {
  4728. module.debug('Should not allow indeterminate, checkbox is already indeterminate');
  4729. return false;
  4730. }
  4731. if(!module.should.ignoreCallbacks() && settings.beforeIndeterminate.apply(input) === false) {
  4732. module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
  4733. return false;
  4734. }
  4735. return true;
  4736. },
  4737. allowDeterminate: function() {
  4738. if(module.is.determinate() && !module.is.initialLoad() ) {
  4739. module.debug('Should not allow determinate, checkbox is already determinate');
  4740. return false;
  4741. }
  4742. if(!module.should.ignoreCallbacks() && settings.beforeDeterminate.apply(input) === false) {
  4743. module.debug('Should not allow determinate, beforeDeterminate cancelled');
  4744. return false;
  4745. }
  4746. return true;
  4747. },
  4748. ignoreCallbacks: function() {
  4749. return (initialLoad && !settings.fireOnInit);
  4750. }
  4751. },
  4752. can: {
  4753. change: function() {
  4754. return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
  4755. },
  4756. uncheck: function() {
  4757. return (typeof settings.uncheckable === 'boolean')
  4758. ? settings.uncheckable
  4759. : !module.is.radio()
  4760. ;
  4761. }
  4762. },
  4763. set: {
  4764. initialLoad: function() {
  4765. initialLoad = true;
  4766. },
  4767. checked: function() {
  4768. module.verbose('Setting class to checked');
  4769. $module
  4770. .removeClass(className.indeterminate)
  4771. .addClass(className.checked)
  4772. ;
  4773. if( module.is.radio() ) {
  4774. module.uncheckOthers();
  4775. }
  4776. if(!module.is.indeterminate() && module.is.checked()) {
  4777. module.debug('Input is already checked, skipping input property change');
  4778. return;
  4779. }
  4780. module.verbose('Setting state to checked', input);
  4781. $input
  4782. .prop('indeterminate', false)
  4783. .prop('checked', true)
  4784. ;
  4785. },
  4786. unchecked: function() {
  4787. module.verbose('Removing checked class');
  4788. $module
  4789. .removeClass(className.indeterminate)
  4790. .removeClass(className.checked)
  4791. ;
  4792. if(!module.is.indeterminate() && module.is.unchecked() ) {
  4793. module.debug('Input is already unchecked');
  4794. return;
  4795. }
  4796. module.debug('Setting state to unchecked');
  4797. $input
  4798. .prop('indeterminate', false)
  4799. .prop('checked', false)
  4800. ;
  4801. },
  4802. indeterminate: function() {
  4803. module.verbose('Setting class to indeterminate');
  4804. $module
  4805. .addClass(className.indeterminate)
  4806. ;
  4807. if( module.is.indeterminate() ) {
  4808. module.debug('Input is already indeterminate, skipping input property change');
  4809. return;
  4810. }
  4811. module.debug('Setting state to indeterminate');
  4812. $input
  4813. .prop('indeterminate', true)
  4814. ;
  4815. },
  4816. determinate: function() {
  4817. module.verbose('Removing indeterminate class');
  4818. $module
  4819. .removeClass(className.indeterminate)
  4820. ;
  4821. if( module.is.determinate() ) {
  4822. module.debug('Input is already determinate, skipping input property change');
  4823. return;
  4824. }
  4825. module.debug('Setting state to determinate');
  4826. $input
  4827. .prop('indeterminate', false)
  4828. ;
  4829. },
  4830. disabled: function() {
  4831. module.verbose('Setting class to disabled');
  4832. $module
  4833. .addClass(className.disabled)
  4834. ;
  4835. if( module.is.disabled() ) {
  4836. module.debug('Input is already disabled, skipping input property change');
  4837. return;
  4838. }
  4839. module.debug('Setting state to disabled');
  4840. $input
  4841. .prop('disabled', 'disabled')
  4842. ;
  4843. },
  4844. enabled: function() {
  4845. module.verbose('Removing disabled class');
  4846. $module.removeClass(className.disabled);
  4847. if( module.is.enabled() ) {
  4848. module.debug('Input is already enabled, skipping input property change');
  4849. return;
  4850. }
  4851. module.debug('Setting state to enabled');
  4852. $input
  4853. .prop('disabled', false)
  4854. ;
  4855. },
  4856. tabbable: function() {
  4857. module.verbose('Adding tabindex to checkbox');
  4858. if( $input.attr('tabindex') === undefined) {
  4859. $input.attr('tabindex', 0);
  4860. }
  4861. }
  4862. },
  4863. remove: {
  4864. initialLoad: function() {
  4865. initialLoad = false;
  4866. }
  4867. },
  4868. trigger: {
  4869. change: function() {
  4870. var
  4871. events = document.createEvent('HTMLEvents'),
  4872. inputElement = $input[0]
  4873. ;
  4874. if(inputElement) {
  4875. module.verbose('Triggering native change event');
  4876. events.initEvent('change', true, false);
  4877. inputElement.dispatchEvent(events);
  4878. }
  4879. }
  4880. },
  4881. create: {
  4882. label: function() {
  4883. if($input.prevAll(selector.label).length > 0) {
  4884. $input.prev(selector.label).detach().insertAfter($input);
  4885. module.debug('Moving existing label', $label);
  4886. }
  4887. else if( !module.has.label() ) {
  4888. $label = $('<label>').insertAfter($input);
  4889. module.debug('Creating label', $label);
  4890. }
  4891. }
  4892. },
  4893. has: {
  4894. label: function() {
  4895. return ($label.length > 0);
  4896. }
  4897. },
  4898. bind: {
  4899. events: function() {
  4900. module.verbose('Attaching checkbox events');
  4901. $module
  4902. .on('click' + eventNamespace, module.event.click)
  4903. .on('change' + eventNamespace, module.event.change)
  4904. .on('keydown' + eventNamespace, selector.input, module.event.keydown)
  4905. .on('keyup' + eventNamespace, selector.input, module.event.keyup)
  4906. ;
  4907. }
  4908. },
  4909. unbind: {
  4910. events: function() {
  4911. module.debug('Removing events');
  4912. $module
  4913. .off(eventNamespace)
  4914. ;
  4915. }
  4916. },
  4917. uncheckOthers: function() {
  4918. var
  4919. $radios = module.get.otherRadios()
  4920. ;
  4921. module.debug('Unchecking other radios', $radios);
  4922. $radios.removeClass(className.checked);
  4923. },
  4924. toggle: function() {
  4925. if( !module.can.change() ) {
  4926. if(!module.is.radio()) {
  4927. module.debug('Checkbox is read-only or disabled, ignoring toggle');
  4928. }
  4929. return;
  4930. }
  4931. if( module.is.indeterminate() || module.is.unchecked() ) {
  4932. module.debug('Currently unchecked');
  4933. module.check();
  4934. }
  4935. else if( module.is.checked() && module.can.uncheck() ) {
  4936. module.debug('Currently checked');
  4937. module.uncheck();
  4938. }
  4939. },
  4940. setting: function(name, value) {
  4941. module.debug('Changing setting', name, value);
  4942. if( $.isPlainObject(name) ) {
  4943. $.extend(true, settings, name);
  4944. }
  4945. else if(value !== undefined) {
  4946. if($.isPlainObject(settings[name])) {
  4947. $.extend(true, settings[name], value);
  4948. }
  4949. else {
  4950. settings[name] = value;
  4951. }
  4952. }
  4953. else {
  4954. return settings[name];
  4955. }
  4956. },
  4957. internal: function(name, value) {
  4958. if( $.isPlainObject(name) ) {
  4959. $.extend(true, module, name);
  4960. }
  4961. else if(value !== undefined) {
  4962. module[name] = value;
  4963. }
  4964. else {
  4965. return module[name];
  4966. }
  4967. },
  4968. debug: function() {
  4969. if(!settings.silent && settings.debug) {
  4970. if(settings.performance) {
  4971. module.performance.log(arguments);
  4972. }
  4973. else {
  4974. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  4975. module.debug.apply(console, arguments);
  4976. }
  4977. }
  4978. },
  4979. verbose: function() {
  4980. if(!settings.silent && settings.verbose && settings.debug) {
  4981. if(settings.performance) {
  4982. module.performance.log(arguments);
  4983. }
  4984. else {
  4985. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  4986. module.verbose.apply(console, arguments);
  4987. }
  4988. }
  4989. },
  4990. error: function() {
  4991. if(!settings.silent) {
  4992. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  4993. module.error.apply(console, arguments);
  4994. }
  4995. },
  4996. performance: {
  4997. log: function(message) {
  4998. var
  4999. currentTime,
  5000. executionTime,
  5001. previousTime
  5002. ;
  5003. if(settings.performance) {
  5004. currentTime = new Date().getTime();
  5005. previousTime = time || currentTime;
  5006. executionTime = currentTime - previousTime;
  5007. time = currentTime;
  5008. performance.push({
  5009. 'Name' : message[0],
  5010. 'Arguments' : [].slice.call(message, 1) || '',
  5011. 'Element' : element,
  5012. 'Execution Time' : executionTime
  5013. });
  5014. }
  5015. clearTimeout(module.performance.timer);
  5016. module.performance.timer = setTimeout(module.performance.display, 500);
  5017. },
  5018. display: function() {
  5019. var
  5020. title = settings.name + ':',
  5021. totalTime = 0
  5022. ;
  5023. time = false;
  5024. clearTimeout(module.performance.timer);
  5025. $.each(performance, function(index, data) {
  5026. totalTime += data['Execution Time'];
  5027. });
  5028. title += ' ' + totalTime + 'ms';
  5029. if(moduleSelector) {
  5030. title += ' \'' + moduleSelector + '\'';
  5031. }
  5032. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  5033. console.groupCollapsed(title);
  5034. if(console.table) {
  5035. console.table(performance);
  5036. }
  5037. else {
  5038. $.each(performance, function(index, data) {
  5039. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  5040. });
  5041. }
  5042. console.groupEnd();
  5043. }
  5044. performance = [];
  5045. }
  5046. },
  5047. invoke: function(query, passedArguments, context) {
  5048. var
  5049. object = instance,
  5050. maxDepth,
  5051. found,
  5052. response
  5053. ;
  5054. passedArguments = passedArguments || queryArguments;
  5055. context = element || context;
  5056. if(typeof query == 'string' && object !== undefined) {
  5057. query = query.split(/[\. ]/);
  5058. maxDepth = query.length - 1;
  5059. $.each(query, function(depth, value) {
  5060. var camelCaseValue = (depth != maxDepth)
  5061. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  5062. : query
  5063. ;
  5064. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  5065. object = object[camelCaseValue];
  5066. }
  5067. else if( object[camelCaseValue] !== undefined ) {
  5068. found = object[camelCaseValue];
  5069. return false;
  5070. }
  5071. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  5072. object = object[value];
  5073. }
  5074. else if( object[value] !== undefined ) {
  5075. found = object[value];
  5076. return false;
  5077. }
  5078. else {
  5079. module.error(error.method, query);
  5080. return false;
  5081. }
  5082. });
  5083. }
  5084. if ( $.isFunction( found ) ) {
  5085. response = found.apply(context, passedArguments);
  5086. }
  5087. else if(found !== undefined) {
  5088. response = found;
  5089. }
  5090. if(Array.isArray(returnedValue)) {
  5091. returnedValue.push(response);
  5092. }
  5093. else if(returnedValue !== undefined) {
  5094. returnedValue = [returnedValue, response];
  5095. }
  5096. else if(response !== undefined) {
  5097. returnedValue = response;
  5098. }
  5099. return found;
  5100. }
  5101. };
  5102. if(methodInvoked) {
  5103. if(instance === undefined) {
  5104. module.initialize();
  5105. }
  5106. module.invoke(query);
  5107. }
  5108. else {
  5109. if(instance !== undefined) {
  5110. instance.invoke('destroy');
  5111. }
  5112. module.initialize();
  5113. }
  5114. })
  5115. ;
  5116. return (returnedValue !== undefined)
  5117. ? returnedValue
  5118. : this
  5119. ;
  5120. };
  5121. $.fn.checkbox.settings = {
  5122. name : 'Checkbox',
  5123. namespace : 'checkbox',
  5124. silent : false,
  5125. debug : false,
  5126. verbose : true,
  5127. performance : true,
  5128. // delegated event context
  5129. uncheckable : 'auto',
  5130. fireOnInit : false,
  5131. enableEnterKey : true,
  5132. onChange : function(){},
  5133. beforeChecked : function(){},
  5134. beforeUnchecked : function(){},
  5135. beforeDeterminate : function(){},
  5136. beforeIndeterminate : function(){},
  5137. onChecked : function(){},
  5138. onUnchecked : function(){},
  5139. onDeterminate : function() {},
  5140. onIndeterminate : function() {},
  5141. onEnable : function(){},
  5142. onDisable : function(){},
  5143. // preserve misspelled callbacks (will be removed in 3.0)
  5144. onEnabled : function(){},
  5145. onDisabled : function(){},
  5146. className : {
  5147. checked : 'checked',
  5148. indeterminate : 'indeterminate',
  5149. disabled : 'disabled',
  5150. hidden : 'hidden',
  5151. radio : 'radio',
  5152. readOnly : 'read-only'
  5153. },
  5154. error : {
  5155. method : 'The method you called is not defined'
  5156. },
  5157. selector : {
  5158. checkbox : '.ui.checkbox',
  5159. label : 'label, .box',
  5160. input : 'input[type="checkbox"], input[type="radio"]',
  5161. link : 'a[href]'
  5162. }
  5163. };
  5164. })( jQuery, window, document );
  5165. /*!
  5166. * # Fomantic-UI - Dimmer
  5167. * http://github.com/fomantic/Fomantic-UI/
  5168. *
  5169. *
  5170. * Released under the MIT license
  5171. * http://opensource.org/licenses/MIT
  5172. *
  5173. */
  5174. ;(function ($, window, document, undefined) {
  5175. 'use strict';
  5176. $.isFunction = $.isFunction || function(obj) {
  5177. return typeof obj === "function" && typeof obj.nodeType !== "number";
  5178. };
  5179. window = (typeof window != 'undefined' && window.Math == Math)
  5180. ? window
  5181. : (typeof self != 'undefined' && self.Math == Math)
  5182. ? self
  5183. : Function('return this')()
  5184. ;
  5185. $.fn.dimmer = function(parameters) {
  5186. var
  5187. $allModules = $(this),
  5188. time = new Date().getTime(),
  5189. performance = [],
  5190. query = arguments[0],
  5191. methodInvoked = (typeof query == 'string'),
  5192. queryArguments = [].slice.call(arguments, 1),
  5193. returnedValue
  5194. ;
  5195. $allModules
  5196. .each(function() {
  5197. var
  5198. settings = ( $.isPlainObject(parameters) )
  5199. ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
  5200. : $.extend({}, $.fn.dimmer.settings),
  5201. selector = settings.selector,
  5202. namespace = settings.namespace,
  5203. className = settings.className,
  5204. error = settings.error,
  5205. eventNamespace = '.' + namespace,
  5206. moduleNamespace = 'module-' + namespace,
  5207. moduleSelector = $allModules.selector || '',
  5208. clickEvent = ('ontouchstart' in document.documentElement)
  5209. ? 'touchstart'
  5210. : 'click',
  5211. $module = $(this),
  5212. $dimmer,
  5213. $dimmable,
  5214. element = this,
  5215. instance = $module.data(moduleNamespace),
  5216. module
  5217. ;
  5218. module = {
  5219. preinitialize: function() {
  5220. if( module.is.dimmer() ) {
  5221. $dimmable = $module.parent();
  5222. $dimmer = $module;
  5223. }
  5224. else {
  5225. $dimmable = $module;
  5226. if( module.has.dimmer() ) {
  5227. if(settings.dimmerName) {
  5228. $dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
  5229. }
  5230. else {
  5231. $dimmer = $dimmable.find(selector.dimmer);
  5232. }
  5233. }
  5234. else {
  5235. $dimmer = module.create();
  5236. }
  5237. }
  5238. },
  5239. initialize: function() {
  5240. module.debug('Initializing dimmer', settings);
  5241. module.bind.events();
  5242. module.set.dimmable();
  5243. module.instantiate();
  5244. },
  5245. instantiate: function() {
  5246. module.verbose('Storing instance of module', module);
  5247. instance = module;
  5248. $module
  5249. .data(moduleNamespace, instance)
  5250. ;
  5251. },
  5252. destroy: function() {
  5253. module.verbose('Destroying previous module', $dimmer);
  5254. module.unbind.events();
  5255. module.remove.variation();
  5256. $dimmable
  5257. .off(eventNamespace)
  5258. ;
  5259. },
  5260. bind: {
  5261. events: function() {
  5262. if(settings.on == 'hover') {
  5263. $dimmable
  5264. .on('mouseenter' + eventNamespace, module.show)
  5265. .on('mouseleave' + eventNamespace, module.hide)
  5266. ;
  5267. }
  5268. else if(settings.on == 'click') {
  5269. $dimmable
  5270. .on(clickEvent + eventNamespace, module.toggle)
  5271. ;
  5272. }
  5273. if( module.is.page() ) {
  5274. module.debug('Setting as a page dimmer', $dimmable);
  5275. module.set.pageDimmer();
  5276. }
  5277. if( module.is.closable() ) {
  5278. module.verbose('Adding dimmer close event', $dimmer);
  5279. $dimmable
  5280. .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
  5281. ;
  5282. }
  5283. }
  5284. },
  5285. unbind: {
  5286. events: function() {
  5287. $module
  5288. .removeData(moduleNamespace)
  5289. ;
  5290. $dimmable
  5291. .off(eventNamespace)
  5292. ;
  5293. }
  5294. },
  5295. event: {
  5296. click: function(event) {
  5297. module.verbose('Determining if event occured on dimmer', event);
  5298. if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
  5299. module.hide();
  5300. event.stopImmediatePropagation();
  5301. }
  5302. }
  5303. },
  5304. addContent: function(element) {
  5305. var
  5306. $content = $(element)
  5307. ;
  5308. module.debug('Add content to dimmer', $content);
  5309. if($content.parent()[0] !== $dimmer[0]) {
  5310. $content.detach().appendTo($dimmer);
  5311. }
  5312. },
  5313. create: function() {
  5314. var
  5315. $element = $( settings.template.dimmer(settings) )
  5316. ;
  5317. if(settings.dimmerName) {
  5318. module.debug('Creating named dimmer', settings.dimmerName);
  5319. $element.addClass(settings.dimmerName);
  5320. }
  5321. $element
  5322. .appendTo($dimmable)
  5323. ;
  5324. return $element;
  5325. },
  5326. show: function(callback) {
  5327. callback = $.isFunction(callback)
  5328. ? callback
  5329. : function(){}
  5330. ;
  5331. module.debug('Showing dimmer', $dimmer, settings);
  5332. module.set.variation();
  5333. if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
  5334. module.animate.show(callback);
  5335. settings.onShow.call(element);
  5336. settings.onChange.call(element);
  5337. }
  5338. else {
  5339. module.debug('Dimmer is already shown or disabled');
  5340. }
  5341. },
  5342. hide: function(callback) {
  5343. callback = $.isFunction(callback)
  5344. ? callback
  5345. : function(){}
  5346. ;
  5347. if( module.is.dimmed() || module.is.animating() ) {
  5348. module.debug('Hiding dimmer', $dimmer);
  5349. module.animate.hide(callback);
  5350. settings.onHide.call(element);
  5351. settings.onChange.call(element);
  5352. }
  5353. else {
  5354. module.debug('Dimmer is not visible');
  5355. }
  5356. },
  5357. toggle: function() {
  5358. module.verbose('Toggling dimmer visibility', $dimmer);
  5359. if( !module.is.dimmed() ) {
  5360. module.show();
  5361. }
  5362. else {
  5363. if ( module.is.closable() ) {
  5364. module.hide();
  5365. }
  5366. }
  5367. },
  5368. animate: {
  5369. show: function(callback) {
  5370. callback = $.isFunction(callback)
  5371. ? callback
  5372. : function(){}
  5373. ;
  5374. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  5375. if(settings.useFlex) {
  5376. module.debug('Using flex dimmer');
  5377. module.remove.legacy();
  5378. }
  5379. else {
  5380. module.debug('Using legacy non-flex dimmer');
  5381. module.set.legacy();
  5382. }
  5383. if(settings.opacity !== 'auto') {
  5384. module.set.opacity();
  5385. }
  5386. $dimmer
  5387. .transition({
  5388. displayType : settings.useFlex
  5389. ? 'flex'
  5390. : 'block',
  5391. animation : settings.transition + ' in',
  5392. queue : false,
  5393. duration : module.get.duration(),
  5394. useFailSafe : true,
  5395. onStart : function() {
  5396. module.set.dimmed();
  5397. },
  5398. onComplete : function() {
  5399. module.set.active();
  5400. callback();
  5401. }
  5402. })
  5403. ;
  5404. }
  5405. else {
  5406. module.verbose('Showing dimmer animation with javascript');
  5407. module.set.dimmed();
  5408. if(settings.opacity == 'auto') {
  5409. settings.opacity = 0.8;
  5410. }
  5411. $dimmer
  5412. .stop()
  5413. .css({
  5414. opacity : 0,
  5415. width : '100%',
  5416. height : '100%'
  5417. })
  5418. .fadeTo(module.get.duration(), settings.opacity, function() {
  5419. $dimmer.removeAttr('style');
  5420. module.set.active();
  5421. callback();
  5422. })
  5423. ;
  5424. }
  5425. },
  5426. hide: function(callback) {
  5427. callback = $.isFunction(callback)
  5428. ? callback
  5429. : function(){}
  5430. ;
  5431. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  5432. module.verbose('Hiding dimmer with css');
  5433. $dimmer
  5434. .transition({
  5435. displayType : settings.useFlex
  5436. ? 'flex'
  5437. : 'block',
  5438. animation : settings.transition + ' out',
  5439. queue : false,
  5440. duration : module.get.duration(),
  5441. useFailSafe : true,
  5442. onComplete : function() {
  5443. module.remove.dimmed();
  5444. module.remove.variation();
  5445. module.remove.active();
  5446. callback();
  5447. }
  5448. })
  5449. ;
  5450. }
  5451. else {
  5452. module.verbose('Hiding dimmer with javascript');
  5453. $dimmer
  5454. .stop()
  5455. .fadeOut(module.get.duration(), function() {
  5456. module.remove.dimmed();
  5457. module.remove.active();
  5458. $dimmer.removeAttr('style');
  5459. callback();
  5460. })
  5461. ;
  5462. }
  5463. }
  5464. },
  5465. get: {
  5466. dimmer: function() {
  5467. return $dimmer;
  5468. },
  5469. duration: function() {
  5470. if(typeof settings.duration == 'object') {
  5471. if( module.is.active() ) {
  5472. return settings.duration.hide;
  5473. }
  5474. else {
  5475. return settings.duration.show;
  5476. }
  5477. }
  5478. return settings.duration;
  5479. }
  5480. },
  5481. has: {
  5482. dimmer: function() {
  5483. if(settings.dimmerName) {
  5484. return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
  5485. }
  5486. else {
  5487. return ( $module.find(selector.dimmer).length > 0 );
  5488. }
  5489. }
  5490. },
  5491. is: {
  5492. active: function() {
  5493. return $dimmer.hasClass(className.active);
  5494. },
  5495. animating: function() {
  5496. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
  5497. },
  5498. closable: function() {
  5499. if(settings.closable == 'auto') {
  5500. if(settings.on == 'hover') {
  5501. return false;
  5502. }
  5503. return true;
  5504. }
  5505. return settings.closable;
  5506. },
  5507. dimmer: function() {
  5508. return $module.hasClass(className.dimmer);
  5509. },
  5510. dimmable: function() {
  5511. return $module.hasClass(className.dimmable);
  5512. },
  5513. dimmed: function() {
  5514. return $dimmable.hasClass(className.dimmed);
  5515. },
  5516. disabled: function() {
  5517. return $dimmable.hasClass(className.disabled);
  5518. },
  5519. enabled: function() {
  5520. return !module.is.disabled();
  5521. },
  5522. page: function () {
  5523. return $dimmable.is('body');
  5524. },
  5525. pageDimmer: function() {
  5526. return $dimmer.hasClass(className.pageDimmer);
  5527. }
  5528. },
  5529. can: {
  5530. show: function() {
  5531. return !$dimmer.hasClass(className.disabled);
  5532. }
  5533. },
  5534. set: {
  5535. opacity: function(opacity) {
  5536. var
  5537. color = $dimmer.css('background-color'),
  5538. colorArray = color.split(','),
  5539. isRGB = (colorArray && colorArray.length == 3),
  5540. isRGBA = (colorArray && colorArray.length == 4)
  5541. ;
  5542. opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
  5543. if(isRGB || isRGBA) {
  5544. colorArray[3] = opacity + ')';
  5545. color = colorArray.join(',');
  5546. }
  5547. else {
  5548. color = 'rgba(0, 0, 0, ' + opacity + ')';
  5549. }
  5550. module.debug('Setting opacity to', opacity);
  5551. $dimmer.css('background-color', color);
  5552. },
  5553. legacy: function() {
  5554. $dimmer.addClass(className.legacy);
  5555. },
  5556. active: function() {
  5557. $dimmer.addClass(className.active);
  5558. },
  5559. dimmable: function() {
  5560. $dimmable.addClass(className.dimmable);
  5561. },
  5562. dimmed: function() {
  5563. $dimmable.addClass(className.dimmed);
  5564. },
  5565. pageDimmer: function() {
  5566. $dimmer.addClass(className.pageDimmer);
  5567. },
  5568. disabled: function() {
  5569. $dimmer.addClass(className.disabled);
  5570. },
  5571. variation: function(variation) {
  5572. variation = variation || settings.variation;
  5573. if(variation) {
  5574. $dimmer.addClass(variation);
  5575. }
  5576. }
  5577. },
  5578. remove: {
  5579. active: function() {
  5580. $dimmer
  5581. .removeClass(className.active)
  5582. ;
  5583. },
  5584. legacy: function() {
  5585. $dimmer.removeClass(className.legacy);
  5586. },
  5587. dimmed: function() {
  5588. $dimmable.removeClass(className.dimmed);
  5589. },
  5590. disabled: function() {
  5591. $dimmer.removeClass(className.disabled);
  5592. },
  5593. variation: function(variation) {
  5594. variation = variation || settings.variation;
  5595. if(variation) {
  5596. $dimmer.removeClass(variation);
  5597. }
  5598. }
  5599. },
  5600. setting: function(name, value) {
  5601. module.debug('Changing setting', name, value);
  5602. if( $.isPlainObject(name) ) {
  5603. $.extend(true, settings, name);
  5604. }
  5605. else if(value !== undefined) {
  5606. if($.isPlainObject(settings[name])) {
  5607. $.extend(true, settings[name], value);
  5608. }
  5609. else {
  5610. settings[name] = value;
  5611. }
  5612. }
  5613. else {
  5614. return settings[name];
  5615. }
  5616. },
  5617. internal: function(name, value) {
  5618. if( $.isPlainObject(name) ) {
  5619. $.extend(true, module, name);
  5620. }
  5621. else if(value !== undefined) {
  5622. module[name] = value;
  5623. }
  5624. else {
  5625. return module[name];
  5626. }
  5627. },
  5628. debug: function() {
  5629. if(!settings.silent && settings.debug) {
  5630. if(settings.performance) {
  5631. module.performance.log(arguments);
  5632. }
  5633. else {
  5634. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  5635. module.debug.apply(console, arguments);
  5636. }
  5637. }
  5638. },
  5639. verbose: function() {
  5640. if(!settings.silent && settings.verbose && settings.debug) {
  5641. if(settings.performance) {
  5642. module.performance.log(arguments);
  5643. }
  5644. else {
  5645. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  5646. module.verbose.apply(console, arguments);
  5647. }
  5648. }
  5649. },
  5650. error: function() {
  5651. if(!settings.silent) {
  5652. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  5653. module.error.apply(console, arguments);
  5654. }
  5655. },
  5656. performance: {
  5657. log: function(message) {
  5658. var
  5659. currentTime,
  5660. executionTime,
  5661. previousTime
  5662. ;
  5663. if(settings.performance) {
  5664. currentTime = new Date().getTime();
  5665. previousTime = time || currentTime;
  5666. executionTime = currentTime - previousTime;
  5667. time = currentTime;
  5668. performance.push({
  5669. 'Name' : message[0],
  5670. 'Arguments' : [].slice.call(message, 1) || '',
  5671. 'Element' : element,
  5672. 'Execution Time' : executionTime
  5673. });
  5674. }
  5675. clearTimeout(module.performance.timer);
  5676. module.performance.timer = setTimeout(module.performance.display, 500);
  5677. },
  5678. display: function() {
  5679. var
  5680. title = settings.name + ':',
  5681. totalTime = 0
  5682. ;
  5683. time = false;
  5684. clearTimeout(module.performance.timer);
  5685. $.each(performance, function(index, data) {
  5686. totalTime += data['Execution Time'];
  5687. });
  5688. title += ' ' + totalTime + 'ms';
  5689. if(moduleSelector) {
  5690. title += ' \'' + moduleSelector + '\'';
  5691. }
  5692. if($allModules.length > 1) {
  5693. title += ' ' + '(' + $allModules.length + ')';
  5694. }
  5695. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  5696. console.groupCollapsed(title);
  5697. if(console.table) {
  5698. console.table(performance);
  5699. }
  5700. else {
  5701. $.each(performance, function(index, data) {
  5702. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  5703. });
  5704. }
  5705. console.groupEnd();
  5706. }
  5707. performance = [];
  5708. }
  5709. },
  5710. invoke: function(query, passedArguments, context) {
  5711. var
  5712. object = instance,
  5713. maxDepth,
  5714. found,
  5715. response
  5716. ;
  5717. passedArguments = passedArguments || queryArguments;
  5718. context = element || context;
  5719. if(typeof query == 'string' && object !== undefined) {
  5720. query = query.split(/[\. ]/);
  5721. maxDepth = query.length - 1;
  5722. $.each(query, function(depth, value) {
  5723. var camelCaseValue = (depth != maxDepth)
  5724. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  5725. : query
  5726. ;
  5727. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  5728. object = object[camelCaseValue];
  5729. }
  5730. else if( object[camelCaseValue] !== undefined ) {
  5731. found = object[camelCaseValue];
  5732. return false;
  5733. }
  5734. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  5735. object = object[value];
  5736. }
  5737. else if( object[value] !== undefined ) {
  5738. found = object[value];
  5739. return false;
  5740. }
  5741. else {
  5742. module.error(error.method, query);
  5743. return false;
  5744. }
  5745. });
  5746. }
  5747. if ( $.isFunction( found ) ) {
  5748. response = found.apply(context, passedArguments);
  5749. }
  5750. else if(found !== undefined) {
  5751. response = found;
  5752. }
  5753. if(Array.isArray(returnedValue)) {
  5754. returnedValue.push(response);
  5755. }
  5756. else if(returnedValue !== undefined) {
  5757. returnedValue = [returnedValue, response];
  5758. }
  5759. else if(response !== undefined) {
  5760. returnedValue = response;
  5761. }
  5762. return found;
  5763. }
  5764. };
  5765. module.preinitialize();
  5766. if(methodInvoked) {
  5767. if(instance === undefined) {
  5768. module.initialize();
  5769. }
  5770. module.invoke(query);
  5771. }
  5772. else {
  5773. if(instance !== undefined) {
  5774. instance.invoke('destroy');
  5775. }
  5776. module.initialize();
  5777. }
  5778. })
  5779. ;
  5780. return (returnedValue !== undefined)
  5781. ? returnedValue
  5782. : this
  5783. ;
  5784. };
  5785. $.fn.dimmer.settings = {
  5786. name : 'Dimmer',
  5787. namespace : 'dimmer',
  5788. silent : false,
  5789. debug : false,
  5790. verbose : false,
  5791. performance : true,
  5792. // whether should use flex layout
  5793. useFlex : true,
  5794. // name to distinguish between multiple dimmers in context
  5795. dimmerName : false,
  5796. // whether to add a variation type
  5797. variation : false,
  5798. // whether to bind close events
  5799. closable : 'auto',
  5800. // whether to use css animations
  5801. useCSS : true,
  5802. // css animation to use
  5803. transition : 'fade',
  5804. // event to bind to
  5805. on : false,
  5806. // overriding opacity value
  5807. opacity : 'auto',
  5808. // transition durations
  5809. duration : {
  5810. show : 500,
  5811. hide : 500
  5812. },
  5813. // whether the dynamically created dimmer should have a loader
  5814. displayLoader: false,
  5815. loaderText : false,
  5816. loaderVariation : '',
  5817. onChange : function(){},
  5818. onShow : function(){},
  5819. onHide : function(){},
  5820. error : {
  5821. method : 'The method you called is not defined.'
  5822. },
  5823. className : {
  5824. active : 'active',
  5825. animating : 'animating',
  5826. dimmable : 'dimmable',
  5827. dimmed : 'dimmed',
  5828. dimmer : 'dimmer',
  5829. disabled : 'disabled',
  5830. hide : 'hide',
  5831. legacy : 'legacy',
  5832. pageDimmer : 'page',
  5833. show : 'show',
  5834. loader : 'ui loader'
  5835. },
  5836. selector: {
  5837. dimmer : '> .ui.dimmer',
  5838. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  5839. },
  5840. template: {
  5841. dimmer: function(settings) {
  5842. var d = $('<div/>').addClass('ui dimmer'),l;
  5843. if(settings.displayLoader) {
  5844. l = $('<div/>')
  5845. .addClass(settings.className.loader)
  5846. .addClass(settings.loaderVariation);
  5847. if(!!settings.loaderText){
  5848. l.text(settings.loaderText);
  5849. l.addClass('text');
  5850. }
  5851. d.append(l);
  5852. }
  5853. return d;
  5854. }
  5855. }
  5856. };
  5857. })( jQuery, window, document );
  5858. /*!
  5859. * # Fomantic-UI - Dropdown
  5860. * http://github.com/fomantic/Fomantic-UI/
  5861. *
  5862. *
  5863. * Released under the MIT license
  5864. * http://opensource.org/licenses/MIT
  5865. *
  5866. */
  5867. ;(function ($, window, document, undefined) {
  5868. 'use strict';
  5869. $.isFunction = $.isFunction || function(obj) {
  5870. return typeof obj === "function" && typeof obj.nodeType !== "number";
  5871. };
  5872. window = (typeof window != 'undefined' && window.Math == Math)
  5873. ? window
  5874. : (typeof self != 'undefined' && self.Math == Math)
  5875. ? self
  5876. : Function('return this')()
  5877. ;
  5878. $.fn.dropdown = function(parameters) {
  5879. var
  5880. $allModules = $(this),
  5881. $document = $(document),
  5882. moduleSelector = $allModules.selector || '',
  5883. hasTouch = ('ontouchstart' in document.documentElement),
  5884. time = new Date().getTime(),
  5885. performance = [],
  5886. query = arguments[0],
  5887. methodInvoked = (typeof query == 'string'),
  5888. queryArguments = [].slice.call(arguments, 1),
  5889. returnedValue
  5890. ;
  5891. $allModules
  5892. .each(function(elementIndex) {
  5893. var
  5894. settings = ( $.isPlainObject(parameters) )
  5895. ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
  5896. : $.extend({}, $.fn.dropdown.settings),
  5897. className = settings.className,
  5898. message = settings.message,
  5899. fields = settings.fields,
  5900. keys = settings.keys,
  5901. metadata = settings.metadata,
  5902. namespace = settings.namespace,
  5903. regExp = settings.regExp,
  5904. selector = settings.selector,
  5905. error = settings.error,
  5906. templates = settings.templates,
  5907. eventNamespace = '.' + namespace,
  5908. moduleNamespace = 'module-' + namespace,
  5909. $module = $(this),
  5910. $context = $(settings.context),
  5911. $text = $module.find(selector.text),
  5912. $search = $module.find(selector.search),
  5913. $sizer = $module.find(selector.sizer),
  5914. $input = $module.find(selector.input),
  5915. $icon = $module.find(selector.icon),
  5916. $clear = $module.find(selector.clearIcon),
  5917. $combo = ($module.prev().find(selector.text).length > 0)
  5918. ? $module.prev().find(selector.text)
  5919. : $module.prev(),
  5920. $menu = $module.children(selector.menu),
  5921. $item = $menu.find(selector.item),
  5922. $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $(),
  5923. activated = false,
  5924. itemActivated = false,
  5925. internalChange = false,
  5926. iconClicked = false,
  5927. element = this,
  5928. instance = $module.data(moduleNamespace),
  5929. selectActionActive,
  5930. initialLoad,
  5931. pageLostFocus,
  5932. willRefocus,
  5933. elementNamespace,
  5934. id,
  5935. selectObserver,
  5936. menuObserver,
  5937. module
  5938. ;
  5939. module = {
  5940. initialize: function() {
  5941. module.debug('Initializing dropdown', settings);
  5942. if( module.is.alreadySetup() ) {
  5943. module.setup.reference();
  5944. }
  5945. else {
  5946. if (settings.ignoreDiacritics && !String.prototype.normalize) {
  5947. settings.ignoreDiacritics = false;
  5948. module.error(error.noNormalize, element);
  5949. }
  5950. module.setup.layout();
  5951. if(settings.values) {
  5952. module.change.values(settings.values);
  5953. }
  5954. module.refreshData();
  5955. module.save.defaults();
  5956. module.restore.selected();
  5957. module.create.id();
  5958. module.bind.events();
  5959. module.observeChanges();
  5960. module.instantiate();
  5961. }
  5962. },
  5963. instantiate: function() {
  5964. module.verbose('Storing instance of dropdown', module);
  5965. instance = module;
  5966. $module
  5967. .data(moduleNamespace, module)
  5968. ;
  5969. },
  5970. destroy: function() {
  5971. module.verbose('Destroying previous dropdown', $module);
  5972. module.remove.tabbable();
  5973. module.remove.active();
  5974. $menu.transition('stop all');
  5975. $menu.removeClass(className.visible).addClass(className.hidden);
  5976. $module
  5977. .off(eventNamespace)
  5978. .removeData(moduleNamespace)
  5979. ;
  5980. $menu
  5981. .off(eventNamespace)
  5982. ;
  5983. $document
  5984. .off(elementNamespace)
  5985. ;
  5986. module.disconnect.menuObserver();
  5987. module.disconnect.selectObserver();
  5988. },
  5989. observeChanges: function() {
  5990. if('MutationObserver' in window) {
  5991. selectObserver = new MutationObserver(module.event.select.mutation);
  5992. menuObserver = new MutationObserver(module.event.menu.mutation);
  5993. module.debug('Setting up mutation observer', selectObserver, menuObserver);
  5994. module.observe.select();
  5995. module.observe.menu();
  5996. }
  5997. },
  5998. disconnect: {
  5999. menuObserver: function() {
  6000. if(menuObserver) {
  6001. menuObserver.disconnect();
  6002. }
  6003. },
  6004. selectObserver: function() {
  6005. if(selectObserver) {
  6006. selectObserver.disconnect();
  6007. }
  6008. }
  6009. },
  6010. observe: {
  6011. select: function() {
  6012. if(module.has.input() && selectObserver) {
  6013. selectObserver.observe($module[0], {
  6014. childList : true,
  6015. subtree : true
  6016. });
  6017. }
  6018. },
  6019. menu: function() {
  6020. if(module.has.menu() && menuObserver) {
  6021. menuObserver.observe($menu[0], {
  6022. childList : true,
  6023. subtree : true
  6024. });
  6025. }
  6026. }
  6027. },
  6028. create: {
  6029. id: function() {
  6030. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  6031. elementNamespace = '.' + id;
  6032. module.verbose('Creating unique id for element', id);
  6033. },
  6034. userChoice: function(values) {
  6035. var
  6036. $userChoices,
  6037. $userChoice,
  6038. isUserValue,
  6039. html
  6040. ;
  6041. values = values || module.get.userValues();
  6042. if(!values) {
  6043. return false;
  6044. }
  6045. values = Array.isArray(values)
  6046. ? values
  6047. : [values]
  6048. ;
  6049. $.each(values, function(index, value) {
  6050. if(module.get.item(value) === false) {
  6051. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  6052. $userChoice = $('<div />')
  6053. .html(html)
  6054. .attr('data-' + metadata.value, value)
  6055. .attr('data-' + metadata.text, value)
  6056. .addClass(className.addition)
  6057. .addClass(className.item)
  6058. ;
  6059. if(settings.hideAdditions) {
  6060. $userChoice.addClass(className.hidden);
  6061. }
  6062. $userChoices = ($userChoices === undefined)
  6063. ? $userChoice
  6064. : $userChoices.add($userChoice)
  6065. ;
  6066. module.verbose('Creating user choices for value', value, $userChoice);
  6067. }
  6068. });
  6069. return $userChoices;
  6070. },
  6071. userLabels: function(value) {
  6072. var
  6073. userValues = module.get.userValues()
  6074. ;
  6075. if(userValues) {
  6076. module.debug('Adding user labels', userValues);
  6077. $.each(userValues, function(index, value) {
  6078. module.verbose('Adding custom user value');
  6079. module.add.label(value, value);
  6080. });
  6081. }
  6082. },
  6083. menu: function() {
  6084. $menu = $('<div />')
  6085. .addClass(className.menu)
  6086. .appendTo($module)
  6087. ;
  6088. },
  6089. sizer: function() {
  6090. $sizer = $('<span />')
  6091. .addClass(className.sizer)
  6092. .insertAfter($search)
  6093. ;
  6094. }
  6095. },
  6096. search: function(query) {
  6097. query = (query !== undefined)
  6098. ? query
  6099. : module.get.query()
  6100. ;
  6101. module.verbose('Searching for query', query);
  6102. if(module.has.minCharacters(query)) {
  6103. module.filter(query);
  6104. }
  6105. else {
  6106. module.hide(null,true);
  6107. }
  6108. },
  6109. select: {
  6110. firstUnfiltered: function() {
  6111. module.verbose('Selecting first non-filtered element');
  6112. module.remove.selectedItem();
  6113. $item
  6114. .not(selector.unselectable)
  6115. .not(selector.addition + selector.hidden)
  6116. .eq(0)
  6117. .addClass(className.selected)
  6118. ;
  6119. },
  6120. nextAvailable: function($selected) {
  6121. $selected = $selected.eq(0);
  6122. var
  6123. $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
  6124. $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
  6125. hasNext = ($nextAvailable.length > 0)
  6126. ;
  6127. if(hasNext) {
  6128. module.verbose('Moving selection to', $nextAvailable);
  6129. $nextAvailable.addClass(className.selected);
  6130. }
  6131. else {
  6132. module.verbose('Moving selection to', $prevAvailable);
  6133. $prevAvailable.addClass(className.selected);
  6134. }
  6135. }
  6136. },
  6137. setup: {
  6138. api: function() {
  6139. var
  6140. apiSettings = {
  6141. debug : settings.debug,
  6142. urlData : {
  6143. value : module.get.value(),
  6144. query : module.get.query()
  6145. },
  6146. on : false
  6147. }
  6148. ;
  6149. module.verbose('First request, initializing API');
  6150. $module
  6151. .api(apiSettings)
  6152. ;
  6153. },
  6154. layout: function() {
  6155. if( $module.is('select') ) {
  6156. module.setup.select();
  6157. module.setup.returnedObject();
  6158. }
  6159. if( !module.has.menu() ) {
  6160. module.create.menu();
  6161. }
  6162. if ( module.is.selection() && module.is.clearable() && !module.has.clearItem() ) {
  6163. module.verbose('Adding clear icon');
  6164. $clear = $('<i />')
  6165. .addClass('remove icon')
  6166. .insertBefore($text)
  6167. ;
  6168. }
  6169. if( module.is.search() && !module.has.search() ) {
  6170. module.verbose('Adding search input');
  6171. $search = $('<input />')
  6172. .addClass(className.search)
  6173. .prop('autocomplete', 'off')
  6174. .insertBefore($text)
  6175. ;
  6176. }
  6177. if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
  6178. module.create.sizer();
  6179. }
  6180. if(settings.allowTab) {
  6181. module.set.tabbable();
  6182. }
  6183. },
  6184. select: function() {
  6185. var
  6186. selectValues = module.get.selectValues()
  6187. ;
  6188. module.debug('Dropdown initialized on a select', selectValues);
  6189. if( $module.is('select') ) {
  6190. $input = $module;
  6191. }
  6192. // see if select is placed correctly already
  6193. if($input.parent(selector.dropdown).length > 0) {
  6194. module.debug('UI dropdown already exists. Creating dropdown menu only');
  6195. $module = $input.closest(selector.dropdown);
  6196. if( !module.has.menu() ) {
  6197. module.create.menu();
  6198. }
  6199. $menu = $module.children(selector.menu);
  6200. module.setup.menu(selectValues);
  6201. }
  6202. else {
  6203. module.debug('Creating entire dropdown from select');
  6204. $module = $('<div />')
  6205. .attr('class', $input.attr('class') )
  6206. .addClass(className.selection)
  6207. .addClass(className.dropdown)
  6208. .html( templates.dropdown(selectValues, fields, settings.preserveHTML, settings.className) )
  6209. .insertBefore($input)
  6210. ;
  6211. if($input.hasClass(className.multiple) && $input.prop('multiple') === false) {
  6212. module.error(error.missingMultiple);
  6213. $input.prop('multiple', true);
  6214. }
  6215. if($input.is('[multiple]')) {
  6216. module.set.multiple();
  6217. }
  6218. if ($input.prop('disabled')) {
  6219. module.debug('Disabling dropdown');
  6220. $module.addClass(className.disabled);
  6221. }
  6222. $input
  6223. .removeAttr('required')
  6224. .removeAttr('class')
  6225. .detach()
  6226. .prependTo($module)
  6227. ;
  6228. }
  6229. module.refresh();
  6230. },
  6231. menu: function(values) {
  6232. $menu.html( templates.menu(values, fields,settings.preserveHTML,settings.className));
  6233. $item = $menu.find(selector.item);
  6234. $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
  6235. },
  6236. reference: function() {
  6237. module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
  6238. // replace module reference
  6239. $module = $module.parent(selector.dropdown);
  6240. instance = $module.data(moduleNamespace);
  6241. element = $module.get(0);
  6242. module.refresh();
  6243. module.setup.returnedObject();
  6244. },
  6245. returnedObject: function() {
  6246. var
  6247. $firstModules = $allModules.slice(0, elementIndex),
  6248. $lastModules = $allModules.slice(elementIndex + 1)
  6249. ;
  6250. // adjust all modules to use correct reference
  6251. $allModules = $firstModules.add($module).add($lastModules);
  6252. }
  6253. },
  6254. refresh: function() {
  6255. module.refreshSelectors();
  6256. module.refreshData();
  6257. },
  6258. refreshItems: function() {
  6259. $item = $menu.find(selector.item);
  6260. $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
  6261. },
  6262. refreshSelectors: function() {
  6263. module.verbose('Refreshing selector cache');
  6264. $text = $module.find(selector.text);
  6265. $search = $module.find(selector.search);
  6266. $input = $module.find(selector.input);
  6267. $icon = $module.find(selector.icon);
  6268. $combo = ($module.prev().find(selector.text).length > 0)
  6269. ? $module.prev().find(selector.text)
  6270. : $module.prev()
  6271. ;
  6272. $menu = $module.children(selector.menu);
  6273. $item = $menu.find(selector.item);
  6274. $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
  6275. },
  6276. refreshData: function() {
  6277. module.verbose('Refreshing cached metadata');
  6278. $item
  6279. .removeData(metadata.text)
  6280. .removeData(metadata.value)
  6281. ;
  6282. },
  6283. clearData: function() {
  6284. module.verbose('Clearing metadata');
  6285. $item
  6286. .removeData(metadata.text)
  6287. .removeData(metadata.value)
  6288. ;
  6289. $module
  6290. .removeData(metadata.defaultText)
  6291. .removeData(metadata.defaultValue)
  6292. .removeData(metadata.placeholderText)
  6293. ;
  6294. },
  6295. toggle: function() {
  6296. module.verbose('Toggling menu visibility');
  6297. if( !module.is.active() ) {
  6298. module.show();
  6299. }
  6300. else {
  6301. module.hide();
  6302. }
  6303. },
  6304. show: function(callback, preventFocus) {
  6305. callback = $.isFunction(callback)
  6306. ? callback
  6307. : function(){}
  6308. ;
  6309. if(!module.can.show() && module.is.remote()) {
  6310. module.debug('No API results retrieved, searching before show');
  6311. module.queryRemote(module.get.query(), module.show);
  6312. }
  6313. if( module.can.show() && !module.is.active() ) {
  6314. module.debug('Showing dropdown');
  6315. if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
  6316. module.remove.message();
  6317. }
  6318. if(module.is.allFiltered()) {
  6319. return true;
  6320. }
  6321. if(settings.onShow.call(element) !== false) {
  6322. module.animate.show(function() {
  6323. if( module.can.click() ) {
  6324. module.bind.intent();
  6325. }
  6326. if(module.has.search() && !preventFocus) {
  6327. module.focusSearch();
  6328. }
  6329. module.set.visible();
  6330. callback.call(element);
  6331. });
  6332. }
  6333. }
  6334. },
  6335. hide: function(callback, preventBlur) {
  6336. callback = $.isFunction(callback)
  6337. ? callback
  6338. : function(){}
  6339. ;
  6340. if( module.is.active() && !module.is.animatingOutward() ) {
  6341. module.debug('Hiding dropdown');
  6342. if(settings.onHide.call(element) !== false) {
  6343. module.animate.hide(function() {
  6344. module.remove.visible();
  6345. // hidding search focus
  6346. if ( module.is.focusedOnSearch() && preventBlur !== true ) {
  6347. $search.blur();
  6348. }
  6349. callback.call(element);
  6350. });
  6351. }
  6352. } else if( module.can.click() ) {
  6353. module.unbind.intent();
  6354. }
  6355. },
  6356. hideOthers: function() {
  6357. module.verbose('Finding other dropdowns to hide');
  6358. $allModules
  6359. .not($module)
  6360. .has(selector.menu + '.' + className.visible)
  6361. .dropdown('hide')
  6362. ;
  6363. },
  6364. hideMenu: function() {
  6365. module.verbose('Hiding menu instantaneously');
  6366. module.remove.active();
  6367. module.remove.visible();
  6368. $menu.transition('hide');
  6369. },
  6370. hideSubMenus: function() {
  6371. var
  6372. $subMenus = $menu.children(selector.item).find(selector.menu)
  6373. ;
  6374. module.verbose('Hiding sub menus', $subMenus);
  6375. $subMenus.transition('hide');
  6376. },
  6377. bind: {
  6378. events: function() {
  6379. if(hasTouch) {
  6380. module.bind.touchEvents();
  6381. }
  6382. module.bind.keyboardEvents();
  6383. module.bind.inputEvents();
  6384. module.bind.mouseEvents();
  6385. },
  6386. touchEvents: function() {
  6387. module.debug('Touch device detected binding additional touch events');
  6388. if( module.is.searchSelection() ) {
  6389. // do nothing special yet
  6390. }
  6391. else if( module.is.single() ) {
  6392. $module
  6393. .on('touchstart' + eventNamespace, module.event.test.toggle)
  6394. ;
  6395. }
  6396. $menu
  6397. .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
  6398. ;
  6399. },
  6400. keyboardEvents: function() {
  6401. module.verbose('Binding keyboard events');
  6402. $module
  6403. .on('keydown' + eventNamespace, module.event.keydown)
  6404. ;
  6405. if( module.has.search() ) {
  6406. $module
  6407. .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
  6408. ;
  6409. }
  6410. if( module.is.multiple() ) {
  6411. $document
  6412. .on('keydown' + elementNamespace, module.event.document.keydown)
  6413. ;
  6414. }
  6415. },
  6416. inputEvents: function() {
  6417. module.verbose('Binding input change events');
  6418. $module
  6419. .on('change' + eventNamespace, selector.input, module.event.change)
  6420. ;
  6421. },
  6422. mouseEvents: function() {
  6423. module.verbose('Binding mouse events');
  6424. if(module.is.multiple()) {
  6425. $module
  6426. .on('click' + eventNamespace, selector.label, module.event.label.click)
  6427. .on('click' + eventNamespace, selector.remove, module.event.remove.click)
  6428. ;
  6429. }
  6430. if( module.is.searchSelection() ) {
  6431. $module
  6432. .on('mousedown' + eventNamespace, module.event.mousedown)
  6433. .on('mouseup' + eventNamespace, module.event.mouseup)
  6434. .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
  6435. .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
  6436. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  6437. .on('click' + eventNamespace, selector.clearIcon, module.event.clearIcon.click)
  6438. .on('focus' + eventNamespace, selector.search, module.event.search.focus)
  6439. .on('click' + eventNamespace, selector.search, module.event.search.focus)
  6440. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  6441. .on('click' + eventNamespace, selector.text, module.event.text.focus)
  6442. ;
  6443. if(module.is.multiple()) {
  6444. $module
  6445. .on('click' + eventNamespace, module.event.click)
  6446. ;
  6447. }
  6448. }
  6449. else {
  6450. if(settings.on == 'click') {
  6451. $module
  6452. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  6453. .on('click' + eventNamespace, module.event.test.toggle)
  6454. ;
  6455. }
  6456. else if(settings.on == 'hover') {
  6457. $module
  6458. .on('mouseenter' + eventNamespace, module.delay.show)
  6459. .on('mouseleave' + eventNamespace, module.delay.hide)
  6460. ;
  6461. }
  6462. else {
  6463. $module
  6464. .on(settings.on + eventNamespace, module.toggle)
  6465. ;
  6466. }
  6467. $module
  6468. .on('mousedown' + eventNamespace, module.event.mousedown)
  6469. .on('mouseup' + eventNamespace, module.event.mouseup)
  6470. .on('focus' + eventNamespace, module.event.focus)
  6471. .on('click' + eventNamespace, selector.clearIcon, module.event.clearIcon.click)
  6472. ;
  6473. if(module.has.menuSearch() ) {
  6474. $module
  6475. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  6476. ;
  6477. }
  6478. else {
  6479. $module
  6480. .on('blur' + eventNamespace, module.event.blur)
  6481. ;
  6482. }
  6483. }
  6484. $menu
  6485. .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
  6486. .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
  6487. .on('click' + eventNamespace, selector.item, module.event.item.click)
  6488. ;
  6489. },
  6490. intent: function() {
  6491. module.verbose('Binding hide intent event to document');
  6492. if(hasTouch) {
  6493. $document
  6494. .on('touchstart' + elementNamespace, module.event.test.touch)
  6495. .on('touchmove' + elementNamespace, module.event.test.touch)
  6496. ;
  6497. }
  6498. $document
  6499. .on('click' + elementNamespace, module.event.test.hide)
  6500. ;
  6501. }
  6502. },
  6503. unbind: {
  6504. intent: function() {
  6505. module.verbose('Removing hide intent event from document');
  6506. if(hasTouch) {
  6507. $document
  6508. .off('touchstart' + elementNamespace)
  6509. .off('touchmove' + elementNamespace)
  6510. ;
  6511. }
  6512. $document
  6513. .off('click' + elementNamespace)
  6514. ;
  6515. }
  6516. },
  6517. filter: function(query) {
  6518. var
  6519. searchTerm = (query !== undefined)
  6520. ? query
  6521. : module.get.query(),
  6522. afterFiltered = function() {
  6523. if(module.is.multiple()) {
  6524. module.filterActive();
  6525. }
  6526. if(query || (!query && module.get.activeItem().length == 0)) {
  6527. module.select.firstUnfiltered();
  6528. }
  6529. if( module.has.allResultsFiltered() ) {
  6530. if( settings.onNoResults.call(element, searchTerm) ) {
  6531. if(settings.allowAdditions) {
  6532. if(settings.hideAdditions) {
  6533. module.verbose('User addition with no menu, setting empty style');
  6534. module.set.empty();
  6535. module.hideMenu();
  6536. }
  6537. }
  6538. else {
  6539. module.verbose('All items filtered, showing message', searchTerm);
  6540. module.add.message(message.noResults);
  6541. }
  6542. }
  6543. else {
  6544. module.verbose('All items filtered, hiding dropdown', searchTerm);
  6545. module.hideMenu();
  6546. }
  6547. }
  6548. else {
  6549. module.remove.empty();
  6550. module.remove.message();
  6551. }
  6552. if(settings.allowAdditions) {
  6553. module.add.userSuggestion(module.escape.htmlEntities(query));
  6554. }
  6555. if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
  6556. module.show();
  6557. }
  6558. }
  6559. ;
  6560. if(settings.useLabels && module.has.maxSelections()) {
  6561. return;
  6562. }
  6563. if(settings.apiSettings) {
  6564. if( module.can.useAPI() ) {
  6565. module.queryRemote(searchTerm, function() {
  6566. if(settings.filterRemoteData) {
  6567. module.filterItems(searchTerm);
  6568. }
  6569. var preSelected = $input.val();
  6570. if(!Array.isArray(preSelected)) {
  6571. preSelected = preSelected && preSelected!=="" ? preSelected.split(settings.delimiter) : [];
  6572. }
  6573. $.each(preSelected,function(index,value){
  6574. $item.filter('[data-value="'+value+'"]')
  6575. .addClass(className.filtered)
  6576. ;
  6577. });
  6578. afterFiltered();
  6579. });
  6580. }
  6581. else {
  6582. module.error(error.noAPI);
  6583. }
  6584. }
  6585. else {
  6586. module.filterItems(searchTerm);
  6587. afterFiltered();
  6588. }
  6589. },
  6590. queryRemote: function(query, callback) {
  6591. var
  6592. apiSettings = {
  6593. errorDuration : false,
  6594. cache : 'local',
  6595. throttle : settings.throttle,
  6596. urlData : {
  6597. query: query
  6598. },
  6599. onError: function() {
  6600. module.add.message(message.serverError);
  6601. callback();
  6602. },
  6603. onFailure: function() {
  6604. module.add.message(message.serverError);
  6605. callback();
  6606. },
  6607. onSuccess : function(response) {
  6608. var
  6609. values = response[fields.remoteValues]
  6610. ;
  6611. if (!Array.isArray(values)){
  6612. values = [];
  6613. }
  6614. module.remove.message();
  6615. module.setup.menu({
  6616. values: values
  6617. });
  6618. if(values.length===0 && !settings.allowAdditions) {
  6619. module.add.message(message.noResults);
  6620. }
  6621. callback();
  6622. }
  6623. }
  6624. ;
  6625. if( !$module.api('get request') ) {
  6626. module.setup.api();
  6627. }
  6628. apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
  6629. $module
  6630. .api('setting', apiSettings)
  6631. .api('query')
  6632. ;
  6633. },
  6634. filterItems: function(query) {
  6635. var
  6636. searchTerm = module.remove.diacritics(query !== undefined
  6637. ? query
  6638. : module.get.query()
  6639. ),
  6640. results = null,
  6641. escapedTerm = module.escape.string(searchTerm),
  6642. regExpFlags = (settings.ignoreSearchCase ? 'i' : '') + 'gm',
  6643. beginsWithRegExp = new RegExp('^' + escapedTerm, regExpFlags)
  6644. ;
  6645. // avoid loop if we're matching nothing
  6646. if( module.has.query() ) {
  6647. results = [];
  6648. module.verbose('Searching for matching values', searchTerm);
  6649. $item
  6650. .each(function(){
  6651. var
  6652. $choice = $(this),
  6653. text,
  6654. value
  6655. ;
  6656. if(settings.match === 'both' || settings.match === 'text') {
  6657. text = module.remove.diacritics(String(module.get.choiceText($choice, false)));
  6658. if(text.search(beginsWithRegExp) !== -1) {
  6659. results.push(this);
  6660. return true;
  6661. }
  6662. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) {
  6663. results.push(this);
  6664. return true;
  6665. }
  6666. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) {
  6667. results.push(this);
  6668. return true;
  6669. }
  6670. }
  6671. if(settings.match === 'both' || settings.match === 'value') {
  6672. value = module.remove.diacritics(String(module.get.choiceValue($choice, text)));
  6673. if(value.search(beginsWithRegExp) !== -1) {
  6674. results.push(this);
  6675. return true;
  6676. }
  6677. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, value)) {
  6678. results.push(this);
  6679. return true;
  6680. }
  6681. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, value)) {
  6682. results.push(this);
  6683. return true;
  6684. }
  6685. }
  6686. })
  6687. ;
  6688. }
  6689. module.debug('Showing only matched items', searchTerm);
  6690. module.remove.filteredItem();
  6691. if(results) {
  6692. $item
  6693. .not(results)
  6694. .addClass(className.filtered)
  6695. ;
  6696. }
  6697. if(!module.has.query()) {
  6698. $divider
  6699. .removeClass(className.hidden);
  6700. } else if(settings.hideDividers === true) {
  6701. $divider
  6702. .addClass(className.hidden);
  6703. } else if(settings.hideDividers === 'empty') {
  6704. $divider
  6705. .removeClass(className.hidden)
  6706. .filter(function() {
  6707. // First find the last divider in this divider group
  6708. // Dividers which are direct siblings are considered a group
  6709. var lastDivider = $(this).nextUntil(selector.item);
  6710. return (lastDivider.length ? lastDivider : $(this))
  6711. // Count all non-filtered items until the next divider (or end of the dropdown)
  6712. .nextUntil(selector.divider)
  6713. .filter(selector.item + ":not(." + className.filtered + ")")
  6714. // Hide divider if no items are found
  6715. .length === 0;
  6716. })
  6717. .addClass(className.hidden);
  6718. }
  6719. },
  6720. fuzzySearch: function(query, term) {
  6721. var
  6722. termLength = term.length,
  6723. queryLength = query.length
  6724. ;
  6725. query = (settings.ignoreSearchCase ? query.toLowerCase() : query);
  6726. term = (settings.ignoreSearchCase ? term.toLowerCase() : term);
  6727. if(queryLength > termLength) {
  6728. return false;
  6729. }
  6730. if(queryLength === termLength) {
  6731. return (query === term);
  6732. }
  6733. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  6734. var
  6735. queryCharacter = query.charCodeAt(characterIndex)
  6736. ;
  6737. while(nextCharacterIndex < termLength) {
  6738. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  6739. continue search;
  6740. }
  6741. }
  6742. return false;
  6743. }
  6744. return true;
  6745. },
  6746. exactSearch: function (query, term) {
  6747. query = (settings.ignoreSearchCase ? query.toLowerCase() : query);
  6748. term = (settings.ignoreSearchCase ? term.toLowerCase() : term);
  6749. return term.indexOf(query) > -1;
  6750. },
  6751. filterActive: function() {
  6752. if(settings.useLabels) {
  6753. $item.filter('.' + className.active)
  6754. .addClass(className.filtered)
  6755. ;
  6756. }
  6757. },
  6758. focusSearch: function(skipHandler) {
  6759. if( module.has.search() && !module.is.focusedOnSearch() ) {
  6760. if(skipHandler) {
  6761. $module.off('focus' + eventNamespace, selector.search);
  6762. $search.focus();
  6763. $module.on('focus' + eventNamespace, selector.search, module.event.search.focus);
  6764. }
  6765. else {
  6766. $search.focus();
  6767. }
  6768. }
  6769. },
  6770. blurSearch: function() {
  6771. if( module.has.search() ) {
  6772. $search.blur();
  6773. }
  6774. },
  6775. forceSelection: function() {
  6776. var
  6777. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  6778. $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
  6779. $selectedItem = ($currentlySelected.length > 0)
  6780. ? $currentlySelected
  6781. : $activeItem,
  6782. hasSelected = ($selectedItem.length > 0)
  6783. ;
  6784. if(settings.allowAdditions || (hasSelected && !module.is.multiple())) {
  6785. module.debug('Forcing partial selection to selected item', $selectedItem);
  6786. module.event.item.click.call($selectedItem, {}, true);
  6787. }
  6788. else {
  6789. module.remove.searchTerm();
  6790. }
  6791. },
  6792. change: {
  6793. values: function(values) {
  6794. if(!settings.allowAdditions) {
  6795. module.clear();
  6796. }
  6797. module.debug('Creating dropdown with specified values', values);
  6798. module.setup.menu({values: values});
  6799. $.each(values, function(index, item) {
  6800. if(item.selected == true) {
  6801. module.debug('Setting initial selection to', item[fields.value]);
  6802. module.set.selected(item[fields.value]);
  6803. if(!module.is.multiple()) {
  6804. return false;
  6805. }
  6806. }
  6807. });
  6808. if(module.has.selectInput()) {
  6809. module.disconnect.selectObserver();
  6810. $input.html('');
  6811. $input.append('<option disabled selected value></option>');
  6812. $.each(values, function(index, item) {
  6813. var
  6814. value = settings.templates.deQuote(item[fields.value]),
  6815. name = settings.templates.escape(
  6816. item[fields.name] || item[fields.value],
  6817. settings.preserveHTML
  6818. )
  6819. ;
  6820. $input.append('<option value="' + value + '">' + name + '</option>');
  6821. });
  6822. module.observe.select();
  6823. }
  6824. }
  6825. },
  6826. event: {
  6827. change: function() {
  6828. if(!internalChange) {
  6829. module.debug('Input changed, updating selection');
  6830. module.set.selected();
  6831. }
  6832. },
  6833. focus: function() {
  6834. if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
  6835. module.show();
  6836. }
  6837. },
  6838. blur: function(event) {
  6839. pageLostFocus = (document.activeElement === this);
  6840. if(!activated && !pageLostFocus) {
  6841. module.remove.activeLabel();
  6842. module.hide();
  6843. }
  6844. },
  6845. mousedown: function() {
  6846. if(module.is.searchSelection()) {
  6847. // prevent menu hiding on immediate re-focus
  6848. willRefocus = true;
  6849. }
  6850. else {
  6851. // prevents focus callback from occurring on mousedown
  6852. activated = true;
  6853. }
  6854. },
  6855. mouseup: function() {
  6856. if(module.is.searchSelection()) {
  6857. // prevent menu hiding on immediate re-focus
  6858. willRefocus = false;
  6859. }
  6860. else {
  6861. activated = false;
  6862. }
  6863. },
  6864. click: function(event) {
  6865. var
  6866. $target = $(event.target)
  6867. ;
  6868. // focus search
  6869. if($target.is($module)) {
  6870. if(!module.is.focusedOnSearch()) {
  6871. module.focusSearch();
  6872. }
  6873. else {
  6874. module.show();
  6875. }
  6876. }
  6877. },
  6878. search: {
  6879. focus: function(event) {
  6880. activated = true;
  6881. if(module.is.multiple()) {
  6882. module.remove.activeLabel();
  6883. }
  6884. if(settings.showOnFocus || (event.type !== 'focus' && event.type !== 'focusin')) {
  6885. module.search();
  6886. }
  6887. },
  6888. blur: function(event) {
  6889. pageLostFocus = (document.activeElement === this);
  6890. if(module.is.searchSelection() && !willRefocus) {
  6891. if(!itemActivated && !pageLostFocus) {
  6892. if(settings.forceSelection) {
  6893. module.forceSelection();
  6894. } else if(!settings.allowAdditions){
  6895. module.remove.searchTerm();
  6896. }
  6897. module.hide();
  6898. }
  6899. }
  6900. willRefocus = false;
  6901. }
  6902. },
  6903. clearIcon: {
  6904. click: function(event) {
  6905. module.clear();
  6906. if(module.is.searchSelection()) {
  6907. module.remove.searchTerm();
  6908. }
  6909. module.hide();
  6910. event.stopPropagation();
  6911. }
  6912. },
  6913. icon: {
  6914. click: function(event) {
  6915. iconClicked=true;
  6916. if(module.has.search()) {
  6917. if(!module.is.active()) {
  6918. if(settings.showOnFocus){
  6919. module.focusSearch();
  6920. } else {
  6921. module.toggle();
  6922. }
  6923. } else {
  6924. module.blurSearch();
  6925. }
  6926. } else {
  6927. module.toggle();
  6928. }
  6929. }
  6930. },
  6931. text: {
  6932. focus: function(event) {
  6933. activated = true;
  6934. module.focusSearch();
  6935. }
  6936. },
  6937. input: function(event) {
  6938. if(module.is.multiple() || module.is.searchSelection()) {
  6939. module.set.filtered();
  6940. }
  6941. clearTimeout(module.timer);
  6942. module.timer = setTimeout(module.search, settings.delay.search);
  6943. },
  6944. label: {
  6945. click: function(event) {
  6946. var
  6947. $label = $(this),
  6948. $labels = $module.find(selector.label),
  6949. $activeLabels = $labels.filter('.' + className.active),
  6950. $nextActive = $label.nextAll('.' + className.active),
  6951. $prevActive = $label.prevAll('.' + className.active),
  6952. $range = ($nextActive.length > 0)
  6953. ? $label.nextUntil($nextActive).add($activeLabels).add($label)
  6954. : $label.prevUntil($prevActive).add($activeLabels).add($label)
  6955. ;
  6956. if(event.shiftKey) {
  6957. $activeLabels.removeClass(className.active);
  6958. $range.addClass(className.active);
  6959. }
  6960. else if(event.ctrlKey) {
  6961. $label.toggleClass(className.active);
  6962. }
  6963. else {
  6964. $activeLabels.removeClass(className.active);
  6965. $label.addClass(className.active);
  6966. }
  6967. settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
  6968. }
  6969. },
  6970. remove: {
  6971. click: function() {
  6972. var
  6973. $label = $(this).parent()
  6974. ;
  6975. if( $label.hasClass(className.active) ) {
  6976. // remove all selected labels
  6977. module.remove.activeLabels();
  6978. }
  6979. else {
  6980. // remove this label only
  6981. module.remove.activeLabels( $label );
  6982. }
  6983. }
  6984. },
  6985. test: {
  6986. toggle: function(event) {
  6987. var
  6988. toggleBehavior = (module.is.multiple())
  6989. ? module.show
  6990. : module.toggle
  6991. ;
  6992. if(module.is.bubbledLabelClick(event) || module.is.bubbledIconClick(event)) {
  6993. return;
  6994. }
  6995. if( module.determine.eventOnElement(event, toggleBehavior) ) {
  6996. event.preventDefault();
  6997. }
  6998. },
  6999. touch: function(event) {
  7000. module.determine.eventOnElement(event, function() {
  7001. if(event.type == 'touchstart') {
  7002. module.timer = setTimeout(function() {
  7003. module.hide();
  7004. }, settings.delay.touch);
  7005. }
  7006. else if(event.type == 'touchmove') {
  7007. clearTimeout(module.timer);
  7008. }
  7009. });
  7010. event.stopPropagation();
  7011. },
  7012. hide: function(event) {
  7013. if(module.determine.eventInModule(event, module.hide)){
  7014. if(element.id && $(event.target).attr('for') === element.id){
  7015. event.preventDefault();
  7016. }
  7017. }
  7018. }
  7019. },
  7020. select: {
  7021. mutation: function(mutations) {
  7022. module.debug('<select> modified, recreating menu');
  7023. if(module.is.selectMutation(mutations)) {
  7024. module.disconnect.selectObserver();
  7025. module.refresh();
  7026. module.setup.select();
  7027. module.set.selected();
  7028. module.observe.select();
  7029. }
  7030. }
  7031. },
  7032. menu: {
  7033. mutation: function(mutations) {
  7034. var
  7035. mutation = mutations[0],
  7036. $addedNode = mutation.addedNodes
  7037. ? $(mutation.addedNodes[0])
  7038. : $(false),
  7039. $removedNode = mutation.removedNodes
  7040. ? $(mutation.removedNodes[0])
  7041. : $(false),
  7042. $changedNodes = $addedNode.add($removedNode),
  7043. isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
  7044. isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
  7045. ;
  7046. if(isUserAddition || isMessage) {
  7047. module.debug('Updating item selector cache');
  7048. module.refreshItems();
  7049. }
  7050. else {
  7051. module.debug('Menu modified, updating selector cache');
  7052. module.refresh();
  7053. }
  7054. },
  7055. mousedown: function() {
  7056. itemActivated = true;
  7057. },
  7058. mouseup: function() {
  7059. itemActivated = false;
  7060. }
  7061. },
  7062. item: {
  7063. mouseenter: function(event) {
  7064. var
  7065. $target = $(event.target),
  7066. $item = $(this),
  7067. $subMenu = $item.children(selector.menu),
  7068. $otherMenus = $item.siblings(selector.item).children(selector.menu),
  7069. hasSubMenu = ($subMenu.length > 0),
  7070. isBubbledEvent = ($subMenu.find($target).length > 0)
  7071. ;
  7072. if( !isBubbledEvent && hasSubMenu ) {
  7073. clearTimeout(module.itemTimer);
  7074. module.itemTimer = setTimeout(function() {
  7075. module.verbose('Showing sub-menu', $subMenu);
  7076. $.each($otherMenus, function() {
  7077. module.animate.hide(false, $(this));
  7078. });
  7079. module.animate.show(false, $subMenu);
  7080. }, settings.delay.show);
  7081. event.preventDefault();
  7082. }
  7083. },
  7084. mouseleave: function(event) {
  7085. var
  7086. $subMenu = $(this).children(selector.menu)
  7087. ;
  7088. if($subMenu.length > 0) {
  7089. clearTimeout(module.itemTimer);
  7090. module.itemTimer = setTimeout(function() {
  7091. module.verbose('Hiding sub-menu', $subMenu);
  7092. module.animate.hide(false, $subMenu);
  7093. }, settings.delay.hide);
  7094. }
  7095. },
  7096. click: function (event, skipRefocus) {
  7097. var
  7098. $choice = $(this),
  7099. $target = (event)
  7100. ? $(event.target)
  7101. : $(''),
  7102. $subMenu = $choice.find(selector.menu),
  7103. text = module.get.choiceText($choice),
  7104. value = module.get.choiceValue($choice, text),
  7105. hasSubMenu = ($subMenu.length > 0),
  7106. isBubbledEvent = ($subMenu.find($target).length > 0)
  7107. ;
  7108. // prevents IE11 bug where menu receives focus even though `tabindex=-1`
  7109. if (document.activeElement.tagName.toLowerCase() !== 'input') {
  7110. $(document.activeElement).blur();
  7111. }
  7112. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  7113. if(module.is.searchSelection()) {
  7114. if(settings.allowAdditions) {
  7115. module.remove.userAddition();
  7116. }
  7117. module.remove.searchTerm();
  7118. if(!module.is.focusedOnSearch() && !(skipRefocus == true)) {
  7119. module.focusSearch(true);
  7120. }
  7121. }
  7122. if(!settings.useLabels) {
  7123. module.remove.filteredItem();
  7124. module.set.scrollPosition($choice);
  7125. }
  7126. module.determine.selectAction.call(this, text, value);
  7127. }
  7128. }
  7129. },
  7130. document: {
  7131. // label selection should occur even when element has no focus
  7132. keydown: function(event) {
  7133. var
  7134. pressedKey = event.which,
  7135. isShortcutKey = module.is.inObject(pressedKey, keys)
  7136. ;
  7137. if(isShortcutKey) {
  7138. var
  7139. $label = $module.find(selector.label),
  7140. $activeLabel = $label.filter('.' + className.active),
  7141. activeValue = $activeLabel.data(metadata.value),
  7142. labelIndex = $label.index($activeLabel),
  7143. labelCount = $label.length,
  7144. hasActiveLabel = ($activeLabel.length > 0),
  7145. hasMultipleActive = ($activeLabel.length > 1),
  7146. isFirstLabel = (labelIndex === 0),
  7147. isLastLabel = (labelIndex + 1 == labelCount),
  7148. isSearch = module.is.searchSelection(),
  7149. isFocusedOnSearch = module.is.focusedOnSearch(),
  7150. isFocused = module.is.focused(),
  7151. caretAtStart = (isFocusedOnSearch && module.get.caretPosition(false) === 0),
  7152. isSelectedSearch = (caretAtStart && module.get.caretPosition(true) !== 0),
  7153. $nextLabel
  7154. ;
  7155. if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
  7156. return;
  7157. }
  7158. if(pressedKey == keys.leftArrow) {
  7159. // activate previous label
  7160. if((isFocused || caretAtStart) && !hasActiveLabel) {
  7161. module.verbose('Selecting previous label');
  7162. $label.last().addClass(className.active);
  7163. }
  7164. else if(hasActiveLabel) {
  7165. if(!event.shiftKey) {
  7166. module.verbose('Selecting previous label');
  7167. $label.removeClass(className.active);
  7168. }
  7169. else {
  7170. module.verbose('Adding previous label to selection');
  7171. }
  7172. if(isFirstLabel && !hasMultipleActive) {
  7173. $activeLabel.addClass(className.active);
  7174. }
  7175. else {
  7176. $activeLabel.prev(selector.siblingLabel)
  7177. .addClass(className.active)
  7178. .end()
  7179. ;
  7180. }
  7181. event.preventDefault();
  7182. }
  7183. }
  7184. else if(pressedKey == keys.rightArrow) {
  7185. // activate first label
  7186. if(isFocused && !hasActiveLabel) {
  7187. $label.first().addClass(className.active);
  7188. }
  7189. // activate next label
  7190. if(hasActiveLabel) {
  7191. if(!event.shiftKey) {
  7192. module.verbose('Selecting next label');
  7193. $label.removeClass(className.active);
  7194. }
  7195. else {
  7196. module.verbose('Adding next label to selection');
  7197. }
  7198. if(isLastLabel) {
  7199. if(isSearch) {
  7200. if(!isFocusedOnSearch) {
  7201. module.focusSearch();
  7202. }
  7203. else {
  7204. $label.removeClass(className.active);
  7205. }
  7206. }
  7207. else if(hasMultipleActive) {
  7208. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  7209. }
  7210. else {
  7211. $activeLabel.addClass(className.active);
  7212. }
  7213. }
  7214. else {
  7215. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  7216. }
  7217. event.preventDefault();
  7218. }
  7219. }
  7220. else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
  7221. if(hasActiveLabel) {
  7222. module.verbose('Removing active labels');
  7223. if(isLastLabel) {
  7224. if(isSearch && !isFocusedOnSearch) {
  7225. module.focusSearch();
  7226. }
  7227. }
  7228. $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
  7229. module.remove.activeLabels($activeLabel);
  7230. event.preventDefault();
  7231. }
  7232. else if(caretAtStart && !isSelectedSearch && !hasActiveLabel && pressedKey == keys.backspace) {
  7233. module.verbose('Removing last label on input backspace');
  7234. $activeLabel = $label.last().addClass(className.active);
  7235. module.remove.activeLabels($activeLabel);
  7236. }
  7237. }
  7238. else {
  7239. $activeLabel.removeClass(className.active);
  7240. }
  7241. }
  7242. }
  7243. },
  7244. keydown: function(event) {
  7245. var
  7246. pressedKey = event.which,
  7247. isShortcutKey = module.is.inObject(pressedKey, keys)
  7248. ;
  7249. if(isShortcutKey) {
  7250. var
  7251. $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
  7252. $activeItem = $menu.children('.' + className.active).eq(0),
  7253. $selectedItem = ($currentlySelected.length > 0)
  7254. ? $currentlySelected
  7255. : $activeItem,
  7256. $visibleItems = ($selectedItem.length > 0)
  7257. ? $selectedItem.siblings(':not(.' + className.filtered +')').addBack()
  7258. : $menu.children(':not(.' + className.filtered +')'),
  7259. $subMenu = $selectedItem.children(selector.menu),
  7260. $parentMenu = $selectedItem.closest(selector.menu),
  7261. inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
  7262. hasSubMenu = ($subMenu.length> 0),
  7263. hasSelectedItem = ($selectedItem.length > 0),
  7264. selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
  7265. delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
  7266. isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable),
  7267. $nextItem,
  7268. isSubMenuItem,
  7269. newIndex
  7270. ;
  7271. // allow selection with menu closed
  7272. if(isAdditionWithoutMenu) {
  7273. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  7274. module.event.item.click.call($selectedItem, event);
  7275. if(module.is.searchSelection()) {
  7276. module.remove.searchTerm();
  7277. }
  7278. if(module.is.multiple()){
  7279. event.preventDefault();
  7280. }
  7281. }
  7282. // visible menu keyboard shortcuts
  7283. if( module.is.visible() ) {
  7284. // enter (select or open sub-menu)
  7285. if(pressedKey == keys.enter || delimiterPressed) {
  7286. if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
  7287. module.verbose('Pressed enter on unselectable category, opening sub menu');
  7288. pressedKey = keys.rightArrow;
  7289. }
  7290. else if(selectedIsSelectable) {
  7291. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  7292. module.event.item.click.call($selectedItem, event);
  7293. if(module.is.searchSelection()) {
  7294. module.remove.searchTerm();
  7295. if(module.is.multiple()) {
  7296. $search.focus();
  7297. }
  7298. }
  7299. }
  7300. event.preventDefault();
  7301. }
  7302. // sub-menu actions
  7303. if(hasSelectedItem) {
  7304. if(pressedKey == keys.leftArrow) {
  7305. isSubMenuItem = ($parentMenu[0] !== $menu[0]);
  7306. if(isSubMenuItem) {
  7307. module.verbose('Left key pressed, closing sub-menu');
  7308. module.animate.hide(false, $parentMenu);
  7309. $selectedItem
  7310. .removeClass(className.selected)
  7311. ;
  7312. $parentMenu
  7313. .closest(selector.item)
  7314. .addClass(className.selected)
  7315. ;
  7316. event.preventDefault();
  7317. }
  7318. }
  7319. // right arrow (show sub-menu)
  7320. if(pressedKey == keys.rightArrow) {
  7321. if(hasSubMenu) {
  7322. module.verbose('Right key pressed, opening sub-menu');
  7323. module.animate.show(false, $subMenu);
  7324. $selectedItem
  7325. .removeClass(className.selected)
  7326. ;
  7327. $subMenu
  7328. .find(selector.item).eq(0)
  7329. .addClass(className.selected)
  7330. ;
  7331. event.preventDefault();
  7332. }
  7333. }
  7334. }
  7335. // up arrow (traverse menu up)
  7336. if(pressedKey == keys.upArrow) {
  7337. $nextItem = (hasSelectedItem && inVisibleMenu)
  7338. ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  7339. : $item.eq(0)
  7340. ;
  7341. if($visibleItems.index( $nextItem ) < 0) {
  7342. module.verbose('Up key pressed but reached top of current menu');
  7343. event.preventDefault();
  7344. return;
  7345. }
  7346. else {
  7347. module.verbose('Up key pressed, changing active item');
  7348. $selectedItem
  7349. .removeClass(className.selected)
  7350. ;
  7351. $nextItem
  7352. .addClass(className.selected)
  7353. ;
  7354. module.set.scrollPosition($nextItem);
  7355. if(settings.selectOnKeydown && module.is.single()) {
  7356. module.set.selectedItem($nextItem);
  7357. }
  7358. }
  7359. event.preventDefault();
  7360. }
  7361. // down arrow (traverse menu down)
  7362. if(pressedKey == keys.downArrow) {
  7363. $nextItem = (hasSelectedItem && inVisibleMenu)
  7364. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  7365. : $item.eq(0)
  7366. ;
  7367. if($nextItem.length === 0) {
  7368. module.verbose('Down key pressed but reached bottom of current menu');
  7369. event.preventDefault();
  7370. return;
  7371. }
  7372. else {
  7373. module.verbose('Down key pressed, changing active item');
  7374. $item
  7375. .removeClass(className.selected)
  7376. ;
  7377. $nextItem
  7378. .addClass(className.selected)
  7379. ;
  7380. module.set.scrollPosition($nextItem);
  7381. if(settings.selectOnKeydown && module.is.single()) {
  7382. module.set.selectedItem($nextItem);
  7383. }
  7384. }
  7385. event.preventDefault();
  7386. }
  7387. // page down (show next page)
  7388. if(pressedKey == keys.pageUp) {
  7389. module.scrollPage('up');
  7390. event.preventDefault();
  7391. }
  7392. if(pressedKey == keys.pageDown) {
  7393. module.scrollPage('down');
  7394. event.preventDefault();
  7395. }
  7396. // escape (close menu)
  7397. if(pressedKey == keys.escape) {
  7398. module.verbose('Escape key pressed, closing dropdown');
  7399. module.hide();
  7400. }
  7401. }
  7402. else {
  7403. // delimiter key
  7404. if(delimiterPressed) {
  7405. event.preventDefault();
  7406. }
  7407. // down arrow (open menu)
  7408. if(pressedKey == keys.downArrow && !module.is.visible()) {
  7409. module.verbose('Down key pressed, showing dropdown');
  7410. module.show();
  7411. event.preventDefault();
  7412. }
  7413. }
  7414. }
  7415. else {
  7416. if( !module.has.search() ) {
  7417. module.set.selectedLetter( String.fromCharCode(pressedKey) );
  7418. }
  7419. }
  7420. }
  7421. },
  7422. trigger: {
  7423. change: function() {
  7424. var
  7425. events = document.createEvent('HTMLEvents'),
  7426. inputElement = $input[0]
  7427. ;
  7428. if(inputElement) {
  7429. module.verbose('Triggering native change event');
  7430. events.initEvent('change', true, false);
  7431. inputElement.dispatchEvent(events);
  7432. }
  7433. }
  7434. },
  7435. determine: {
  7436. selectAction: function(text, value) {
  7437. selectActionActive = true;
  7438. module.verbose('Determining action', settings.action);
  7439. if( $.isFunction( module.action[settings.action] ) ) {
  7440. module.verbose('Triggering preset action', settings.action, text, value);
  7441. module.action[ settings.action ].call(element, text, value, this);
  7442. }
  7443. else if( $.isFunction(settings.action) ) {
  7444. module.verbose('Triggering user action', settings.action, text, value);
  7445. settings.action.call(element, text, value, this);
  7446. }
  7447. else {
  7448. module.error(error.action, settings.action);
  7449. }
  7450. selectActionActive = false;
  7451. },
  7452. eventInModule: function(event, callback) {
  7453. var
  7454. $target = $(event.target),
  7455. inDocument = ($target.closest(document.documentElement).length > 0),
  7456. inModule = ($target.closest($module).length > 0)
  7457. ;
  7458. callback = $.isFunction(callback)
  7459. ? callback
  7460. : function(){}
  7461. ;
  7462. if(inDocument && !inModule) {
  7463. module.verbose('Triggering event', callback);
  7464. callback();
  7465. return true;
  7466. }
  7467. else {
  7468. module.verbose('Event occurred in dropdown, canceling callback');
  7469. return false;
  7470. }
  7471. },
  7472. eventOnElement: function(event, callback) {
  7473. var
  7474. $target = $(event.target),
  7475. $label = $target.closest(selector.siblingLabel),
  7476. inVisibleDOM = document.body.contains(event.target),
  7477. notOnLabel = ($module.find($label).length === 0 || !(module.is.multiple() && settings.useLabels)),
  7478. notInMenu = ($target.closest($menu).length === 0)
  7479. ;
  7480. callback = $.isFunction(callback)
  7481. ? callback
  7482. : function(){}
  7483. ;
  7484. if(inVisibleDOM && notOnLabel && notInMenu) {
  7485. module.verbose('Triggering event', callback);
  7486. callback();
  7487. return true;
  7488. }
  7489. else {
  7490. module.verbose('Event occurred in dropdown menu, canceling callback');
  7491. return false;
  7492. }
  7493. }
  7494. },
  7495. action: {
  7496. nothing: function() {},
  7497. activate: function(text, value, element) {
  7498. value = (value !== undefined)
  7499. ? value
  7500. : text
  7501. ;
  7502. if( module.can.activate( $(element) ) ) {
  7503. module.set.selected(value, $(element));
  7504. if(!module.is.multiple()) {
  7505. module.hideAndClear();
  7506. }
  7507. }
  7508. },
  7509. select: function(text, value, element) {
  7510. value = (value !== undefined)
  7511. ? value
  7512. : text
  7513. ;
  7514. if( module.can.activate( $(element) ) ) {
  7515. module.set.value(value, text, $(element));
  7516. if(!module.is.multiple()) {
  7517. module.hideAndClear();
  7518. }
  7519. }
  7520. },
  7521. combo: function(text, value, element) {
  7522. value = (value !== undefined)
  7523. ? value
  7524. : text
  7525. ;
  7526. module.set.selected(value, $(element));
  7527. module.hideAndClear();
  7528. },
  7529. hide: function(text, value, element) {
  7530. module.set.value(value, text, $(element));
  7531. module.hideAndClear();
  7532. }
  7533. },
  7534. get: {
  7535. id: function() {
  7536. return id;
  7537. },
  7538. defaultText: function() {
  7539. return $module.data(metadata.defaultText);
  7540. },
  7541. defaultValue: function() {
  7542. return $module.data(metadata.defaultValue);
  7543. },
  7544. placeholderText: function() {
  7545. if(settings.placeholder != 'auto' && typeof settings.placeholder == 'string') {
  7546. return settings.placeholder;
  7547. }
  7548. return $module.data(metadata.placeholderText) || '';
  7549. },
  7550. text: function() {
  7551. return $text.text();
  7552. },
  7553. query: function() {
  7554. return $.trim($search.val());
  7555. },
  7556. searchWidth: function(value) {
  7557. value = (value !== undefined)
  7558. ? value
  7559. : $search.val()
  7560. ;
  7561. $sizer.text(value);
  7562. // prevent rounding issues
  7563. return Math.ceil( $sizer.width() + 1);
  7564. },
  7565. selectionCount: function() {
  7566. var
  7567. values = module.get.values(),
  7568. count
  7569. ;
  7570. count = ( module.is.multiple() )
  7571. ? Array.isArray(values)
  7572. ? values.length
  7573. : 0
  7574. : (module.get.value() !== '')
  7575. ? 1
  7576. : 0
  7577. ;
  7578. return count;
  7579. },
  7580. transition: function($subMenu) {
  7581. return (settings.transition == 'auto')
  7582. ? module.is.upward($subMenu)
  7583. ? 'slide up'
  7584. : 'slide down'
  7585. : settings.transition
  7586. ;
  7587. },
  7588. userValues: function() {
  7589. var
  7590. values = module.get.values()
  7591. ;
  7592. if(!values) {
  7593. return false;
  7594. }
  7595. values = Array.isArray(values)
  7596. ? values
  7597. : [values]
  7598. ;
  7599. return $.grep(values, function(value) {
  7600. return (module.get.item(value) === false);
  7601. });
  7602. },
  7603. uniqueArray: function(array) {
  7604. return $.grep(array, function (value, index) {
  7605. return $.inArray(value, array) === index;
  7606. });
  7607. },
  7608. caretPosition: function(returnEndPos) {
  7609. var
  7610. input = $search.get(0),
  7611. range,
  7612. rangeLength
  7613. ;
  7614. if(returnEndPos && 'selectionEnd' in input){
  7615. return input.selectionEnd;
  7616. }
  7617. else if(!returnEndPos && 'selectionStart' in input) {
  7618. return input.selectionStart;
  7619. }
  7620. if (document.selection) {
  7621. input.focus();
  7622. range = document.selection.createRange();
  7623. rangeLength = range.text.length;
  7624. if(returnEndPos) {
  7625. return rangeLength;
  7626. }
  7627. range.moveStart('character', -input.value.length);
  7628. return range.text.length - rangeLength;
  7629. }
  7630. },
  7631. value: function() {
  7632. var
  7633. value = ($input.length > 0)
  7634. ? $input.val()
  7635. : $module.data(metadata.value),
  7636. isEmptyMultiselect = (Array.isArray(value) && value.length === 1 && value[0] === '')
  7637. ;
  7638. // prevents placeholder element from being selected when multiple
  7639. return (value === undefined || isEmptyMultiselect)
  7640. ? ''
  7641. : value
  7642. ;
  7643. },
  7644. values: function() {
  7645. var
  7646. value = module.get.value()
  7647. ;
  7648. if(value === '') {
  7649. return '';
  7650. }
  7651. return ( !module.has.selectInput() && module.is.multiple() )
  7652. ? (typeof value == 'string') // delimited string
  7653. ? module.escape.htmlEntities(value).split(settings.delimiter)
  7654. : ''
  7655. : value
  7656. ;
  7657. },
  7658. remoteValues: function() {
  7659. var
  7660. values = module.get.values(),
  7661. remoteValues = false
  7662. ;
  7663. if(values) {
  7664. if(typeof values == 'string') {
  7665. values = [values];
  7666. }
  7667. $.each(values, function(index, value) {
  7668. var
  7669. name = module.read.remoteData(value)
  7670. ;
  7671. module.verbose('Restoring value from session data', name, value);
  7672. if(name) {
  7673. if(!remoteValues) {
  7674. remoteValues = {};
  7675. }
  7676. remoteValues[value] = name;
  7677. }
  7678. });
  7679. }
  7680. return remoteValues;
  7681. },
  7682. choiceText: function($choice, preserveHTML) {
  7683. preserveHTML = (preserveHTML !== undefined)
  7684. ? preserveHTML
  7685. : settings.preserveHTML
  7686. ;
  7687. if($choice) {
  7688. if($choice.find(selector.menu).length > 0) {
  7689. module.verbose('Retrieving text of element with sub-menu');
  7690. $choice = $choice.clone();
  7691. $choice.find(selector.menu).remove();
  7692. $choice.find(selector.menuIcon).remove();
  7693. }
  7694. return ($choice.data(metadata.text) !== undefined)
  7695. ? $choice.data(metadata.text)
  7696. : (preserveHTML)
  7697. ? $.trim($choice.html())
  7698. : $.trim($choice.text())
  7699. ;
  7700. }
  7701. },
  7702. choiceValue: function($choice, choiceText) {
  7703. choiceText = choiceText || module.get.choiceText($choice);
  7704. if(!$choice) {
  7705. return false;
  7706. }
  7707. return ($choice.data(metadata.value) !== undefined)
  7708. ? String( $choice.data(metadata.value) )
  7709. : (typeof choiceText === 'string')
  7710. ? $.trim(
  7711. settings.ignoreSearchCase
  7712. ? choiceText.toLowerCase()
  7713. : choiceText
  7714. )
  7715. : String(choiceText)
  7716. ;
  7717. },
  7718. inputEvent: function() {
  7719. var
  7720. input = $search[0]
  7721. ;
  7722. if(input) {
  7723. return (input.oninput !== undefined)
  7724. ? 'input'
  7725. : (input.onpropertychange !== undefined)
  7726. ? 'propertychange'
  7727. : 'keyup'
  7728. ;
  7729. }
  7730. return false;
  7731. },
  7732. selectValues: function() {
  7733. var
  7734. select = {},
  7735. oldGroup = []
  7736. ;
  7737. select.values = [];
  7738. $module
  7739. .find('option')
  7740. .each(function() {
  7741. var
  7742. $option = $(this),
  7743. name = $option.html(),
  7744. disabled = $option.attr('disabled'),
  7745. value = ( $option.attr('value') !== undefined )
  7746. ? $option.attr('value')
  7747. : name,
  7748. group = $option.parent('optgroup')
  7749. ;
  7750. if(settings.placeholder === 'auto' && value === '') {
  7751. select.placeholder = name;
  7752. }
  7753. else {
  7754. if(group.length !== oldGroup.length || group[0] !== oldGroup[0]) {
  7755. select.values.push({
  7756. type: 'header',
  7757. divider: settings.headerDivider,
  7758. name: group.attr('label') || ''
  7759. });
  7760. oldGroup = group;
  7761. }
  7762. select.values.push({
  7763. name : name,
  7764. value : value,
  7765. disabled : disabled
  7766. });
  7767. }
  7768. })
  7769. ;
  7770. if(settings.placeholder && settings.placeholder !== 'auto') {
  7771. module.debug('Setting placeholder value to', settings.placeholder);
  7772. select.placeholder = settings.placeholder;
  7773. }
  7774. if(settings.sortSelect) {
  7775. if(settings.sortSelect === true) {
  7776. select.values.sort(function(a, b) {
  7777. return a.name.localeCompare(b.name);
  7778. });
  7779. } else if(settings.sortSelect === 'natural') {
  7780. select.values.sort(function(a, b) {
  7781. return (a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
  7782. });
  7783. } else if($.isFunction(settings.sortSelect)) {
  7784. select.values.sort(settings.sortSelect);
  7785. }
  7786. module.debug('Retrieved and sorted values from select', select);
  7787. }
  7788. else {
  7789. module.debug('Retrieved values from select', select);
  7790. }
  7791. return select;
  7792. },
  7793. activeItem: function() {
  7794. return $item.filter('.' + className.active);
  7795. },
  7796. selectedItem: function() {
  7797. var
  7798. $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
  7799. ;
  7800. return ($selectedItem.length > 0)
  7801. ? $selectedItem
  7802. : $item.eq(0)
  7803. ;
  7804. },
  7805. itemWithAdditions: function(value) {
  7806. var
  7807. $items = module.get.item(value),
  7808. $userItems = module.create.userChoice(value),
  7809. hasUserItems = ($userItems && $userItems.length > 0)
  7810. ;
  7811. if(hasUserItems) {
  7812. $items = ($items.length > 0)
  7813. ? $items.add($userItems)
  7814. : $userItems
  7815. ;
  7816. }
  7817. return $items;
  7818. },
  7819. item: function(value, strict) {
  7820. var
  7821. $selectedItem = false,
  7822. shouldSearch,
  7823. isMultiple
  7824. ;
  7825. value = (value !== undefined)
  7826. ? value
  7827. : ( module.get.values() !== undefined)
  7828. ? module.get.values()
  7829. : module.get.text()
  7830. ;
  7831. isMultiple = (module.is.multiple() && Array.isArray(value));
  7832. shouldSearch = (isMultiple)
  7833. ? (value.length > 0)
  7834. : (value !== undefined && value !== null)
  7835. ;
  7836. strict = (value === '' || value === false || value === true)
  7837. ? true
  7838. : strict || false
  7839. ;
  7840. if(shouldSearch) {
  7841. $item
  7842. .each(function() {
  7843. var
  7844. $choice = $(this),
  7845. optionText = module.get.choiceText($choice),
  7846. optionValue = module.get.choiceValue($choice, optionText)
  7847. ;
  7848. // safe early exit
  7849. if(optionValue === null || optionValue === undefined) {
  7850. return;
  7851. }
  7852. if(isMultiple) {
  7853. if($.inArray( String(optionValue), value) !== -1) {
  7854. $selectedItem = ($selectedItem)
  7855. ? $selectedItem.add($choice)
  7856. : $choice
  7857. ;
  7858. }
  7859. }
  7860. else if(strict) {
  7861. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  7862. if( optionValue === value) {
  7863. $selectedItem = $choice;
  7864. return true;
  7865. }
  7866. }
  7867. else {
  7868. if(settings.ignoreCase) {
  7869. optionValue = optionValue.toLowerCase();
  7870. value = value.toLowerCase();
  7871. }
  7872. if( String(optionValue) == String(value)) {
  7873. module.verbose('Found select item by value', optionValue, value);
  7874. $selectedItem = $choice;
  7875. return true;
  7876. }
  7877. }
  7878. })
  7879. ;
  7880. }
  7881. return $selectedItem;
  7882. }
  7883. },
  7884. check: {
  7885. maxSelections: function(selectionCount) {
  7886. if(settings.maxSelections) {
  7887. selectionCount = (selectionCount !== undefined)
  7888. ? selectionCount
  7889. : module.get.selectionCount()
  7890. ;
  7891. if(selectionCount >= settings.maxSelections) {
  7892. module.debug('Maximum selection count reached');
  7893. if(settings.useLabels) {
  7894. $item.addClass(className.filtered);
  7895. module.add.message(message.maxSelections);
  7896. }
  7897. return true;
  7898. }
  7899. else {
  7900. module.verbose('No longer at maximum selection count');
  7901. module.remove.message();
  7902. module.remove.filteredItem();
  7903. if(module.is.searchSelection()) {
  7904. module.filterItems();
  7905. }
  7906. return false;
  7907. }
  7908. }
  7909. return true;
  7910. }
  7911. },
  7912. restore: {
  7913. defaults: function(preventChangeTrigger) {
  7914. module.clear(preventChangeTrigger);
  7915. module.restore.defaultText();
  7916. module.restore.defaultValue();
  7917. },
  7918. defaultText: function() {
  7919. var
  7920. defaultText = module.get.defaultText(),
  7921. placeholderText = module.get.placeholderText
  7922. ;
  7923. if(defaultText === placeholderText) {
  7924. module.debug('Restoring default placeholder text', defaultText);
  7925. module.set.placeholderText(defaultText);
  7926. }
  7927. else {
  7928. module.debug('Restoring default text', defaultText);
  7929. module.set.text(defaultText);
  7930. }
  7931. },
  7932. placeholderText: function() {
  7933. module.set.placeholderText();
  7934. },
  7935. defaultValue: function() {
  7936. var
  7937. defaultValue = module.get.defaultValue()
  7938. ;
  7939. if(defaultValue !== undefined) {
  7940. module.debug('Restoring default value', defaultValue);
  7941. if(defaultValue !== '') {
  7942. module.set.value(defaultValue);
  7943. module.set.selected();
  7944. }
  7945. else {
  7946. module.remove.activeItem();
  7947. module.remove.selectedItem();
  7948. }
  7949. }
  7950. },
  7951. labels: function() {
  7952. if(settings.allowAdditions) {
  7953. if(!settings.useLabels) {
  7954. module.error(error.labels);
  7955. settings.useLabels = true;
  7956. }
  7957. module.debug('Restoring selected values');
  7958. module.create.userLabels();
  7959. }
  7960. module.check.maxSelections();
  7961. },
  7962. selected: function() {
  7963. module.restore.values();
  7964. if(module.is.multiple()) {
  7965. module.debug('Restoring previously selected values and labels');
  7966. module.restore.labels();
  7967. }
  7968. else {
  7969. module.debug('Restoring previously selected values');
  7970. }
  7971. },
  7972. values: function() {
  7973. // prevents callbacks from occurring on initial load
  7974. module.set.initialLoad();
  7975. if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) {
  7976. module.restore.remoteValues();
  7977. }
  7978. else {
  7979. module.set.selected();
  7980. }
  7981. var value = module.get.value();
  7982. if(value && value !== '' && !(Array.isArray(value) && value.length === 0)) {
  7983. $input.removeClass(className.noselection);
  7984. } else {
  7985. $input.addClass(className.noselection);
  7986. }
  7987. module.remove.initialLoad();
  7988. },
  7989. remoteValues: function() {
  7990. var
  7991. values = module.get.remoteValues()
  7992. ;
  7993. module.debug('Recreating selected from session data', values);
  7994. if(values) {
  7995. if( module.is.single() ) {
  7996. $.each(values, function(value, name) {
  7997. module.set.text(name);
  7998. });
  7999. }
  8000. else {
  8001. $.each(values, function(value, name) {
  8002. module.add.label(value, name);
  8003. });
  8004. }
  8005. }
  8006. }
  8007. },
  8008. read: {
  8009. remoteData: function(value) {
  8010. var
  8011. name
  8012. ;
  8013. if(window.Storage === undefined) {
  8014. module.error(error.noStorage);
  8015. return;
  8016. }
  8017. name = sessionStorage.getItem(value);
  8018. return (name !== undefined)
  8019. ? name
  8020. : false
  8021. ;
  8022. }
  8023. },
  8024. save: {
  8025. defaults: function() {
  8026. module.save.defaultText();
  8027. module.save.placeholderText();
  8028. module.save.defaultValue();
  8029. },
  8030. defaultValue: function() {
  8031. var
  8032. value = module.get.value()
  8033. ;
  8034. module.verbose('Saving default value as', value);
  8035. $module.data(metadata.defaultValue, value);
  8036. },
  8037. defaultText: function() {
  8038. var
  8039. text = module.get.text()
  8040. ;
  8041. module.verbose('Saving default text as', text);
  8042. $module.data(metadata.defaultText, text);
  8043. },
  8044. placeholderText: function() {
  8045. var
  8046. text
  8047. ;
  8048. if(settings.placeholder !== false && $text.hasClass(className.placeholder)) {
  8049. text = module.get.text();
  8050. module.verbose('Saving placeholder text as', text);
  8051. $module.data(metadata.placeholderText, text);
  8052. }
  8053. },
  8054. remoteData: function(name, value) {
  8055. if(window.Storage === undefined) {
  8056. module.error(error.noStorage);
  8057. return;
  8058. }
  8059. module.verbose('Saving remote data to session storage', value, name);
  8060. sessionStorage.setItem(value, name);
  8061. }
  8062. },
  8063. clear: function(preventChangeTrigger) {
  8064. if(module.is.multiple() && settings.useLabels) {
  8065. module.remove.labels();
  8066. }
  8067. else {
  8068. module.remove.activeItem();
  8069. module.remove.selectedItem();
  8070. module.remove.filteredItem();
  8071. }
  8072. module.set.placeholderText();
  8073. module.clearValue(preventChangeTrigger);
  8074. },
  8075. clearValue: function(preventChangeTrigger) {
  8076. module.set.value('', null, null, preventChangeTrigger);
  8077. },
  8078. scrollPage: function(direction, $selectedItem) {
  8079. var
  8080. $currentItem = $selectedItem || module.get.selectedItem(),
  8081. $menu = $currentItem.closest(selector.menu),
  8082. menuHeight = $menu.outerHeight(),
  8083. currentScroll = $menu.scrollTop(),
  8084. itemHeight = $item.eq(0).outerHeight(),
  8085. itemsPerPage = Math.floor(menuHeight / itemHeight),
  8086. maxScroll = $menu.prop('scrollHeight'),
  8087. newScroll = (direction == 'up')
  8088. ? currentScroll - (itemHeight * itemsPerPage)
  8089. : currentScroll + (itemHeight * itemsPerPage),
  8090. $selectableItem = $item.not(selector.unselectable),
  8091. isWithinRange,
  8092. $nextSelectedItem,
  8093. elementIndex
  8094. ;
  8095. elementIndex = (direction == 'up')
  8096. ? $selectableItem.index($currentItem) - itemsPerPage
  8097. : $selectableItem.index($currentItem) + itemsPerPage
  8098. ;
  8099. isWithinRange = (direction == 'up')
  8100. ? (elementIndex >= 0)
  8101. : (elementIndex < $selectableItem.length)
  8102. ;
  8103. $nextSelectedItem = (isWithinRange)
  8104. ? $selectableItem.eq(elementIndex)
  8105. : (direction == 'up')
  8106. ? $selectableItem.first()
  8107. : $selectableItem.last()
  8108. ;
  8109. if($nextSelectedItem.length > 0) {
  8110. module.debug('Scrolling page', direction, $nextSelectedItem);
  8111. $currentItem
  8112. .removeClass(className.selected)
  8113. ;
  8114. $nextSelectedItem
  8115. .addClass(className.selected)
  8116. ;
  8117. if(settings.selectOnKeydown && module.is.single()) {
  8118. module.set.selectedItem($nextSelectedItem);
  8119. }
  8120. $menu
  8121. .scrollTop(newScroll)
  8122. ;
  8123. }
  8124. },
  8125. set: {
  8126. filtered: function() {
  8127. var
  8128. isMultiple = module.is.multiple(),
  8129. isSearch = module.is.searchSelection(),
  8130. isSearchMultiple = (isMultiple && isSearch),
  8131. searchValue = (isSearch)
  8132. ? module.get.query()
  8133. : '',
  8134. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
  8135. searchWidth = module.get.searchWidth(),
  8136. valueIsSet = searchValue !== ''
  8137. ;
  8138. if(isMultiple && hasSearchValue) {
  8139. module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
  8140. $search.css('width', searchWidth);
  8141. }
  8142. if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
  8143. module.verbose('Hiding placeholder text');
  8144. $text.addClass(className.filtered);
  8145. }
  8146. else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
  8147. module.verbose('Showing placeholder text');
  8148. $text.removeClass(className.filtered);
  8149. }
  8150. },
  8151. empty: function() {
  8152. $module.addClass(className.empty);
  8153. },
  8154. loading: function() {
  8155. $module.addClass(className.loading);
  8156. },
  8157. placeholderText: function(text) {
  8158. text = text || module.get.placeholderText();
  8159. module.debug('Setting placeholder text', text);
  8160. module.set.text(text);
  8161. $text.addClass(className.placeholder);
  8162. },
  8163. tabbable: function() {
  8164. if( module.is.searchSelection() ) {
  8165. module.debug('Added tabindex to searchable dropdown');
  8166. $search
  8167. .val('')
  8168. .attr('tabindex', 0)
  8169. ;
  8170. $menu
  8171. .attr('tabindex', -1)
  8172. ;
  8173. }
  8174. else {
  8175. module.debug('Added tabindex to dropdown');
  8176. if( $module.attr('tabindex') === undefined) {
  8177. $module
  8178. .attr('tabindex', 0)
  8179. ;
  8180. $menu
  8181. .attr('tabindex', -1)
  8182. ;
  8183. }
  8184. }
  8185. },
  8186. initialLoad: function() {
  8187. module.verbose('Setting initial load');
  8188. initialLoad = true;
  8189. },
  8190. activeItem: function($item) {
  8191. if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) {
  8192. $item.addClass(className.filtered);
  8193. }
  8194. else {
  8195. $item.addClass(className.active);
  8196. }
  8197. },
  8198. partialSearch: function(text) {
  8199. var
  8200. length = module.get.query().length
  8201. ;
  8202. $search.val( text.substr(0, length));
  8203. },
  8204. scrollPosition: function($item, forceScroll) {
  8205. var
  8206. edgeTolerance = 5,
  8207. $menu,
  8208. hasActive,
  8209. offset,
  8210. itemHeight,
  8211. itemOffset,
  8212. menuOffset,
  8213. menuScroll,
  8214. menuHeight,
  8215. abovePage,
  8216. belowPage
  8217. ;
  8218. $item = $item || module.get.selectedItem();
  8219. $menu = $item.closest(selector.menu);
  8220. hasActive = ($item && $item.length > 0);
  8221. forceScroll = (forceScroll !== undefined)
  8222. ? forceScroll
  8223. : false
  8224. ;
  8225. if(module.get.activeItem().length === 0){
  8226. forceScroll = false;
  8227. }
  8228. if($item && $menu.length > 0 && hasActive) {
  8229. itemOffset = $item.position().top;
  8230. $menu.addClass(className.loading);
  8231. menuScroll = $menu.scrollTop();
  8232. menuOffset = $menu.offset().top;
  8233. itemOffset = $item.offset().top;
  8234. offset = menuScroll - menuOffset + itemOffset;
  8235. if(!forceScroll) {
  8236. menuHeight = $menu.height();
  8237. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  8238. abovePage = ((offset - edgeTolerance) < menuScroll);
  8239. }
  8240. module.debug('Scrolling to active item', offset);
  8241. if(forceScroll || abovePage || belowPage) {
  8242. $menu.scrollTop(offset);
  8243. }
  8244. $menu.removeClass(className.loading);
  8245. }
  8246. },
  8247. text: function(text) {
  8248. if(settings.action === 'combo') {
  8249. module.debug('Changing combo button text', text, $combo);
  8250. if(settings.preserveHTML) {
  8251. $combo.html(text);
  8252. }
  8253. else {
  8254. $combo.text(text);
  8255. }
  8256. }
  8257. else if(settings.action === 'activate') {
  8258. if(text !== module.get.placeholderText()) {
  8259. $text.removeClass(className.placeholder);
  8260. }
  8261. module.debug('Changing text', text, $text);
  8262. $text
  8263. .removeClass(className.filtered)
  8264. ;
  8265. if(settings.preserveHTML) {
  8266. $text.html(text);
  8267. }
  8268. else {
  8269. $text.text(text);
  8270. }
  8271. }
  8272. },
  8273. selectedItem: function($item) {
  8274. var
  8275. value = module.get.choiceValue($item),
  8276. searchText = module.get.choiceText($item, false),
  8277. text = module.get.choiceText($item, true)
  8278. ;
  8279. module.debug('Setting user selection to item', $item);
  8280. module.remove.activeItem();
  8281. module.set.partialSearch(searchText);
  8282. module.set.activeItem($item);
  8283. module.set.selected(value, $item);
  8284. module.set.text(text);
  8285. },
  8286. selectedLetter: function(letter) {
  8287. var
  8288. $selectedItem = $item.filter('.' + className.selected),
  8289. alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter),
  8290. $nextValue = false,
  8291. $nextItem
  8292. ;
  8293. // check next of same letter
  8294. if(alreadySelectedLetter) {
  8295. $nextItem = $selectedItem.nextAll($item).eq(0);
  8296. if( module.has.firstLetter($nextItem, letter) ) {
  8297. $nextValue = $nextItem;
  8298. }
  8299. }
  8300. // check all values
  8301. if(!$nextValue) {
  8302. $item
  8303. .each(function(){
  8304. if(module.has.firstLetter($(this), letter)) {
  8305. $nextValue = $(this);
  8306. return false;
  8307. }
  8308. })
  8309. ;
  8310. }
  8311. // set next value
  8312. if($nextValue) {
  8313. module.verbose('Scrolling to next value with letter', letter);
  8314. module.set.scrollPosition($nextValue);
  8315. $selectedItem.removeClass(className.selected);
  8316. $nextValue.addClass(className.selected);
  8317. if(settings.selectOnKeydown && module.is.single()) {
  8318. module.set.selectedItem($nextValue);
  8319. }
  8320. }
  8321. },
  8322. direction: function($menu) {
  8323. if(settings.direction == 'auto') {
  8324. // reset position, remove upward if it's base menu
  8325. if (!$menu) {
  8326. module.remove.upward();
  8327. } else if (module.is.upward($menu)) {
  8328. //we need make sure when make assertion openDownward for $menu, $menu does not have upward class
  8329. module.remove.upward($menu);
  8330. }
  8331. if(module.can.openDownward($menu)) {
  8332. module.remove.upward($menu);
  8333. }
  8334. else {
  8335. module.set.upward($menu);
  8336. }
  8337. if(!module.is.leftward($menu) && !module.can.openRightward($menu)) {
  8338. module.set.leftward($menu);
  8339. }
  8340. }
  8341. else if(settings.direction == 'upward') {
  8342. module.set.upward($menu);
  8343. }
  8344. },
  8345. upward: function($currentMenu) {
  8346. var $element = $currentMenu || $module;
  8347. $element.addClass(className.upward);
  8348. },
  8349. leftward: function($currentMenu) {
  8350. var $element = $currentMenu || $menu;
  8351. $element.addClass(className.leftward);
  8352. },
  8353. value: function(value, text, $selected, preventChangeTrigger) {
  8354. if(value !== undefined && value !== '' && !(Array.isArray(value) && value.length === 0)) {
  8355. $input.removeClass(className.noselection);
  8356. } else {
  8357. $input.addClass(className.noselection);
  8358. }
  8359. var
  8360. escapedValue = module.escape.value(value),
  8361. hasInput = ($input.length > 0),
  8362. currentValue = module.get.values(),
  8363. stringValue = (value !== undefined)
  8364. ? String(value)
  8365. : value,
  8366. newValue
  8367. ;
  8368. if(hasInput) {
  8369. if(!settings.allowReselection && stringValue == currentValue) {
  8370. module.verbose('Skipping value update already same value', value, currentValue);
  8371. if(!module.is.initialLoad()) {
  8372. return;
  8373. }
  8374. }
  8375. if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) {
  8376. module.debug('Adding user option', value);
  8377. module.add.optionValue(value);
  8378. }
  8379. module.debug('Updating input value', escapedValue, currentValue);
  8380. internalChange = true;
  8381. $input
  8382. .val(escapedValue)
  8383. ;
  8384. if(settings.fireOnInit === false && module.is.initialLoad()) {
  8385. module.debug('Input native change event ignored on initial load');
  8386. }
  8387. else if(preventChangeTrigger !== true) {
  8388. module.trigger.change();
  8389. }
  8390. internalChange = false;
  8391. }
  8392. else {
  8393. module.verbose('Storing value in metadata', escapedValue, $input);
  8394. if(escapedValue !== currentValue) {
  8395. $module.data(metadata.value, stringValue);
  8396. }
  8397. }
  8398. if(settings.fireOnInit === false && module.is.initialLoad()) {
  8399. module.verbose('No callback on initial load', settings.onChange);
  8400. }
  8401. else if(preventChangeTrigger !== true) {
  8402. settings.onChange.call(element, value, text, $selected);
  8403. }
  8404. },
  8405. active: function() {
  8406. $module
  8407. .addClass(className.active)
  8408. ;
  8409. },
  8410. multiple: function() {
  8411. $module.addClass(className.multiple);
  8412. },
  8413. visible: function() {
  8414. $module.addClass(className.visible);
  8415. },
  8416. exactly: function(value, $selectedItem) {
  8417. module.debug('Setting selected to exact values');
  8418. module.clear();
  8419. module.set.selected(value, $selectedItem);
  8420. },
  8421. selected: function(value, $selectedItem) {
  8422. var
  8423. isMultiple = module.is.multiple()
  8424. ;
  8425. $selectedItem = (settings.allowAdditions)
  8426. ? $selectedItem || module.get.itemWithAdditions(value)
  8427. : $selectedItem || module.get.item(value)
  8428. ;
  8429. if(!$selectedItem) {
  8430. return;
  8431. }
  8432. module.debug('Setting selected menu item to', $selectedItem);
  8433. if(module.is.multiple()) {
  8434. module.remove.searchWidth();
  8435. }
  8436. if(module.is.single()) {
  8437. module.remove.activeItem();
  8438. module.remove.selectedItem();
  8439. }
  8440. else if(settings.useLabels) {
  8441. module.remove.selectedItem();
  8442. }
  8443. // select each item
  8444. $selectedItem
  8445. .each(function() {
  8446. var
  8447. $selected = $(this),
  8448. selectedText = module.get.choiceText($selected),
  8449. selectedValue = module.get.choiceValue($selected, selectedText),
  8450. isFiltered = $selected.hasClass(className.filtered),
  8451. isActive = $selected.hasClass(className.active),
  8452. isUserValue = $selected.hasClass(className.addition),
  8453. shouldAnimate = (isMultiple && $selectedItem.length == 1)
  8454. ;
  8455. if(isMultiple) {
  8456. if(!isActive || isUserValue) {
  8457. if(settings.apiSettings && settings.saveRemoteData) {
  8458. module.save.remoteData(selectedText, selectedValue);
  8459. }
  8460. if(settings.useLabels) {
  8461. module.add.label(selectedValue, selectedText, shouldAnimate);
  8462. module.add.value(selectedValue, selectedText, $selected);
  8463. module.set.activeItem($selected);
  8464. module.filterActive();
  8465. module.select.nextAvailable($selectedItem);
  8466. }
  8467. else {
  8468. module.add.value(selectedValue, selectedText, $selected);
  8469. module.set.text(module.add.variables(message.count));
  8470. module.set.activeItem($selected);
  8471. }
  8472. }
  8473. else if(!isFiltered && (settings.useLabels || selectActionActive)) {
  8474. module.debug('Selected active value, removing label');
  8475. module.remove.selected(selectedValue);
  8476. }
  8477. }
  8478. else {
  8479. if(settings.apiSettings && settings.saveRemoteData) {
  8480. module.save.remoteData(selectedText, selectedValue);
  8481. }
  8482. module.set.text(selectedText);
  8483. module.set.value(selectedValue, selectedText, $selected);
  8484. $selected
  8485. .addClass(className.active)
  8486. .addClass(className.selected)
  8487. ;
  8488. }
  8489. })
  8490. ;
  8491. module.remove.searchTerm();
  8492. }
  8493. },
  8494. add: {
  8495. label: function(value, text, shouldAnimate) {
  8496. var
  8497. $next = module.is.searchSelection()
  8498. ? $search
  8499. : $text,
  8500. escapedValue = module.escape.value(value),
  8501. $label
  8502. ;
  8503. if(settings.ignoreCase) {
  8504. escapedValue = escapedValue.toLowerCase();
  8505. }
  8506. $label = $('<a />')
  8507. .addClass(className.label)
  8508. .attr('data-' + metadata.value, escapedValue)
  8509. .html(templates.label(escapedValue, text, settings.preserveHTML, settings.className))
  8510. ;
  8511. $label = settings.onLabelCreate.call($label, escapedValue, text);
  8512. if(module.has.label(value)) {
  8513. module.debug('User selection already exists, skipping', escapedValue);
  8514. return;
  8515. }
  8516. if(settings.label.variation) {
  8517. $label.addClass(settings.label.variation);
  8518. }
  8519. if(shouldAnimate === true) {
  8520. module.debug('Animating in label', $label);
  8521. $label
  8522. .addClass(className.hidden)
  8523. .insertBefore($next)
  8524. .transition({
  8525. animation : settings.label.transition,
  8526. debug : settings.debug,
  8527. verbose : settings.verbose,
  8528. duration : settings.label.duration
  8529. })
  8530. ;
  8531. }
  8532. else {
  8533. module.debug('Adding selection label', $label);
  8534. $label
  8535. .insertBefore($next)
  8536. ;
  8537. }
  8538. },
  8539. message: function(message) {
  8540. var
  8541. $message = $menu.children(selector.message),
  8542. html = settings.templates.message(module.add.variables(message))
  8543. ;
  8544. if($message.length > 0) {
  8545. $message
  8546. .html(html)
  8547. ;
  8548. }
  8549. else {
  8550. $message = $('<div/>')
  8551. .html(html)
  8552. .addClass(className.message)
  8553. .appendTo($menu)
  8554. ;
  8555. }
  8556. },
  8557. optionValue: function(value) {
  8558. var
  8559. escapedValue = module.escape.value(value),
  8560. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  8561. hasOption = ($option.length > 0)
  8562. ;
  8563. if(hasOption) {
  8564. return;
  8565. }
  8566. // temporarily disconnect observer
  8567. module.disconnect.selectObserver();
  8568. if( module.is.single() ) {
  8569. module.verbose('Removing previous user addition');
  8570. $input.find('option.' + className.addition).remove();
  8571. }
  8572. $('<option/>')
  8573. .prop('value', escapedValue)
  8574. .addClass(className.addition)
  8575. .html(value)
  8576. .appendTo($input)
  8577. ;
  8578. module.verbose('Adding user addition as an <option>', value);
  8579. module.observe.select();
  8580. },
  8581. userSuggestion: function(value) {
  8582. var
  8583. $addition = $menu.children(selector.addition),
  8584. $existingItem = module.get.item(value),
  8585. alreadyHasValue = $existingItem && $existingItem.not(selector.addition).length,
  8586. hasUserSuggestion = $addition.length > 0,
  8587. html
  8588. ;
  8589. if(settings.useLabels && module.has.maxSelections()) {
  8590. return;
  8591. }
  8592. if(value === '' || alreadyHasValue) {
  8593. $addition.remove();
  8594. return;
  8595. }
  8596. if(hasUserSuggestion) {
  8597. $addition
  8598. .data(metadata.value, value)
  8599. .data(metadata.text, value)
  8600. .attr('data-' + metadata.value, value)
  8601. .attr('data-' + metadata.text, value)
  8602. .removeClass(className.filtered)
  8603. ;
  8604. if(!settings.hideAdditions) {
  8605. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  8606. $addition
  8607. .html(html)
  8608. ;
  8609. }
  8610. module.verbose('Replacing user suggestion with new value', $addition);
  8611. }
  8612. else {
  8613. $addition = module.create.userChoice(value);
  8614. $addition
  8615. .prependTo($menu)
  8616. ;
  8617. module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
  8618. }
  8619. if(!settings.hideAdditions || module.is.allFiltered()) {
  8620. $addition
  8621. .addClass(className.selected)
  8622. .siblings()
  8623. .removeClass(className.selected)
  8624. ;
  8625. }
  8626. module.refreshItems();
  8627. },
  8628. variables: function(message, term) {
  8629. var
  8630. hasCount = (message.search('{count}') !== -1),
  8631. hasMaxCount = (message.search('{maxCount}') !== -1),
  8632. hasTerm = (message.search('{term}') !== -1),
  8633. count,
  8634. query
  8635. ;
  8636. module.verbose('Adding templated variables to message', message);
  8637. if(hasCount) {
  8638. count = module.get.selectionCount();
  8639. message = message.replace('{count}', count);
  8640. }
  8641. if(hasMaxCount) {
  8642. count = module.get.selectionCount();
  8643. message = message.replace('{maxCount}', settings.maxSelections);
  8644. }
  8645. if(hasTerm) {
  8646. query = term || module.get.query();
  8647. message = message.replace('{term}', query);
  8648. }
  8649. return message;
  8650. },
  8651. value: function(addedValue, addedText, $selectedItem) {
  8652. var
  8653. currentValue = module.get.values(),
  8654. newValue
  8655. ;
  8656. if(module.has.value(addedValue)) {
  8657. module.debug('Value already selected');
  8658. return;
  8659. }
  8660. if(addedValue === '') {
  8661. module.debug('Cannot select blank values from multiselect');
  8662. return;
  8663. }
  8664. // extend current array
  8665. if(Array.isArray(currentValue)) {
  8666. newValue = currentValue.concat([addedValue]);
  8667. newValue = module.get.uniqueArray(newValue);
  8668. }
  8669. else {
  8670. newValue = [addedValue];
  8671. }
  8672. // add values
  8673. if( module.has.selectInput() ) {
  8674. if(module.can.extendSelect()) {
  8675. module.debug('Adding value to select', addedValue, newValue, $input);
  8676. module.add.optionValue(addedValue);
  8677. }
  8678. }
  8679. else {
  8680. newValue = newValue.join(settings.delimiter);
  8681. module.debug('Setting hidden input to delimited value', newValue, $input);
  8682. }
  8683. if(settings.fireOnInit === false && module.is.initialLoad()) {
  8684. module.verbose('Skipping onadd callback on initial load', settings.onAdd);
  8685. }
  8686. else {
  8687. settings.onAdd.call(element, addedValue, addedText, $selectedItem);
  8688. }
  8689. module.set.value(newValue, addedText, $selectedItem);
  8690. module.check.maxSelections();
  8691. },
  8692. },
  8693. remove: {
  8694. active: function() {
  8695. $module.removeClass(className.active);
  8696. },
  8697. activeLabel: function() {
  8698. $module.find(selector.label).removeClass(className.active);
  8699. },
  8700. empty: function() {
  8701. $module.removeClass(className.empty);
  8702. },
  8703. loading: function() {
  8704. $module.removeClass(className.loading);
  8705. },
  8706. initialLoad: function() {
  8707. initialLoad = false;
  8708. },
  8709. upward: function($currentMenu) {
  8710. var $element = $currentMenu || $module;
  8711. $element.removeClass(className.upward);
  8712. },
  8713. leftward: function($currentMenu) {
  8714. var $element = $currentMenu || $menu;
  8715. $element.removeClass(className.leftward);
  8716. },
  8717. visible: function() {
  8718. $module.removeClass(className.visible);
  8719. },
  8720. activeItem: function() {
  8721. $item.removeClass(className.active);
  8722. },
  8723. filteredItem: function() {
  8724. if(settings.useLabels && module.has.maxSelections() ) {
  8725. return;
  8726. }
  8727. if(settings.useLabels && module.is.multiple()) {
  8728. $item.not('.' + className.active).removeClass(className.filtered);
  8729. }
  8730. else {
  8731. $item.removeClass(className.filtered);
  8732. }
  8733. if(settings.hideDividers) {
  8734. $divider.removeClass(className.hidden);
  8735. }
  8736. module.remove.empty();
  8737. },
  8738. optionValue: function(value) {
  8739. var
  8740. escapedValue = module.escape.value(value),
  8741. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  8742. hasOption = ($option.length > 0)
  8743. ;
  8744. if(!hasOption || !$option.hasClass(className.addition)) {
  8745. return;
  8746. }
  8747. // temporarily disconnect observer
  8748. if(selectObserver) {
  8749. selectObserver.disconnect();
  8750. module.verbose('Temporarily disconnecting mutation observer');
  8751. }
  8752. $option.remove();
  8753. module.verbose('Removing user addition as an <option>', escapedValue);
  8754. if(selectObserver) {
  8755. selectObserver.observe($input[0], {
  8756. childList : true,
  8757. subtree : true
  8758. });
  8759. }
  8760. },
  8761. message: function() {
  8762. $menu.children(selector.message).remove();
  8763. },
  8764. searchWidth: function() {
  8765. $search.css('width', '');
  8766. },
  8767. searchTerm: function() {
  8768. module.verbose('Cleared search term');
  8769. $search.val('');
  8770. module.set.filtered();
  8771. },
  8772. userAddition: function() {
  8773. $item.filter(selector.addition).remove();
  8774. },
  8775. selected: function(value, $selectedItem) {
  8776. $selectedItem = (settings.allowAdditions)
  8777. ? $selectedItem || module.get.itemWithAdditions(value)
  8778. : $selectedItem || module.get.item(value)
  8779. ;
  8780. if(!$selectedItem) {
  8781. return false;
  8782. }
  8783. $selectedItem
  8784. .each(function() {
  8785. var
  8786. $selected = $(this),
  8787. selectedText = module.get.choiceText($selected),
  8788. selectedValue = module.get.choiceValue($selected, selectedText)
  8789. ;
  8790. if(module.is.multiple()) {
  8791. if(settings.useLabels) {
  8792. module.remove.value(selectedValue, selectedText, $selected);
  8793. module.remove.label(selectedValue);
  8794. }
  8795. else {
  8796. module.remove.value(selectedValue, selectedText, $selected);
  8797. if(module.get.selectionCount() === 0) {
  8798. module.set.placeholderText();
  8799. }
  8800. else {
  8801. module.set.text(module.add.variables(message.count));
  8802. }
  8803. }
  8804. }
  8805. else {
  8806. module.remove.value(selectedValue, selectedText, $selected);
  8807. }
  8808. $selected
  8809. .removeClass(className.filtered)
  8810. .removeClass(className.active)
  8811. ;
  8812. if(settings.useLabels) {
  8813. $selected.removeClass(className.selected);
  8814. }
  8815. })
  8816. ;
  8817. },
  8818. selectedItem: function() {
  8819. $item.removeClass(className.selected);
  8820. },
  8821. value: function(removedValue, removedText, $removedItem) {
  8822. var
  8823. values = module.get.values(),
  8824. newValue
  8825. ;
  8826. if( module.has.selectInput() ) {
  8827. module.verbose('Input is <select> removing selected option', removedValue);
  8828. newValue = module.remove.arrayValue(removedValue, values);
  8829. module.remove.optionValue(removedValue);
  8830. }
  8831. else {
  8832. module.verbose('Removing from delimited values', removedValue);
  8833. newValue = module.remove.arrayValue(removedValue, values);
  8834. newValue = newValue.join(settings.delimiter);
  8835. }
  8836. if(settings.fireOnInit === false && module.is.initialLoad()) {
  8837. module.verbose('No callback on initial load', settings.onRemove);
  8838. }
  8839. else {
  8840. settings.onRemove.call(element, removedValue, removedText, $removedItem);
  8841. }
  8842. module.set.value(newValue, removedText, $removedItem);
  8843. module.check.maxSelections();
  8844. },
  8845. arrayValue: function(removedValue, values) {
  8846. if( !Array.isArray(values) ) {
  8847. values = [values];
  8848. }
  8849. values = $.grep(values, function(value){
  8850. return (removedValue != value);
  8851. });
  8852. module.verbose('Removed value from delimited string', removedValue, values);
  8853. return values;
  8854. },
  8855. label: function(value, shouldAnimate) {
  8856. var
  8857. $labels = $module.find(selector.label),
  8858. $removedLabel = $labels.filter('[data-' + metadata.value + '="' + module.escape.string(settings.ignoreCase ? value.toLowerCase() : value) +'"]')
  8859. ;
  8860. module.verbose('Removing label', $removedLabel);
  8861. $removedLabel.remove();
  8862. },
  8863. activeLabels: function($activeLabels) {
  8864. $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
  8865. module.verbose('Removing active label selections', $activeLabels);
  8866. module.remove.labels($activeLabels);
  8867. },
  8868. labels: function($labels) {
  8869. $labels = $labels || $module.find(selector.label);
  8870. module.verbose('Removing labels', $labels);
  8871. $labels
  8872. .each(function(){
  8873. var
  8874. $label = $(this),
  8875. value = $label.data(metadata.value),
  8876. stringValue = (value !== undefined)
  8877. ? String(value)
  8878. : value,
  8879. isUserValue = module.is.userValue(stringValue)
  8880. ;
  8881. if(settings.onLabelRemove.call($label, value) === false) {
  8882. module.debug('Label remove callback cancelled removal');
  8883. return;
  8884. }
  8885. module.remove.message();
  8886. if(isUserValue) {
  8887. module.remove.value(stringValue);
  8888. module.remove.label(stringValue);
  8889. }
  8890. else {
  8891. // selected will also remove label
  8892. module.remove.selected(stringValue);
  8893. }
  8894. })
  8895. ;
  8896. },
  8897. tabbable: function() {
  8898. if( module.is.searchSelection() ) {
  8899. module.debug('Searchable dropdown initialized');
  8900. $search
  8901. .removeAttr('tabindex')
  8902. ;
  8903. $menu
  8904. .removeAttr('tabindex')
  8905. ;
  8906. }
  8907. else {
  8908. module.debug('Simple selection dropdown initialized');
  8909. $module
  8910. .removeAttr('tabindex')
  8911. ;
  8912. $menu
  8913. .removeAttr('tabindex')
  8914. ;
  8915. }
  8916. },
  8917. diacritics: function(text) {
  8918. return settings.ignoreDiacritics ? text.normalize('NFD').replace(/[\u0300-\u036f]/g, '') : text;
  8919. }
  8920. },
  8921. has: {
  8922. menuSearch: function() {
  8923. return (module.has.search() && $search.closest($menu).length > 0);
  8924. },
  8925. clearItem: function() {
  8926. return ($clear.length > 0);
  8927. },
  8928. search: function() {
  8929. return ($search.length > 0);
  8930. },
  8931. sizer: function() {
  8932. return ($sizer.length > 0);
  8933. },
  8934. selectInput: function() {
  8935. return ( $input.is('select') );
  8936. },
  8937. minCharacters: function(searchTerm) {
  8938. if(settings.minCharacters && !iconClicked) {
  8939. searchTerm = (searchTerm !== undefined)
  8940. ? String(searchTerm)
  8941. : String(module.get.query())
  8942. ;
  8943. return (searchTerm.length >= settings.minCharacters);
  8944. }
  8945. iconClicked=false;
  8946. return true;
  8947. },
  8948. firstLetter: function($item, letter) {
  8949. var
  8950. text,
  8951. firstLetter
  8952. ;
  8953. if(!$item || $item.length === 0 || typeof letter !== 'string') {
  8954. return false;
  8955. }
  8956. text = module.get.choiceText($item, false);
  8957. letter = letter.toLowerCase();
  8958. firstLetter = String(text).charAt(0).toLowerCase();
  8959. return (letter == firstLetter);
  8960. },
  8961. input: function() {
  8962. return ($input.length > 0);
  8963. },
  8964. items: function() {
  8965. return ($item.length > 0);
  8966. },
  8967. menu: function() {
  8968. return ($menu.length > 0);
  8969. },
  8970. message: function() {
  8971. return ($menu.children(selector.message).length !== 0);
  8972. },
  8973. label: function(value) {
  8974. var
  8975. escapedValue = module.escape.value(value),
  8976. $labels = $module.find(selector.label)
  8977. ;
  8978. if(settings.ignoreCase) {
  8979. escapedValue = escapedValue.toLowerCase();
  8980. }
  8981. return ($labels.filter('[data-' + metadata.value + '="' + module.escape.string(escapedValue) +'"]').length > 0);
  8982. },
  8983. maxSelections: function() {
  8984. return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
  8985. },
  8986. allResultsFiltered: function() {
  8987. var
  8988. $normalResults = $item.not(selector.addition)
  8989. ;
  8990. return ($normalResults.filter(selector.unselectable).length === $normalResults.length);
  8991. },
  8992. userSuggestion: function() {
  8993. return ($menu.children(selector.addition).length > 0);
  8994. },
  8995. query: function() {
  8996. return (module.get.query() !== '');
  8997. },
  8998. value: function(value) {
  8999. return (settings.ignoreCase)
  9000. ? module.has.valueIgnoringCase(value)
  9001. : module.has.valueMatchingCase(value)
  9002. ;
  9003. },
  9004. valueMatchingCase: function(value) {
  9005. var
  9006. values = module.get.values(),
  9007. hasValue = Array.isArray(values)
  9008. ? values && ($.inArray(value, values) !== -1)
  9009. : (values == value)
  9010. ;
  9011. return (hasValue)
  9012. ? true
  9013. : false
  9014. ;
  9015. },
  9016. valueIgnoringCase: function(value) {
  9017. var
  9018. values = module.get.values(),
  9019. hasValue = false
  9020. ;
  9021. if(!Array.isArray(values)) {
  9022. values = [values];
  9023. }
  9024. $.each(values, function(index, existingValue) {
  9025. if(String(value).toLowerCase() == String(existingValue).toLowerCase()) {
  9026. hasValue = true;
  9027. return false;
  9028. }
  9029. });
  9030. return hasValue;
  9031. }
  9032. },
  9033. is: {
  9034. active: function() {
  9035. return $module.hasClass(className.active);
  9036. },
  9037. animatingInward: function() {
  9038. return $menu.transition('is inward');
  9039. },
  9040. animatingOutward: function() {
  9041. return $menu.transition('is outward');
  9042. },
  9043. bubbledLabelClick: function(event) {
  9044. return $(event.target).is('select, input') && $module.closest('label').length > 0;
  9045. },
  9046. bubbledIconClick: function(event) {
  9047. return $(event.target).closest($icon).length > 0;
  9048. },
  9049. alreadySetup: function() {
  9050. return ($module.is('select') && $module.parent(selector.dropdown).data(moduleNamespace) !== undefined && $module.prev().length === 0);
  9051. },
  9052. animating: function($subMenu) {
  9053. return ($subMenu)
  9054. ? $subMenu.transition && $subMenu.transition('is animating')
  9055. : $menu.transition && $menu.transition('is animating')
  9056. ;
  9057. },
  9058. leftward: function($subMenu) {
  9059. var $selectedMenu = $subMenu || $menu;
  9060. return $selectedMenu.hasClass(className.leftward);
  9061. },
  9062. clearable: function() {
  9063. return ($module.hasClass(className.clearable) || settings.clearable);
  9064. },
  9065. disabled: function() {
  9066. return $module.hasClass(className.disabled);
  9067. },
  9068. focused: function() {
  9069. return (document.activeElement === $module[0]);
  9070. },
  9071. focusedOnSearch: function() {
  9072. return (document.activeElement === $search[0]);
  9073. },
  9074. allFiltered: function() {
  9075. return( (module.is.multiple() || module.has.search()) && !(settings.hideAdditions == false && module.has.userSuggestion()) && !module.has.message() && module.has.allResultsFiltered() );
  9076. },
  9077. hidden: function($subMenu) {
  9078. return !module.is.visible($subMenu);
  9079. },
  9080. initialLoad: function() {
  9081. return initialLoad;
  9082. },
  9083. inObject: function(needle, object) {
  9084. var
  9085. found = false
  9086. ;
  9087. $.each(object, function(index, property) {
  9088. if(property == needle) {
  9089. found = true;
  9090. return true;
  9091. }
  9092. });
  9093. return found;
  9094. },
  9095. multiple: function() {
  9096. return $module.hasClass(className.multiple);
  9097. },
  9098. remote: function() {
  9099. return settings.apiSettings && module.can.useAPI();
  9100. },
  9101. single: function() {
  9102. return !module.is.multiple();
  9103. },
  9104. selectMutation: function(mutations) {
  9105. var
  9106. selectChanged = false
  9107. ;
  9108. $.each(mutations, function(index, mutation) {
  9109. if($(mutation.target).is('select') || $(mutation.addedNodes).is('select')) {
  9110. selectChanged = true;
  9111. return false;
  9112. }
  9113. });
  9114. return selectChanged;
  9115. },
  9116. search: function() {
  9117. return $module.hasClass(className.search);
  9118. },
  9119. searchSelection: function() {
  9120. return ( module.has.search() && $search.parent(selector.dropdown).length === 1 );
  9121. },
  9122. selection: function() {
  9123. return $module.hasClass(className.selection);
  9124. },
  9125. userValue: function(value) {
  9126. return ($.inArray(value, module.get.userValues()) !== -1);
  9127. },
  9128. upward: function($menu) {
  9129. var $element = $menu || $module;
  9130. return $element.hasClass(className.upward);
  9131. },
  9132. visible: function($subMenu) {
  9133. return ($subMenu)
  9134. ? $subMenu.hasClass(className.visible)
  9135. : $menu.hasClass(className.visible)
  9136. ;
  9137. },
  9138. verticallyScrollableContext: function() {
  9139. var
  9140. overflowY = ($context.get(0) !== window)
  9141. ? $context.css('overflow-y')
  9142. : false
  9143. ;
  9144. return (overflowY == 'auto' || overflowY == 'scroll');
  9145. },
  9146. horizontallyScrollableContext: function() {
  9147. var
  9148. overflowX = ($context.get(0) !== window)
  9149. ? $context.css('overflow-X')
  9150. : false
  9151. ;
  9152. return (overflowX == 'auto' || overflowX == 'scroll');
  9153. }
  9154. },
  9155. can: {
  9156. activate: function($item) {
  9157. if(settings.useLabels) {
  9158. return true;
  9159. }
  9160. if(!module.has.maxSelections()) {
  9161. return true;
  9162. }
  9163. if(module.has.maxSelections() && $item.hasClass(className.active)) {
  9164. return true;
  9165. }
  9166. return false;
  9167. },
  9168. openDownward: function($subMenu) {
  9169. var
  9170. $currentMenu = $subMenu || $menu,
  9171. canOpenDownward = true,
  9172. onScreen = {},
  9173. calculations
  9174. ;
  9175. $currentMenu
  9176. .addClass(className.loading)
  9177. ;
  9178. calculations = {
  9179. context: {
  9180. offset : ($context.get(0) === window)
  9181. ? { top: 0, left: 0}
  9182. : $context.offset(),
  9183. scrollTop : $context.scrollTop(),
  9184. height : $context.outerHeight()
  9185. },
  9186. menu : {
  9187. offset: $currentMenu.offset(),
  9188. height: $currentMenu.outerHeight()
  9189. }
  9190. };
  9191. if(module.is.verticallyScrollableContext()) {
  9192. calculations.menu.offset.top += calculations.context.scrollTop;
  9193. }
  9194. onScreen = {
  9195. above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.context.offset.top - calculations.menu.height,
  9196. below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top - calculations.context.offset.top + calculations.menu.height
  9197. };
  9198. if(onScreen.below) {
  9199. module.verbose('Dropdown can fit in context downward', onScreen);
  9200. canOpenDownward = true;
  9201. }
  9202. else if(!onScreen.below && !onScreen.above) {
  9203. module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
  9204. canOpenDownward = true;
  9205. }
  9206. else {
  9207. module.verbose('Dropdown cannot fit below, opening upward', onScreen);
  9208. canOpenDownward = false;
  9209. }
  9210. $currentMenu.removeClass(className.loading);
  9211. return canOpenDownward;
  9212. },
  9213. openRightward: function($subMenu) {
  9214. var
  9215. $currentMenu = $subMenu || $menu,
  9216. canOpenRightward = true,
  9217. isOffscreenRight = false,
  9218. calculations
  9219. ;
  9220. $currentMenu
  9221. .addClass(className.loading)
  9222. ;
  9223. calculations = {
  9224. context: {
  9225. offset : ($context.get(0) === window)
  9226. ? { top: 0, left: 0}
  9227. : $context.offset(),
  9228. scrollLeft : $context.scrollLeft(),
  9229. width : $context.outerWidth()
  9230. },
  9231. menu: {
  9232. offset : $currentMenu.offset(),
  9233. width : $currentMenu.outerWidth()
  9234. }
  9235. };
  9236. if(module.is.horizontallyScrollableContext()) {
  9237. calculations.menu.offset.left += calculations.context.scrollLeft;
  9238. }
  9239. isOffscreenRight = (calculations.menu.offset.left - calculations.context.offset.left + calculations.menu.width >= calculations.context.scrollLeft + calculations.context.width);
  9240. if(isOffscreenRight) {
  9241. module.verbose('Dropdown cannot fit in context rightward', isOffscreenRight);
  9242. canOpenRightward = false;
  9243. }
  9244. $currentMenu.removeClass(className.loading);
  9245. return canOpenRightward;
  9246. },
  9247. click: function() {
  9248. return (hasTouch || settings.on == 'click');
  9249. },
  9250. extendSelect: function() {
  9251. return settings.allowAdditions || settings.apiSettings;
  9252. },
  9253. show: function() {
  9254. return !module.is.disabled() && (module.has.items() || module.has.message());
  9255. },
  9256. useAPI: function() {
  9257. return $.fn.api !== undefined;
  9258. }
  9259. },
  9260. animate: {
  9261. show: function(callback, $subMenu) {
  9262. var
  9263. $currentMenu = $subMenu || $menu,
  9264. start = ($subMenu)
  9265. ? function() {}
  9266. : function() {
  9267. module.hideSubMenus();
  9268. module.hideOthers();
  9269. module.set.active();
  9270. },
  9271. transition
  9272. ;
  9273. callback = $.isFunction(callback)
  9274. ? callback
  9275. : function(){}
  9276. ;
  9277. module.verbose('Doing menu show animation', $currentMenu);
  9278. module.set.direction($subMenu);
  9279. transition = module.get.transition($subMenu);
  9280. if( module.is.selection() ) {
  9281. module.set.scrollPosition(module.get.selectedItem(), true);
  9282. }
  9283. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  9284. if(transition == 'none') {
  9285. start();
  9286. $currentMenu.transition('show');
  9287. callback.call(element);
  9288. }
  9289. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  9290. $currentMenu
  9291. .transition({
  9292. animation : transition + ' in',
  9293. debug : settings.debug,
  9294. verbose : settings.verbose,
  9295. duration : settings.duration,
  9296. queue : true,
  9297. onStart : start,
  9298. onComplete : function() {
  9299. callback.call(element);
  9300. }
  9301. })
  9302. ;
  9303. }
  9304. else {
  9305. module.error(error.noTransition, transition);
  9306. }
  9307. }
  9308. },
  9309. hide: function(callback, $subMenu) {
  9310. var
  9311. $currentMenu = $subMenu || $menu,
  9312. start = ($subMenu)
  9313. ? function() {}
  9314. : function() {
  9315. if( module.can.click() ) {
  9316. module.unbind.intent();
  9317. }
  9318. module.remove.active();
  9319. },
  9320. transition = module.get.transition($subMenu)
  9321. ;
  9322. callback = $.isFunction(callback)
  9323. ? callback
  9324. : function(){}
  9325. ;
  9326. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  9327. module.verbose('Doing menu hide animation', $currentMenu);
  9328. if(transition == 'none') {
  9329. start();
  9330. $currentMenu.transition('hide');
  9331. callback.call(element);
  9332. }
  9333. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  9334. $currentMenu
  9335. .transition({
  9336. animation : transition + ' out',
  9337. duration : settings.duration,
  9338. debug : settings.debug,
  9339. verbose : settings.verbose,
  9340. queue : false,
  9341. onStart : start,
  9342. onComplete : function() {
  9343. callback.call(element);
  9344. }
  9345. })
  9346. ;
  9347. }
  9348. else {
  9349. module.error(error.transition);
  9350. }
  9351. }
  9352. }
  9353. },
  9354. hideAndClear: function() {
  9355. module.remove.searchTerm();
  9356. if( module.has.maxSelections() ) {
  9357. return;
  9358. }
  9359. if(module.has.search()) {
  9360. module.hide(function() {
  9361. module.remove.filteredItem();
  9362. });
  9363. }
  9364. else {
  9365. module.hide();
  9366. }
  9367. },
  9368. delay: {
  9369. show: function() {
  9370. module.verbose('Delaying show event to ensure user intent');
  9371. clearTimeout(module.timer);
  9372. module.timer = setTimeout(module.show, settings.delay.show);
  9373. },
  9374. hide: function() {
  9375. module.verbose('Delaying hide event to ensure user intent');
  9376. clearTimeout(module.timer);
  9377. module.timer = setTimeout(module.hide, settings.delay.hide);
  9378. }
  9379. },
  9380. escape: {
  9381. value: function(value) {
  9382. var
  9383. multipleValues = Array.isArray(value),
  9384. stringValue = (typeof value === 'string'),
  9385. isUnparsable = (!stringValue && !multipleValues),
  9386. hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
  9387. values = []
  9388. ;
  9389. if(isUnparsable || !hasQuotes) {
  9390. return value;
  9391. }
  9392. module.debug('Encoding quote values for use in select', value);
  9393. if(multipleValues) {
  9394. $.each(value, function(index, value){
  9395. values.push(value.replace(regExp.quote, '&quot;'));
  9396. });
  9397. return values;
  9398. }
  9399. return value.replace(regExp.quote, '&quot;');
  9400. },
  9401. string: function(text) {
  9402. text = String(text);
  9403. return text.replace(regExp.escape, '\\$&');
  9404. },
  9405. htmlEntities: function(string) {
  9406. var
  9407. badChars = /[&<>"'`]/g,
  9408. shouldEscape = /[&<>"'`]/,
  9409. escape = {
  9410. "&": "&amp;",
  9411. "<": "&lt;",
  9412. ">": "&gt;",
  9413. '"': "&quot;",
  9414. "'": "&#x27;",
  9415. "`": "&#x60;"
  9416. },
  9417. escapedChar = function(chr) {
  9418. return escape[chr];
  9419. }
  9420. ;
  9421. if(shouldEscape.test(string)) {
  9422. return string.replace(badChars, escapedChar);
  9423. }
  9424. return string;
  9425. }
  9426. },
  9427. setting: function(name, value) {
  9428. module.debug('Changing setting', name, value);
  9429. if( $.isPlainObject(name) ) {
  9430. $.extend(true, settings, name);
  9431. }
  9432. else if(value !== undefined) {
  9433. if($.isPlainObject(settings[name])) {
  9434. $.extend(true, settings[name], value);
  9435. }
  9436. else {
  9437. settings[name] = value;
  9438. }
  9439. }
  9440. else {
  9441. return settings[name];
  9442. }
  9443. },
  9444. internal: function(name, value) {
  9445. if( $.isPlainObject(name) ) {
  9446. $.extend(true, module, name);
  9447. }
  9448. else if(value !== undefined) {
  9449. module[name] = value;
  9450. }
  9451. else {
  9452. return module[name];
  9453. }
  9454. },
  9455. debug: function() {
  9456. if(!settings.silent && settings.debug) {
  9457. if(settings.performance) {
  9458. module.performance.log(arguments);
  9459. }
  9460. else {
  9461. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9462. module.debug.apply(console, arguments);
  9463. }
  9464. }
  9465. },
  9466. verbose: function() {
  9467. if(!settings.silent && settings.verbose && settings.debug) {
  9468. if(settings.performance) {
  9469. module.performance.log(arguments);
  9470. }
  9471. else {
  9472. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9473. module.verbose.apply(console, arguments);
  9474. }
  9475. }
  9476. },
  9477. error: function() {
  9478. if(!settings.silent) {
  9479. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9480. module.error.apply(console, arguments);
  9481. }
  9482. },
  9483. performance: {
  9484. log: function(message) {
  9485. var
  9486. currentTime,
  9487. executionTime,
  9488. previousTime
  9489. ;
  9490. if(settings.performance) {
  9491. currentTime = new Date().getTime();
  9492. previousTime = time || currentTime;
  9493. executionTime = currentTime - previousTime;
  9494. time = currentTime;
  9495. performance.push({
  9496. 'Name' : message[0],
  9497. 'Arguments' : [].slice.call(message, 1) || '',
  9498. 'Element' : element,
  9499. 'Execution Time' : executionTime
  9500. });
  9501. }
  9502. clearTimeout(module.performance.timer);
  9503. module.performance.timer = setTimeout(module.performance.display, 500);
  9504. },
  9505. display: function() {
  9506. var
  9507. title = settings.name + ':',
  9508. totalTime = 0
  9509. ;
  9510. time = false;
  9511. clearTimeout(module.performance.timer);
  9512. $.each(performance, function(index, data) {
  9513. totalTime += data['Execution Time'];
  9514. });
  9515. title += ' ' + totalTime + 'ms';
  9516. if(moduleSelector) {
  9517. title += ' \'' + moduleSelector + '\'';
  9518. }
  9519. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9520. console.groupCollapsed(title);
  9521. if(console.table) {
  9522. console.table(performance);
  9523. }
  9524. else {
  9525. $.each(performance, function(index, data) {
  9526. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9527. });
  9528. }
  9529. console.groupEnd();
  9530. }
  9531. performance = [];
  9532. }
  9533. },
  9534. invoke: function(query, passedArguments, context) {
  9535. var
  9536. object = instance,
  9537. maxDepth,
  9538. found,
  9539. response
  9540. ;
  9541. passedArguments = passedArguments || queryArguments;
  9542. context = element || context;
  9543. if(typeof query == 'string' && object !== undefined) {
  9544. query = query.split(/[\. ]/);
  9545. maxDepth = query.length - 1;
  9546. $.each(query, function(depth, value) {
  9547. var camelCaseValue = (depth != maxDepth)
  9548. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9549. : query
  9550. ;
  9551. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9552. object = object[camelCaseValue];
  9553. }
  9554. else if( object[camelCaseValue] !== undefined ) {
  9555. found = object[camelCaseValue];
  9556. return false;
  9557. }
  9558. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9559. object = object[value];
  9560. }
  9561. else if( object[value] !== undefined ) {
  9562. found = object[value];
  9563. return false;
  9564. }
  9565. else {
  9566. module.error(error.method, query);
  9567. return false;
  9568. }
  9569. });
  9570. }
  9571. if ( $.isFunction( found ) ) {
  9572. response = found.apply(context, passedArguments);
  9573. }
  9574. else if(found !== undefined) {
  9575. response = found;
  9576. }
  9577. if(Array.isArray(returnedValue)) {
  9578. returnedValue.push(response);
  9579. }
  9580. else if(returnedValue !== undefined) {
  9581. returnedValue = [returnedValue, response];
  9582. }
  9583. else if(response !== undefined) {
  9584. returnedValue = response;
  9585. }
  9586. return found;
  9587. }
  9588. };
  9589. if(methodInvoked) {
  9590. if(instance === undefined) {
  9591. module.initialize();
  9592. }
  9593. module.invoke(query);
  9594. }
  9595. else {
  9596. if(instance !== undefined) {
  9597. instance.invoke('destroy');
  9598. }
  9599. module.initialize();
  9600. }
  9601. })
  9602. ;
  9603. return (returnedValue !== undefined)
  9604. ? returnedValue
  9605. : $allModules
  9606. ;
  9607. };
  9608. $.fn.dropdown.settings = {
  9609. silent : false,
  9610. debug : false,
  9611. verbose : false,
  9612. performance : true,
  9613. on : 'click', // what event should show menu action on item selection
  9614. action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
  9615. values : false, // specify values to use for dropdown
  9616. clearable : false, // whether the value of the dropdown can be cleared
  9617. apiSettings : false,
  9618. selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
  9619. minCharacters : 0, // Minimum characters required to trigger API call
  9620. filterRemoteData : false, // Whether API results should be filtered after being returned for query term
  9621. saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
  9622. throttle : 200, // How long to wait after last user input to search remotely
  9623. context : window, // Context to use when determining if on screen
  9624. direction : 'auto', // Whether dropdown should always open in one direction
  9625. keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
  9626. match : 'both', // what to match against with search selection (both, text, or label)
  9627. fullTextSearch : false, // search anywhere in value (set to 'exact' to require exact matches)
  9628. ignoreDiacritics : false, // match results also if they contain diacritics of the same base character (for example searching for "a" will also match "á" or "â" or "à", etc...)
  9629. hideDividers : false, // Whether to hide any divider elements (specified in selector.divider) that are sibling to any items when searched (set to true will hide all dividers, set to 'empty' will hide them when they are not followed by a visible item)
  9630. placeholder : 'auto', // whether to convert blank <select> values to placeholder text
  9631. preserveHTML : true, // preserve html when selecting value
  9632. sortSelect : false, // sort selection on init
  9633. forceSelection : true, // force a choice on blur with search selection
  9634. allowAdditions : false, // whether multiple select should allow user added values
  9635. ignoreCase : false, // whether to consider case sensitivity when creating labels
  9636. ignoreSearchCase : true, // whether to consider case sensitivity when filtering items
  9637. hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
  9638. maxSelections : false, // When set to a number limits the number of selections to this count
  9639. useLabels : true, // whether multiple select should filter currently active selections from choices
  9640. delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
  9641. showOnFocus : true, // show menu on focus
  9642. allowReselection : false, // whether current value should trigger callbacks when reselected
  9643. allowTab : true, // add tabindex to element
  9644. allowCategorySelection : false, // allow elements with sub-menus to be selected
  9645. fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
  9646. transition : 'auto', // auto transition will slide down or up based on direction
  9647. duration : 200, // duration of transition
  9648. glyphWidth : 1.037, // widest glyph width in em (W is 1.037 em) used to calculate multiselect input width
  9649. headerDivider : true, // whether option headers should have an additional divider line underneath when converted from <select> <optgroup>
  9650. // label settings on multi-select
  9651. label: {
  9652. transition : 'scale',
  9653. duration : 200,
  9654. variation : false
  9655. },
  9656. // delay before event
  9657. delay : {
  9658. hide : 300,
  9659. show : 200,
  9660. search : 20,
  9661. touch : 50
  9662. },
  9663. /* Callbacks */
  9664. onChange : function(value, text, $selected){},
  9665. onAdd : function(value, text, $selected){},
  9666. onRemove : function(value, text, $selected){},
  9667. onLabelSelect : function($selectedLabels){},
  9668. onLabelCreate : function(value, text) { return $(this); },
  9669. onLabelRemove : function(value) { return true; },
  9670. onNoResults : function(searchTerm) { return true; },
  9671. onShow : function(){},
  9672. onHide : function(){},
  9673. /* Component */
  9674. name : 'Dropdown',
  9675. namespace : 'dropdown',
  9676. message: {
  9677. addResult : 'Add <b>{term}</b>',
  9678. count : '{count} selected',
  9679. maxSelections : 'Max {maxCount} selections',
  9680. noResults : 'No results found.',
  9681. serverError : 'There was an error contacting the server'
  9682. },
  9683. error : {
  9684. action : 'You called a dropdown action that was not defined',
  9685. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  9686. labels : 'Allowing user additions currently requires the use of labels.',
  9687. missingMultiple : '<select> requires multiple property to be set to correctly preserve multiple values',
  9688. method : 'The method you called is not defined.',
  9689. noAPI : 'The API module is required to load resources remotely',
  9690. noStorage : 'Saving remote data requires session storage',
  9691. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  9692. noNormalize : '"ignoreDiacritics" setting will be ignored. Browser does not support String().normalize(). You may consider including <https://cdn.jsdelivr.net/npm/unorm@1.4.1/lib/unorm.min.js> as a polyfill.'
  9693. },
  9694. regExp : {
  9695. escape : /[-[\]{}()*+?.,\\^$|#\s:=@]/g,
  9696. quote : /"/g
  9697. },
  9698. metadata : {
  9699. defaultText : 'defaultText',
  9700. defaultValue : 'defaultValue',
  9701. placeholderText : 'placeholder',
  9702. text : 'text',
  9703. value : 'value'
  9704. },
  9705. // property names for remote query
  9706. fields: {
  9707. remoteValues : 'results', // grouping for api results
  9708. values : 'values', // grouping for all dropdown values
  9709. disabled : 'disabled', // whether value should be disabled
  9710. name : 'name', // displayed dropdown text
  9711. value : 'value', // actual dropdown value
  9712. text : 'text', // displayed text when selected
  9713. type : 'type', // type of dropdown element
  9714. image : 'image', // optional image path
  9715. imageClass : 'imageClass', // optional individual class for image
  9716. icon : 'icon', // optional icon name
  9717. iconClass : 'iconClass', // optional individual class for icon (for example to use flag instead)
  9718. class : 'class', // optional individual class for item/header
  9719. divider : 'divider' // optional divider append for group headers
  9720. },
  9721. keys : {
  9722. backspace : 8,
  9723. delimiter : 188, // comma
  9724. deleteKey : 46,
  9725. enter : 13,
  9726. escape : 27,
  9727. pageUp : 33,
  9728. pageDown : 34,
  9729. leftArrow : 37,
  9730. upArrow : 38,
  9731. rightArrow : 39,
  9732. downArrow : 40
  9733. },
  9734. selector : {
  9735. addition : '.addition',
  9736. divider : '.divider, .header',
  9737. dropdown : '.ui.dropdown',
  9738. hidden : '.hidden',
  9739. icon : '> .dropdown.icon',
  9740. input : '> input[type="hidden"], > select',
  9741. item : '.item',
  9742. label : '> .label',
  9743. remove : '> .label > .delete.icon',
  9744. siblingLabel : '.label',
  9745. menu : '.menu',
  9746. message : '.message',
  9747. menuIcon : '.dropdown.icon',
  9748. search : 'input.search, .menu > .search > input, .menu input.search',
  9749. sizer : '> input.sizer',
  9750. text : '> .text:not(.icon)',
  9751. unselectable : '.disabled, .filtered',
  9752. clearIcon : '> .remove.icon'
  9753. },
  9754. className : {
  9755. active : 'active',
  9756. addition : 'addition',
  9757. animating : 'animating',
  9758. disabled : 'disabled',
  9759. empty : 'empty',
  9760. dropdown : 'ui dropdown',
  9761. filtered : 'filtered',
  9762. hidden : 'hidden transition',
  9763. icon : 'icon',
  9764. image : 'image',
  9765. item : 'item',
  9766. label : 'ui label',
  9767. loading : 'loading',
  9768. menu : 'menu',
  9769. message : 'message',
  9770. multiple : 'multiple',
  9771. placeholder : 'default',
  9772. sizer : 'sizer',
  9773. search : 'search',
  9774. selected : 'selected',
  9775. selection : 'selection',
  9776. upward : 'upward',
  9777. leftward : 'left',
  9778. visible : 'visible',
  9779. clearable : 'clearable',
  9780. noselection : 'noselection',
  9781. delete : 'delete',
  9782. header : 'header',
  9783. divider : 'divider',
  9784. groupIcon : ''
  9785. }
  9786. };
  9787. /* Templates */
  9788. $.fn.dropdown.settings.templates = {
  9789. deQuote: function(string) {
  9790. return String(string).replace(/"/g,"");
  9791. },
  9792. escape: function(string, preserveHTML) {
  9793. if (preserveHTML){
  9794. return string;
  9795. }
  9796. var
  9797. badChars = /[&<>"'`]/g,
  9798. shouldEscape = /[&<>"'`]/,
  9799. escape = {
  9800. "&": "&amp;",
  9801. "<": "&lt;",
  9802. ">": "&gt;",
  9803. '"': "&quot;",
  9804. "'": "&#x27;",
  9805. "`": "&#x60;"
  9806. },
  9807. escapedChar = function(chr) {
  9808. return escape[chr];
  9809. }
  9810. ;
  9811. if(shouldEscape.test(string)) {
  9812. return string.replace(badChars, escapedChar);
  9813. }
  9814. return string;
  9815. },
  9816. // generates dropdown from select values
  9817. dropdown: function(select, fields, preserveHTML, className) {
  9818. var
  9819. placeholder = select.placeholder || false,
  9820. html = '',
  9821. escape = $.fn.dropdown.settings.templates.escape
  9822. ;
  9823. html += '<i class="dropdown icon"></i>';
  9824. if(placeholder) {
  9825. html += '<div class="default text">' + escape(placeholder,preserveHTML) + '</div>';
  9826. }
  9827. else {
  9828. html += '<div class="text"></div>';
  9829. }
  9830. html += '<div class="'+className.menu+'">';
  9831. html += $.fn.dropdown.settings.templates.menu(select, fields, preserveHTML,className);
  9832. html += '</div>';
  9833. return html;
  9834. },
  9835. // generates just menu from select
  9836. menu: function(response, fields, preserveHTML, className) {
  9837. var
  9838. values = response[fields.values] || [],
  9839. html = '',
  9840. escape = $.fn.dropdown.settings.templates.escape,
  9841. deQuote = $.fn.dropdown.settings.templates.deQuote
  9842. ;
  9843. $.each(values, function(index, option) {
  9844. var
  9845. itemType = (option[fields.type])
  9846. ? option[fields.type]
  9847. : 'item'
  9848. ;
  9849. if( itemType === 'item' ) {
  9850. var
  9851. maybeText = (option[fields.text])
  9852. ? ' data-text="' + deQuote(option[fields.text]) + '"'
  9853. : '',
  9854. maybeDisabled = (option[fields.disabled])
  9855. ? className.disabled+' '
  9856. : ''
  9857. ;
  9858. html += '<div class="'+ maybeDisabled + (option[fields.class] ? deQuote(option[fields.class]) : className.item)+'" data-value="' + deQuote(option[fields.value]) + '"' + maybeText + '>';
  9859. if(option[fields.image]) {
  9860. html += '<img class="'+(option[fields.imageClass] ? deQuote(option[fields.imageClass]) : className.image)+'" src="' + deQuote(option[fields.image]) + '">';
  9861. }
  9862. if(option[fields.icon]) {
  9863. html += '<i class="'+deQuote(option[fields.icon])+' '+(option[fields.iconClass] ? deQuote(option[fields.iconClass]) : className.icon)+'"></i>';
  9864. }
  9865. html += escape(option[fields.name] || option[fields.value],preserveHTML);
  9866. html += '</div>';
  9867. } else if (itemType === 'header') {
  9868. var groupName = escape(option[fields.name],preserveHTML),
  9869. groupIcon = option[fields.icon] ? deQuote(option[fields.icon]) : className.groupIcon
  9870. ;
  9871. if(groupName !== '' || groupIcon !== '') {
  9872. html += '<div class="' + (option[fields.class] ? deQuote(option[fields.class]) : className.header) + '">';
  9873. if (groupIcon !== '') {
  9874. html += '<i class="' + groupIcon + ' ' + (option[fields.iconClass] ? deQuote(option[fields.iconClass]) : className.icon) + '"></i>';
  9875. }
  9876. html += groupName;
  9877. html += '</div>';
  9878. }
  9879. if(option[fields.divider]){
  9880. html += '<div class="'+className.divider+'"></div>';
  9881. }
  9882. }
  9883. });
  9884. return html;
  9885. },
  9886. // generates label for multiselect
  9887. label: function(value, text, preserveHTML, className) {
  9888. var
  9889. escape = $.fn.dropdown.settings.templates.escape;
  9890. return escape(text,preserveHTML) + '<i class="'+className.delete+' icon"></i>';
  9891. },
  9892. // generates messages like "No results"
  9893. message: function(message) {
  9894. return message;
  9895. },
  9896. // generates user addition to selection menu
  9897. addition: function(choice) {
  9898. return choice;
  9899. }
  9900. };
  9901. })( jQuery, window, document );
  9902. /*!
  9903. * # Fomantic-UI - Embed
  9904. * http://github.com/fomantic/Fomantic-UI/
  9905. *
  9906. *
  9907. * Released under the MIT license
  9908. * http://opensource.org/licenses/MIT
  9909. *
  9910. */
  9911. ;(function ($, window, document, undefined) {
  9912. "use strict";
  9913. $.isFunction = $.isFunction || function(obj) {
  9914. return typeof obj === "function" && typeof obj.nodeType !== "number";
  9915. };
  9916. window = (typeof window != 'undefined' && window.Math == Math)
  9917. ? window
  9918. : (typeof self != 'undefined' && self.Math == Math)
  9919. ? self
  9920. : Function('return this')()
  9921. ;
  9922. $.fn.embed = function(parameters) {
  9923. var
  9924. $allModules = $(this),
  9925. moduleSelector = $allModules.selector || '',
  9926. time = new Date().getTime(),
  9927. performance = [],
  9928. query = arguments[0],
  9929. methodInvoked = (typeof query == 'string'),
  9930. queryArguments = [].slice.call(arguments, 1),
  9931. returnedValue
  9932. ;
  9933. $allModules
  9934. .each(function() {
  9935. var
  9936. settings = ( $.isPlainObject(parameters) )
  9937. ? $.extend(true, {}, $.fn.embed.settings, parameters)
  9938. : $.extend({}, $.fn.embed.settings),
  9939. selector = settings.selector,
  9940. className = settings.className,
  9941. sources = settings.sources,
  9942. error = settings.error,
  9943. metadata = settings.metadata,
  9944. namespace = settings.namespace,
  9945. templates = settings.templates,
  9946. eventNamespace = '.' + namespace,
  9947. moduleNamespace = 'module-' + namespace,
  9948. $module = $(this),
  9949. $placeholder = $module.find(selector.placeholder),
  9950. $icon = $module.find(selector.icon),
  9951. $embed = $module.find(selector.embed),
  9952. element = this,
  9953. instance = $module.data(moduleNamespace),
  9954. module
  9955. ;
  9956. module = {
  9957. initialize: function() {
  9958. module.debug('Initializing embed');
  9959. module.determine.autoplay();
  9960. module.create();
  9961. module.bind.events();
  9962. module.instantiate();
  9963. },
  9964. instantiate: function() {
  9965. module.verbose('Storing instance of module', module);
  9966. instance = module;
  9967. $module
  9968. .data(moduleNamespace, module)
  9969. ;
  9970. },
  9971. destroy: function() {
  9972. module.verbose('Destroying previous instance of embed');
  9973. module.reset();
  9974. $module
  9975. .removeData(moduleNamespace)
  9976. .off(eventNamespace)
  9977. ;
  9978. },
  9979. refresh: function() {
  9980. module.verbose('Refreshing selector cache');
  9981. $placeholder = $module.find(selector.placeholder);
  9982. $icon = $module.find(selector.icon);
  9983. $embed = $module.find(selector.embed);
  9984. },
  9985. bind: {
  9986. events: function() {
  9987. if( module.has.placeholder() ) {
  9988. module.debug('Adding placeholder events');
  9989. $module
  9990. .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
  9991. .on('click' + eventNamespace, selector.icon, module.createAndShow)
  9992. ;
  9993. }
  9994. }
  9995. },
  9996. create: function() {
  9997. var
  9998. placeholder = module.get.placeholder()
  9999. ;
  10000. if(placeholder) {
  10001. module.createPlaceholder();
  10002. }
  10003. else {
  10004. module.createAndShow();
  10005. }
  10006. },
  10007. createPlaceholder: function(placeholder) {
  10008. var
  10009. icon = module.get.icon(),
  10010. url = module.get.url(),
  10011. embed = module.generate.embed(url)
  10012. ;
  10013. placeholder = placeholder || module.get.placeholder();
  10014. $module.html( templates.placeholder(placeholder, icon) );
  10015. module.debug('Creating placeholder for embed', placeholder, icon);
  10016. },
  10017. createEmbed: function(url) {
  10018. module.refresh();
  10019. url = url || module.get.url();
  10020. $embed = $('<div/>')
  10021. .addClass(className.embed)
  10022. .html( module.generate.embed(url) )
  10023. .appendTo($module)
  10024. ;
  10025. settings.onCreate.call(element, url);
  10026. module.debug('Creating embed object', $embed);
  10027. },
  10028. changeEmbed: function(url) {
  10029. $embed
  10030. .html( module.generate.embed(url) )
  10031. ;
  10032. },
  10033. createAndShow: function() {
  10034. module.createEmbed();
  10035. module.show();
  10036. },
  10037. // sets new embed
  10038. change: function(source, id, url) {
  10039. module.debug('Changing video to ', source, id, url);
  10040. $module
  10041. .data(metadata.source, source)
  10042. .data(metadata.id, id)
  10043. ;
  10044. if(url) {
  10045. $module.data(metadata.url, url);
  10046. }
  10047. else {
  10048. $module.removeData(metadata.url);
  10049. }
  10050. if(module.has.embed()) {
  10051. module.changeEmbed();
  10052. }
  10053. else {
  10054. module.create();
  10055. }
  10056. },
  10057. // clears embed
  10058. reset: function() {
  10059. module.debug('Clearing embed and showing placeholder');
  10060. module.remove.data();
  10061. module.remove.active();
  10062. module.remove.embed();
  10063. module.showPlaceholder();
  10064. settings.onReset.call(element);
  10065. },
  10066. // shows current embed
  10067. show: function() {
  10068. module.debug('Showing embed');
  10069. module.set.active();
  10070. settings.onDisplay.call(element);
  10071. },
  10072. hide: function() {
  10073. module.debug('Hiding embed');
  10074. module.showPlaceholder();
  10075. },
  10076. showPlaceholder: function() {
  10077. module.debug('Showing placeholder image');
  10078. module.remove.active();
  10079. settings.onPlaceholderDisplay.call(element);
  10080. },
  10081. get: {
  10082. id: function() {
  10083. return settings.id || $module.data(metadata.id);
  10084. },
  10085. placeholder: function() {
  10086. return settings.placeholder || $module.data(metadata.placeholder);
  10087. },
  10088. icon: function() {
  10089. return (settings.icon)
  10090. ? settings.icon
  10091. : ($module.data(metadata.icon) !== undefined)
  10092. ? $module.data(metadata.icon)
  10093. : module.determine.icon()
  10094. ;
  10095. },
  10096. source: function(url) {
  10097. return (settings.source)
  10098. ? settings.source
  10099. : ($module.data(metadata.source) !== undefined)
  10100. ? $module.data(metadata.source)
  10101. : module.determine.source()
  10102. ;
  10103. },
  10104. type: function() {
  10105. var source = module.get.source();
  10106. return (sources[source] !== undefined)
  10107. ? sources[source].type
  10108. : false
  10109. ;
  10110. },
  10111. url: function() {
  10112. return (settings.url)
  10113. ? settings.url
  10114. : ($module.data(metadata.url) !== undefined)
  10115. ? $module.data(metadata.url)
  10116. : module.determine.url()
  10117. ;
  10118. }
  10119. },
  10120. determine: {
  10121. autoplay: function() {
  10122. if(module.should.autoplay()) {
  10123. settings.autoplay = true;
  10124. }
  10125. },
  10126. source: function(url) {
  10127. var
  10128. matchedSource = false
  10129. ;
  10130. url = url || module.get.url();
  10131. if(url) {
  10132. $.each(sources, function(name, source) {
  10133. if(url.search(source.domain) !== -1) {
  10134. matchedSource = name;
  10135. return false;
  10136. }
  10137. });
  10138. }
  10139. return matchedSource;
  10140. },
  10141. icon: function() {
  10142. var
  10143. source = module.get.source()
  10144. ;
  10145. return (sources[source] !== undefined)
  10146. ? sources[source].icon
  10147. : false
  10148. ;
  10149. },
  10150. url: function() {
  10151. var
  10152. id = settings.id || $module.data(metadata.id),
  10153. source = settings.source || $module.data(metadata.source),
  10154. url
  10155. ;
  10156. url = (sources[source] !== undefined)
  10157. ? sources[source].url.replace('{id}', id)
  10158. : false
  10159. ;
  10160. if(url) {
  10161. $module.data(metadata.url, url);
  10162. }
  10163. return url;
  10164. }
  10165. },
  10166. set: {
  10167. active: function() {
  10168. $module.addClass(className.active);
  10169. }
  10170. },
  10171. remove: {
  10172. data: function() {
  10173. $module
  10174. .removeData(metadata.id)
  10175. .removeData(metadata.icon)
  10176. .removeData(metadata.placeholder)
  10177. .removeData(metadata.source)
  10178. .removeData(metadata.url)
  10179. ;
  10180. },
  10181. active: function() {
  10182. $module.removeClass(className.active);
  10183. },
  10184. embed: function() {
  10185. $embed.empty();
  10186. }
  10187. },
  10188. encode: {
  10189. parameters: function(parameters) {
  10190. var
  10191. urlString = [],
  10192. index
  10193. ;
  10194. for (index in parameters) {
  10195. urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
  10196. }
  10197. return urlString.join('&amp;');
  10198. }
  10199. },
  10200. generate: {
  10201. embed: function(url) {
  10202. module.debug('Generating embed html');
  10203. var
  10204. source = module.get.source(),
  10205. html,
  10206. parameters
  10207. ;
  10208. url = module.get.url(url);
  10209. if(url) {
  10210. parameters = module.generate.parameters(source);
  10211. html = templates.iframe(url, parameters);
  10212. }
  10213. else {
  10214. module.error(error.noURL, $module);
  10215. }
  10216. return html;
  10217. },
  10218. parameters: function(source, extraParameters) {
  10219. var
  10220. parameters = (sources[source] && sources[source].parameters !== undefined)
  10221. ? sources[source].parameters(settings)
  10222. : {}
  10223. ;
  10224. extraParameters = extraParameters || settings.parameters;
  10225. if(extraParameters) {
  10226. parameters = $.extend({}, parameters, extraParameters);
  10227. }
  10228. parameters = settings.onEmbed(parameters);
  10229. return module.encode.parameters(parameters);
  10230. }
  10231. },
  10232. has: {
  10233. embed: function() {
  10234. return ($embed.length > 0);
  10235. },
  10236. placeholder: function() {
  10237. return settings.placeholder || $module.data(metadata.placeholder);
  10238. }
  10239. },
  10240. should: {
  10241. autoplay: function() {
  10242. return (settings.autoplay === 'auto')
  10243. ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
  10244. : settings.autoplay
  10245. ;
  10246. }
  10247. },
  10248. is: {
  10249. video: function() {
  10250. return module.get.type() == 'video';
  10251. }
  10252. },
  10253. setting: function(name, value) {
  10254. module.debug('Changing setting', name, value);
  10255. if( $.isPlainObject(name) ) {
  10256. $.extend(true, settings, name);
  10257. }
  10258. else if(value !== undefined) {
  10259. if($.isPlainObject(settings[name])) {
  10260. $.extend(true, settings[name], value);
  10261. }
  10262. else {
  10263. settings[name] = value;
  10264. }
  10265. }
  10266. else {
  10267. return settings[name];
  10268. }
  10269. },
  10270. internal: function(name, value) {
  10271. if( $.isPlainObject(name) ) {
  10272. $.extend(true, module, name);
  10273. }
  10274. else if(value !== undefined) {
  10275. module[name] = value;
  10276. }
  10277. else {
  10278. return module[name];
  10279. }
  10280. },
  10281. debug: function() {
  10282. if(!settings.silent && settings.debug) {
  10283. if(settings.performance) {
  10284. module.performance.log(arguments);
  10285. }
  10286. else {
  10287. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10288. module.debug.apply(console, arguments);
  10289. }
  10290. }
  10291. },
  10292. verbose: function() {
  10293. if(!settings.silent && settings.verbose && settings.debug) {
  10294. if(settings.performance) {
  10295. module.performance.log(arguments);
  10296. }
  10297. else {
  10298. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10299. module.verbose.apply(console, arguments);
  10300. }
  10301. }
  10302. },
  10303. error: function() {
  10304. if(!settings.silent) {
  10305. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  10306. module.error.apply(console, arguments);
  10307. }
  10308. },
  10309. performance: {
  10310. log: function(message) {
  10311. var
  10312. currentTime,
  10313. executionTime,
  10314. previousTime
  10315. ;
  10316. if(settings.performance) {
  10317. currentTime = new Date().getTime();
  10318. previousTime = time || currentTime;
  10319. executionTime = currentTime - previousTime;
  10320. time = currentTime;
  10321. performance.push({
  10322. 'Name' : message[0],
  10323. 'Arguments' : [].slice.call(message, 1) || '',
  10324. 'Element' : element,
  10325. 'Execution Time' : executionTime
  10326. });
  10327. }
  10328. clearTimeout(module.performance.timer);
  10329. module.performance.timer = setTimeout(module.performance.display, 500);
  10330. },
  10331. display: function() {
  10332. var
  10333. title = settings.name + ':',
  10334. totalTime = 0
  10335. ;
  10336. time = false;
  10337. clearTimeout(module.performance.timer);
  10338. $.each(performance, function(index, data) {
  10339. totalTime += data['Execution Time'];
  10340. });
  10341. title += ' ' + totalTime + 'ms';
  10342. if(moduleSelector) {
  10343. title += ' \'' + moduleSelector + '\'';
  10344. }
  10345. if($allModules.length > 1) {
  10346. title += ' ' + '(' + $allModules.length + ')';
  10347. }
  10348. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  10349. console.groupCollapsed(title);
  10350. if(console.table) {
  10351. console.table(performance);
  10352. }
  10353. else {
  10354. $.each(performance, function(index, data) {
  10355. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  10356. });
  10357. }
  10358. console.groupEnd();
  10359. }
  10360. performance = [];
  10361. }
  10362. },
  10363. invoke: function(query, passedArguments, context) {
  10364. var
  10365. object = instance,
  10366. maxDepth,
  10367. found,
  10368. response
  10369. ;
  10370. passedArguments = passedArguments || queryArguments;
  10371. context = element || context;
  10372. if(typeof query == 'string' && object !== undefined) {
  10373. query = query.split(/[\. ]/);
  10374. maxDepth = query.length - 1;
  10375. $.each(query, function(depth, value) {
  10376. var camelCaseValue = (depth != maxDepth)
  10377. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  10378. : query
  10379. ;
  10380. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  10381. object = object[camelCaseValue];
  10382. }
  10383. else if( object[camelCaseValue] !== undefined ) {
  10384. found = object[camelCaseValue];
  10385. return false;
  10386. }
  10387. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  10388. object = object[value];
  10389. }
  10390. else if( object[value] !== undefined ) {
  10391. found = object[value];
  10392. return false;
  10393. }
  10394. else {
  10395. module.error(error.method, query);
  10396. return false;
  10397. }
  10398. });
  10399. }
  10400. if ( $.isFunction( found ) ) {
  10401. response = found.apply(context, passedArguments);
  10402. }
  10403. else if(found !== undefined) {
  10404. response = found;
  10405. }
  10406. if(Array.isArray(returnedValue)) {
  10407. returnedValue.push(response);
  10408. }
  10409. else if(returnedValue !== undefined) {
  10410. returnedValue = [returnedValue, response];
  10411. }
  10412. else if(response !== undefined) {
  10413. returnedValue = response;
  10414. }
  10415. return found;
  10416. }
  10417. };
  10418. if(methodInvoked) {
  10419. if(instance === undefined) {
  10420. module.initialize();
  10421. }
  10422. module.invoke(query);
  10423. }
  10424. else {
  10425. if(instance !== undefined) {
  10426. instance.invoke('destroy');
  10427. }
  10428. module.initialize();
  10429. }
  10430. })
  10431. ;
  10432. return (returnedValue !== undefined)
  10433. ? returnedValue
  10434. : this
  10435. ;
  10436. };
  10437. $.fn.embed.settings = {
  10438. name : 'Embed',
  10439. namespace : 'embed',
  10440. silent : false,
  10441. debug : false,
  10442. verbose : false,
  10443. performance : true,
  10444. icon : false,
  10445. source : false,
  10446. url : false,
  10447. id : false,
  10448. // standard video settings
  10449. autoplay : 'auto',
  10450. color : '#444444',
  10451. hd : true,
  10452. brandedUI : false,
  10453. // additional parameters to include with the embed
  10454. parameters: false,
  10455. onDisplay : function() {},
  10456. onPlaceholderDisplay : function() {},
  10457. onReset : function() {},
  10458. onCreate : function(url) {},
  10459. onEmbed : function(parameters) {
  10460. return parameters;
  10461. },
  10462. metadata : {
  10463. id : 'id',
  10464. icon : 'icon',
  10465. placeholder : 'placeholder',
  10466. source : 'source',
  10467. url : 'url'
  10468. },
  10469. error : {
  10470. noURL : 'No URL specified',
  10471. method : 'The method you called is not defined'
  10472. },
  10473. className : {
  10474. active : 'active',
  10475. embed : 'embed'
  10476. },
  10477. selector : {
  10478. embed : '.embed',
  10479. placeholder : '.placeholder',
  10480. icon : '.icon'
  10481. },
  10482. sources: {
  10483. youtube: {
  10484. name : 'youtube',
  10485. type : 'video',
  10486. icon : 'video play',
  10487. domain : 'youtube.com',
  10488. url : '//www.youtube.com/embed/{id}',
  10489. parameters: function(settings) {
  10490. return {
  10491. autohide : !settings.brandedUI,
  10492. autoplay : settings.autoplay,
  10493. color : settings.color || undefined,
  10494. hq : settings.hd,
  10495. jsapi : settings.api,
  10496. modestbranding : !settings.brandedUI
  10497. };
  10498. }
  10499. },
  10500. vimeo: {
  10501. name : 'vimeo',
  10502. type : 'video',
  10503. icon : 'video play',
  10504. domain : 'vimeo.com',
  10505. url : '//player.vimeo.com/video/{id}',
  10506. parameters: function(settings) {
  10507. return {
  10508. api : settings.api,
  10509. autoplay : settings.autoplay,
  10510. byline : settings.brandedUI,
  10511. color : settings.color || undefined,
  10512. portrait : settings.brandedUI,
  10513. title : settings.brandedUI
  10514. };
  10515. }
  10516. }
  10517. },
  10518. templates: {
  10519. iframe : function(url, parameters) {
  10520. var src = url;
  10521. if (parameters) {
  10522. src += '?' + parameters;
  10523. }
  10524. return ''
  10525. + '<iframe src="' + src + '"'
  10526. + ' width="100%" height="100%"'
  10527. + ' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  10528. ;
  10529. },
  10530. placeholder : function(image, icon) {
  10531. var
  10532. html = ''
  10533. ;
  10534. if(icon) {
  10535. html += '<i class="' + icon + ' icon"></i>';
  10536. }
  10537. if(image) {
  10538. html += '<img class="placeholder" src="' + image + '">';
  10539. }
  10540. return html;
  10541. }
  10542. },
  10543. // NOT YET IMPLEMENTED
  10544. api : false,
  10545. onPause : function() {},
  10546. onPlay : function() {},
  10547. onStop : function() {}
  10548. };
  10549. })( jQuery, window, document );
  10550. /*!
  10551. * # Fomantic-UI - Modal
  10552. * http://github.com/fomantic/Fomantic-UI/
  10553. *
  10554. *
  10555. * Released under the MIT license
  10556. * http://opensource.org/licenses/MIT
  10557. *
  10558. */
  10559. ;(function ($, window, document, undefined) {
  10560. 'use strict';
  10561. $.isFunction = $.isFunction || function(obj) {
  10562. return typeof obj === "function" && typeof obj.nodeType !== "number";
  10563. };
  10564. window = (typeof window != 'undefined' && window.Math == Math)
  10565. ? window
  10566. : (typeof self != 'undefined' && self.Math == Math)
  10567. ? self
  10568. : Function('return this')()
  10569. ;
  10570. $.fn.modal = function(parameters) {
  10571. var
  10572. $allModules = $(this),
  10573. $window = $(window),
  10574. $document = $(document),
  10575. $body = $('body'),
  10576. moduleSelector = $allModules.selector || '',
  10577. time = new Date().getTime(),
  10578. performance = [],
  10579. query = arguments[0],
  10580. methodInvoked = (typeof query == 'string'),
  10581. queryArguments = [].slice.call(arguments, 1),
  10582. requestAnimationFrame = window.requestAnimationFrame
  10583. || window.mozRequestAnimationFrame
  10584. || window.webkitRequestAnimationFrame
  10585. || window.msRequestAnimationFrame
  10586. || function(callback) { setTimeout(callback, 0); },
  10587. returnedValue
  10588. ;
  10589. $allModules
  10590. .each(function() {
  10591. var
  10592. settings = ( $.isPlainObject(parameters) )
  10593. ? $.extend(true, {}, $.fn.modal.settings, parameters)
  10594. : $.extend({}, $.fn.modal.settings),
  10595. selector = settings.selector,
  10596. className = settings.className,
  10597. namespace = settings.namespace,
  10598. error = settings.error,
  10599. eventNamespace = '.' + namespace,
  10600. moduleNamespace = 'module-' + namespace,
  10601. $module = $(this),
  10602. $context = $(settings.context),
  10603. $close = $module.find(selector.close),
  10604. $allModals,
  10605. $otherModals,
  10606. $focusedElement,
  10607. $dimmable,
  10608. $dimmer,
  10609. element = this,
  10610. instance = $module.data(moduleNamespace),
  10611. ignoreRepeatedEvents = false,
  10612. initialMouseDownInModal,
  10613. initialMouseDownInScrollbar,
  10614. initialBodyMargin = '',
  10615. tempBodyMargin = '',
  10616. elementEventNamespace,
  10617. id,
  10618. observer,
  10619. module
  10620. ;
  10621. module = {
  10622. initialize: function() {
  10623. module.cache = {};
  10624. module.verbose('Initializing dimmer', $context);
  10625. module.create.id();
  10626. module.create.dimmer();
  10627. if ( settings.allowMultiple ) {
  10628. module.create.innerDimmer();
  10629. }
  10630. if (!settings.centered){
  10631. $module.addClass('top aligned');
  10632. }
  10633. module.refreshModals();
  10634. module.bind.events();
  10635. if(settings.observeChanges) {
  10636. module.observeChanges();
  10637. }
  10638. module.instantiate();
  10639. },
  10640. instantiate: function() {
  10641. module.verbose('Storing instance of modal');
  10642. instance = module;
  10643. $module
  10644. .data(moduleNamespace, instance)
  10645. ;
  10646. },
  10647. create: {
  10648. dimmer: function() {
  10649. var
  10650. defaultSettings = {
  10651. debug : settings.debug,
  10652. dimmerName : 'modals'
  10653. },
  10654. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  10655. ;
  10656. if($.fn.dimmer === undefined) {
  10657. module.error(error.dimmer);
  10658. return;
  10659. }
  10660. module.debug('Creating dimmer');
  10661. $dimmable = $context.dimmer(dimmerSettings);
  10662. if(settings.detachable) {
  10663. module.verbose('Modal is detachable, moving content into dimmer');
  10664. $dimmable.dimmer('add content', $module);
  10665. }
  10666. else {
  10667. module.set.undetached();
  10668. }
  10669. $dimmer = $dimmable.dimmer('get dimmer');
  10670. },
  10671. id: function() {
  10672. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  10673. elementEventNamespace = '.' + id;
  10674. module.verbose('Creating unique id for element', id);
  10675. },
  10676. innerDimmer: function() {
  10677. if ( $module.find(selector.dimmer).length == 0 ) {
  10678. $module.prepend('<div class="ui inverted dimmer"></div>');
  10679. }
  10680. }
  10681. },
  10682. destroy: function() {
  10683. if (observer) {
  10684. observer.disconnect();
  10685. }
  10686. module.verbose('Destroying previous modal');
  10687. $module
  10688. .removeData(moduleNamespace)
  10689. .off(eventNamespace)
  10690. ;
  10691. $window.off(elementEventNamespace);
  10692. $dimmer.off(elementEventNamespace);
  10693. $close.off(eventNamespace);
  10694. $context.dimmer('destroy');
  10695. },
  10696. observeChanges: function() {
  10697. if('MutationObserver' in window) {
  10698. observer = new MutationObserver(function(mutations) {
  10699. module.debug('DOM tree modified, refreshing');
  10700. module.refresh();
  10701. });
  10702. observer.observe(element, {
  10703. childList : true,
  10704. subtree : true
  10705. });
  10706. module.debug('Setting up mutation observer', observer);
  10707. }
  10708. },
  10709. refresh: function() {
  10710. module.remove.scrolling();
  10711. module.cacheSizes();
  10712. if(!module.can.useFlex()) {
  10713. module.set.modalOffset();
  10714. }
  10715. module.set.screenHeight();
  10716. module.set.type();
  10717. },
  10718. refreshModals: function() {
  10719. $otherModals = $module.siblings(selector.modal);
  10720. $allModals = $otherModals.add($module);
  10721. },
  10722. attachEvents: function(selector, event) {
  10723. var
  10724. $toggle = $(selector)
  10725. ;
  10726. event = $.isFunction(module[event])
  10727. ? module[event]
  10728. : module.toggle
  10729. ;
  10730. if($toggle.length > 0) {
  10731. module.debug('Attaching modal events to element', selector, event);
  10732. $toggle
  10733. .off(eventNamespace)
  10734. .on('click' + eventNamespace, event)
  10735. ;
  10736. }
  10737. else {
  10738. module.error(error.notFound, selector);
  10739. }
  10740. },
  10741. bind: {
  10742. events: function() {
  10743. module.verbose('Attaching events');
  10744. $module
  10745. .on('click' + eventNamespace, selector.close, module.event.close)
  10746. .on('click' + eventNamespace, selector.approve, module.event.approve)
  10747. .on('click' + eventNamespace, selector.deny, module.event.deny)
  10748. ;
  10749. $window
  10750. .on('resize' + elementEventNamespace, module.event.resize)
  10751. ;
  10752. },
  10753. scrollLock: function() {
  10754. // touch events default to passive, due to changes in chrome to optimize mobile perf
  10755. $dimmable.get(0).addEventListener('touchmove', module.event.preventScroll, { passive: false });
  10756. }
  10757. },
  10758. unbind: {
  10759. scrollLock: function() {
  10760. $dimmable.get(0).removeEventListener('touchmove', module.event.preventScroll, { passive: false });
  10761. }
  10762. },
  10763. get: {
  10764. id: function() {
  10765. return (Math.random().toString(16) + '000000000').substr(2, 8);
  10766. }
  10767. },
  10768. event: {
  10769. approve: function() {
  10770. if(ignoreRepeatedEvents || settings.onApprove.call(element, $(this)) === false) {
  10771. module.verbose('Approve callback returned false cancelling hide');
  10772. return;
  10773. }
  10774. ignoreRepeatedEvents = true;
  10775. module.hide(function() {
  10776. ignoreRepeatedEvents = false;
  10777. });
  10778. },
  10779. preventScroll: function(event) {
  10780. if(event.target.className.indexOf('dimmer') !== -1) {
  10781. event.preventDefault();
  10782. }
  10783. },
  10784. deny: function() {
  10785. if(ignoreRepeatedEvents || settings.onDeny.call(element, $(this)) === false) {
  10786. module.verbose('Deny callback returned false cancelling hide');
  10787. return;
  10788. }
  10789. ignoreRepeatedEvents = true;
  10790. module.hide(function() {
  10791. ignoreRepeatedEvents = false;
  10792. });
  10793. },
  10794. close: function() {
  10795. module.hide();
  10796. },
  10797. mousedown: function(event) {
  10798. var
  10799. $target = $(event.target),
  10800. isRtl = module.is.rtl();
  10801. ;
  10802. initialMouseDownInModal = ($target.closest(selector.modal).length > 0);
  10803. if(initialMouseDownInModal) {
  10804. module.verbose('Mouse down event registered inside the modal');
  10805. }
  10806. initialMouseDownInScrollbar = module.is.scrolling() && ((!isRtl && $(window).outerWidth() - settings.scrollbarWidth <= event.clientX) || (isRtl && settings.scrollbarWidth >= event.clientX));
  10807. if(initialMouseDownInScrollbar) {
  10808. module.verbose('Mouse down event registered inside the scrollbar');
  10809. }
  10810. },
  10811. mouseup: function(event) {
  10812. if(!settings.closable) {
  10813. module.verbose('Dimmer clicked but closable setting is disabled');
  10814. return;
  10815. }
  10816. if(initialMouseDownInModal) {
  10817. module.debug('Dimmer clicked but mouse down was initially registered inside the modal');
  10818. return;
  10819. }
  10820. if(initialMouseDownInScrollbar){
  10821. module.debug('Dimmer clicked but mouse down was initially registered inside the scrollbar');
  10822. return;
  10823. }
  10824. var
  10825. $target = $(event.target),
  10826. isInModal = ($target.closest(selector.modal).length > 0),
  10827. isInDOM = $.contains(document.documentElement, event.target)
  10828. ;
  10829. if(!isInModal && isInDOM && module.is.active() && $module.hasClass(className.front) ) {
  10830. module.debug('Dimmer clicked, hiding all modals');
  10831. if(settings.allowMultiple) {
  10832. if(!module.hideAll()) {
  10833. return;
  10834. }
  10835. }
  10836. else if(!module.hide()){
  10837. return;
  10838. }
  10839. module.remove.clickaway();
  10840. }
  10841. },
  10842. debounce: function(method, delay) {
  10843. clearTimeout(module.timer);
  10844. module.timer = setTimeout(method, delay);
  10845. },
  10846. keyboard: function(event) {
  10847. var
  10848. keyCode = event.which,
  10849. escapeKey = 27
  10850. ;
  10851. if(keyCode == escapeKey) {
  10852. if(settings.closable) {
  10853. module.debug('Escape key pressed hiding modal');
  10854. if ( $module.hasClass(className.front) ) {
  10855. module.hide();
  10856. }
  10857. }
  10858. else {
  10859. module.debug('Escape key pressed, but closable is set to false');
  10860. }
  10861. event.preventDefault();
  10862. }
  10863. },
  10864. resize: function() {
  10865. if( $dimmable.dimmer('is active') && ( module.is.animating() || module.is.active() ) ) {
  10866. requestAnimationFrame(module.refresh);
  10867. }
  10868. }
  10869. },
  10870. toggle: function() {
  10871. if( module.is.active() || module.is.animating() ) {
  10872. module.hide();
  10873. }
  10874. else {
  10875. module.show();
  10876. }
  10877. },
  10878. show: function(callback) {
  10879. callback = $.isFunction(callback)
  10880. ? callback
  10881. : function(){}
  10882. ;
  10883. module.refreshModals();
  10884. module.set.dimmerSettings();
  10885. module.set.dimmerStyles();
  10886. module.showModal(callback);
  10887. },
  10888. hide: function(callback) {
  10889. callback = $.isFunction(callback)
  10890. ? callback
  10891. : function(){}
  10892. ;
  10893. module.refreshModals();
  10894. return module.hideModal(callback);
  10895. },
  10896. showModal: function(callback) {
  10897. callback = $.isFunction(callback)
  10898. ? callback
  10899. : function(){}
  10900. ;
  10901. if( module.is.animating() || !module.is.active() ) {
  10902. module.showDimmer();
  10903. module.cacheSizes();
  10904. module.set.bodyMargin();
  10905. if(module.can.useFlex()) {
  10906. module.remove.legacy();
  10907. }
  10908. else {
  10909. module.set.legacy();
  10910. module.set.modalOffset();
  10911. module.debug('Using non-flex legacy modal positioning.');
  10912. }
  10913. module.set.screenHeight();
  10914. module.set.type();
  10915. module.set.clickaway();
  10916. if( !settings.allowMultiple && module.others.active() ) {
  10917. module.hideOthers(module.showModal);
  10918. }
  10919. else {
  10920. ignoreRepeatedEvents = false;
  10921. if( settings.allowMultiple ) {
  10922. if ( module.others.active() ) {
  10923. $otherModals.filter('.' + className.active).find(selector.dimmer).addClass('active');
  10924. }
  10925. if ( settings.detachable ) {
  10926. $module.detach().appendTo($dimmer);
  10927. }
  10928. }
  10929. settings.onShow.call(element);
  10930. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  10931. module.debug('Showing modal with css animations');
  10932. $module
  10933. .transition({
  10934. debug : settings.debug,
  10935. animation : settings.transition + ' in',
  10936. queue : settings.queue,
  10937. duration : settings.duration,
  10938. useFailSafe : true,
  10939. onComplete : function() {
  10940. settings.onVisible.apply(element);
  10941. if(settings.keyboardShortcuts) {
  10942. module.add.keyboardShortcuts();
  10943. }
  10944. module.save.focus();
  10945. module.set.active();
  10946. if(settings.autofocus) {
  10947. module.set.autofocus();
  10948. }
  10949. callback();
  10950. }
  10951. })
  10952. ;
  10953. }
  10954. else {
  10955. module.error(error.noTransition);
  10956. }
  10957. }
  10958. }
  10959. else {
  10960. module.debug('Modal is already visible');
  10961. }
  10962. },
  10963. hideModal: function(callback, keepDimmed, hideOthersToo) {
  10964. var
  10965. $previousModal = $otherModals.filter('.' + className.active).last()
  10966. ;
  10967. callback = $.isFunction(callback)
  10968. ? callback
  10969. : function(){}
  10970. ;
  10971. module.debug('Hiding modal');
  10972. if(settings.onHide.call(element, $(this)) === false) {
  10973. module.verbose('Hide callback returned false cancelling hide');
  10974. ignoreRepeatedEvents = false;
  10975. return false;
  10976. }
  10977. if( module.is.animating() || module.is.active() ) {
  10978. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  10979. module.remove.active();
  10980. $module
  10981. .transition({
  10982. debug : settings.debug,
  10983. animation : settings.transition + ' out',
  10984. queue : settings.queue,
  10985. duration : settings.duration,
  10986. useFailSafe : true,
  10987. onStart : function() {
  10988. if(!module.others.active() && !module.others.animating() && !keepDimmed) {
  10989. module.hideDimmer();
  10990. }
  10991. if( settings.keyboardShortcuts && !module.others.active() ) {
  10992. module.remove.keyboardShortcuts();
  10993. }
  10994. },
  10995. onComplete : function() {
  10996. module.unbind.scrollLock();
  10997. if ( settings.allowMultiple ) {
  10998. $previousModal.addClass(className.front);
  10999. $module.removeClass(className.front);
  11000. if ( hideOthersToo ) {
  11001. $allModals.find(selector.dimmer).removeClass('active');
  11002. }
  11003. else {
  11004. $previousModal.find(selector.dimmer).removeClass('active');
  11005. }
  11006. }
  11007. settings.onHidden.call(element);
  11008. module.remove.dimmerStyles();
  11009. module.restore.focus();
  11010. callback();
  11011. }
  11012. })
  11013. ;
  11014. }
  11015. else {
  11016. module.error(error.noTransition);
  11017. }
  11018. }
  11019. },
  11020. showDimmer: function() {
  11021. if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
  11022. module.save.bodyMargin();
  11023. module.debug('Showing dimmer');
  11024. $dimmable.dimmer('show');
  11025. }
  11026. else {
  11027. module.debug('Dimmer already visible');
  11028. }
  11029. },
  11030. hideDimmer: function() {
  11031. if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
  11032. module.unbind.scrollLock();
  11033. $dimmable.dimmer('hide', function() {
  11034. module.restore.bodyMargin();
  11035. module.remove.clickaway();
  11036. module.remove.screenHeight();
  11037. });
  11038. }
  11039. else {
  11040. module.debug('Dimmer is not visible cannot hide');
  11041. return;
  11042. }
  11043. },
  11044. hideAll: function(callback) {
  11045. var
  11046. $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
  11047. ;
  11048. callback = $.isFunction(callback)
  11049. ? callback
  11050. : function(){}
  11051. ;
  11052. if( $visibleModals.length > 0 ) {
  11053. module.debug('Hiding all visible modals');
  11054. var hideOk = true;
  11055. //check in reverse order trying to hide most top displayed modal first
  11056. $($visibleModals.get().reverse()).each(function(index,element){
  11057. if(hideOk){
  11058. hideOk = $(element).modal('hide modal', callback, false, true);
  11059. }
  11060. });
  11061. if(hideOk) {
  11062. module.hideDimmer();
  11063. }
  11064. return hideOk;
  11065. }
  11066. },
  11067. hideOthers: function(callback) {
  11068. var
  11069. $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
  11070. ;
  11071. callback = $.isFunction(callback)
  11072. ? callback
  11073. : function(){}
  11074. ;
  11075. if( $visibleModals.length > 0 ) {
  11076. module.debug('Hiding other modals', $otherModals);
  11077. $visibleModals
  11078. .modal('hide modal', callback, true)
  11079. ;
  11080. }
  11081. },
  11082. others: {
  11083. active: function() {
  11084. return ($otherModals.filter('.' + className.active).length > 0);
  11085. },
  11086. animating: function() {
  11087. return ($otherModals.filter('.' + className.animating).length > 0);
  11088. }
  11089. },
  11090. add: {
  11091. keyboardShortcuts: function() {
  11092. module.verbose('Adding keyboard shortcuts');
  11093. $document
  11094. .on('keyup' + eventNamespace, module.event.keyboard)
  11095. ;
  11096. }
  11097. },
  11098. save: {
  11099. focus: function() {
  11100. var
  11101. $activeElement = $(document.activeElement),
  11102. inCurrentModal = $activeElement.closest($module).length > 0
  11103. ;
  11104. if(!inCurrentModal) {
  11105. $focusedElement = $(document.activeElement).blur();
  11106. }
  11107. },
  11108. bodyMargin: function() {
  11109. initialBodyMargin = $body.css('margin-'+(module.can.leftBodyScrollbar() ? 'left':'right'));
  11110. var bodyMarginRightPixel = parseInt(initialBodyMargin.replace(/[^\d.]/g, '')),
  11111. bodyScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
  11112. tempBodyMargin = bodyMarginRightPixel + bodyScrollbarWidth;
  11113. }
  11114. },
  11115. restore: {
  11116. focus: function() {
  11117. if($focusedElement && $focusedElement.length > 0 && settings.restoreFocus) {
  11118. $focusedElement.focus();
  11119. }
  11120. },
  11121. bodyMargin: function() {
  11122. var position = module.can.leftBodyScrollbar() ? 'left':'right';
  11123. $body.css('margin-'+position, initialBodyMargin);
  11124. $body.find(selector.bodyFixed.replace('right',position)).css('padding-'+position, initialBodyMargin);
  11125. }
  11126. },
  11127. remove: {
  11128. active: function() {
  11129. $module.removeClass(className.active);
  11130. },
  11131. legacy: function() {
  11132. $module.removeClass(className.legacy);
  11133. },
  11134. clickaway: function() {
  11135. if (!settings.detachable) {
  11136. $module
  11137. .off('mousedown' + elementEventNamespace)
  11138. ;
  11139. }
  11140. $dimmer
  11141. .off('mousedown' + elementEventNamespace)
  11142. ;
  11143. $dimmer
  11144. .off('mouseup' + elementEventNamespace)
  11145. ;
  11146. },
  11147. dimmerStyles: function() {
  11148. $dimmer.removeClass(className.inverted);
  11149. $dimmable.removeClass(className.blurring);
  11150. },
  11151. bodyStyle: function() {
  11152. if($body.attr('style') === '') {
  11153. module.verbose('Removing style attribute');
  11154. $body.removeAttr('style');
  11155. }
  11156. },
  11157. screenHeight: function() {
  11158. module.debug('Removing page height');
  11159. $body
  11160. .css('height', '')
  11161. ;
  11162. },
  11163. keyboardShortcuts: function() {
  11164. module.verbose('Removing keyboard shortcuts');
  11165. $document
  11166. .off('keyup' + eventNamespace)
  11167. ;
  11168. },
  11169. scrolling: function() {
  11170. $dimmable.removeClass(className.scrolling);
  11171. $module.removeClass(className.scrolling);
  11172. }
  11173. },
  11174. cacheSizes: function() {
  11175. $module.addClass(className.loading);
  11176. var
  11177. scrollHeight = $module.prop('scrollHeight'),
  11178. modalWidth = $module.outerWidth(),
  11179. modalHeight = $module.outerHeight()
  11180. ;
  11181. if(module.cache.pageHeight === undefined || modalHeight !== 0) {
  11182. $.extend(module.cache, {
  11183. pageHeight : $(document).outerHeight(),
  11184. width : modalWidth,
  11185. height : modalHeight + settings.offset,
  11186. scrollHeight : scrollHeight + settings.offset,
  11187. contextHeight : (settings.context == 'body')
  11188. ? $(window).height()
  11189. : $dimmable.height(),
  11190. });
  11191. module.cache.topOffset = -(module.cache.height / 2);
  11192. }
  11193. $module.removeClass(className.loading);
  11194. module.debug('Caching modal and container sizes', module.cache);
  11195. },
  11196. can: {
  11197. leftBodyScrollbar: function(){
  11198. if(module.cache.leftBodyScrollbar === undefined) {
  11199. module.cache.leftBodyScrollbar = module.is.rtl() && ((module.is.iframe && !module.is.firefox()) || module.is.safari() || module.is.edge() || module.is.ie());
  11200. }
  11201. return module.cache.leftBodyScrollbar;
  11202. },
  11203. useFlex: function() {
  11204. return settings.useFlex && settings.detachable && !module.is.ie();
  11205. },
  11206. fit: function() {
  11207. var
  11208. contextHeight = module.cache.contextHeight,
  11209. verticalCenter = module.cache.contextHeight / 2,
  11210. topOffset = module.cache.topOffset,
  11211. scrollHeight = module.cache.scrollHeight,
  11212. height = module.cache.height,
  11213. paddingHeight = settings.padding,
  11214. startPosition = (verticalCenter + topOffset)
  11215. ;
  11216. return (scrollHeight > height)
  11217. ? (startPosition + scrollHeight + paddingHeight < contextHeight)
  11218. : (height + (paddingHeight * 2) < contextHeight)
  11219. ;
  11220. }
  11221. },
  11222. is: {
  11223. active: function() {
  11224. return $module.hasClass(className.active);
  11225. },
  11226. ie: function() {
  11227. if(module.cache.isIE === undefined) {
  11228. var
  11229. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  11230. isIE = ('ActiveXObject' in window)
  11231. ;
  11232. module.cache.isIE = (isIE11 || isIE);
  11233. }
  11234. return module.cache.isIE;
  11235. },
  11236. animating: function() {
  11237. return $module.transition('is supported')
  11238. ? $module.transition('is animating')
  11239. : $module.is(':visible')
  11240. ;
  11241. },
  11242. scrolling: function() {
  11243. return $dimmable.hasClass(className.scrolling);
  11244. },
  11245. modernBrowser: function() {
  11246. // appName for IE11 reports 'Netscape' can no longer use
  11247. return !(window.ActiveXObject || 'ActiveXObject' in window);
  11248. },
  11249. rtl: function() {
  11250. if(module.cache.isRTL === undefined) {
  11251. module.cache.isRTL = $body.attr('dir') === 'rtl' || $body.css('direction') === 'rtl';
  11252. }
  11253. return module.cache.isRTL;
  11254. },
  11255. safari: function() {
  11256. if(module.cache.isSafari === undefined) {
  11257. module.cache.isSafari = /constructor/i.test(window.HTMLElement) || !!window.ApplePaySession;
  11258. }
  11259. return module.cache.isSafari;
  11260. },
  11261. edge: function(){
  11262. if(module.cache.isEdge === undefined) {
  11263. module.cache.isEdge = !!window.setImmediate && !module.is.ie();
  11264. }
  11265. return module.cache.isEdge;
  11266. },
  11267. firefox: function(){
  11268. if(module.cache.isFirefox === undefined) {
  11269. module.cache.isFirefox = !!window.InstallTrigger;
  11270. }
  11271. return module.cache.isFirefox;
  11272. },
  11273. iframe: function() {
  11274. return !(self === top);
  11275. }
  11276. },
  11277. set: {
  11278. autofocus: function() {
  11279. var
  11280. $inputs = $module.find('[tabindex], :input').filter(':visible').filter(function() {
  11281. return $(this).closest('.disabled').length === 0;
  11282. }),
  11283. $autofocus = $inputs.filter('[autofocus]'),
  11284. $input = ($autofocus.length > 0)
  11285. ? $autofocus.first()
  11286. : $inputs.first()
  11287. ;
  11288. if($input.length > 0) {
  11289. $input.focus();
  11290. }
  11291. },
  11292. bodyMargin: function() {
  11293. var position = module.can.leftBodyScrollbar() ? 'left':'right';
  11294. if(settings.detachable || module.can.fit()) {
  11295. $body.css('margin-'+position, tempBodyMargin + 'px');
  11296. }
  11297. $body.find(selector.bodyFixed.replace('right',position)).css('padding-'+position, tempBodyMargin + 'px');
  11298. },
  11299. clickaway: function() {
  11300. if (!settings.detachable) {
  11301. $module
  11302. .on('mousedown' + elementEventNamespace, module.event.mousedown)
  11303. ;
  11304. }
  11305. $dimmer
  11306. .on('mousedown' + elementEventNamespace, module.event.mousedown)
  11307. ;
  11308. $dimmer
  11309. .on('mouseup' + elementEventNamespace, module.event.mouseup)
  11310. ;
  11311. },
  11312. dimmerSettings: function() {
  11313. if($.fn.dimmer === undefined) {
  11314. module.error(error.dimmer);
  11315. return;
  11316. }
  11317. var
  11318. defaultSettings = {
  11319. debug : settings.debug,
  11320. dimmerName : 'modals',
  11321. closable : 'auto',
  11322. useFlex : module.can.useFlex(),
  11323. duration : {
  11324. show : settings.duration,
  11325. hide : settings.duration
  11326. }
  11327. },
  11328. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  11329. ;
  11330. if(settings.inverted) {
  11331. dimmerSettings.variation = (dimmerSettings.variation !== undefined)
  11332. ? dimmerSettings.variation + ' inverted'
  11333. : 'inverted'
  11334. ;
  11335. }
  11336. $context.dimmer('setting', dimmerSettings);
  11337. },
  11338. dimmerStyles: function() {
  11339. if(settings.inverted) {
  11340. $dimmer.addClass(className.inverted);
  11341. }
  11342. else {
  11343. $dimmer.removeClass(className.inverted);
  11344. }
  11345. if(settings.blurring) {
  11346. $dimmable.addClass(className.blurring);
  11347. }
  11348. else {
  11349. $dimmable.removeClass(className.blurring);
  11350. }
  11351. },
  11352. modalOffset: function() {
  11353. if (!settings.detachable) {
  11354. var canFit = module.can.fit();
  11355. $module
  11356. .css({
  11357. top: (!$module.hasClass('aligned') && canFit)
  11358. ? $(document).scrollTop() + (module.cache.contextHeight - module.cache.height) / 2
  11359. : !canFit || $module.hasClass('top')
  11360. ? $(document).scrollTop() + settings.padding
  11361. : $(document).scrollTop() + (module.cache.contextHeight - module.cache.height - settings.padding),
  11362. marginLeft: -(module.cache.width / 2)
  11363. })
  11364. ;
  11365. } else {
  11366. $module
  11367. .css({
  11368. marginTop: (!$module.hasClass('aligned') && module.can.fit())
  11369. ? -(module.cache.height / 2)
  11370. : settings.padding / 2,
  11371. marginLeft: -(module.cache.width / 2)
  11372. })
  11373. ;
  11374. }
  11375. module.verbose('Setting modal offset for legacy mode');
  11376. },
  11377. screenHeight: function() {
  11378. if( module.can.fit() ) {
  11379. $body.css('height', '');
  11380. }
  11381. else if(!$module.hasClass('bottom')) {
  11382. module.debug('Modal is taller than page content, resizing page height');
  11383. $body
  11384. .css('height', module.cache.height + (settings.padding * 2) )
  11385. ;
  11386. }
  11387. },
  11388. active: function() {
  11389. $module.addClass(className.active + ' ' + className.front);
  11390. $otherModals.filter('.' + className.active).removeClass(className.front);
  11391. },
  11392. scrolling: function() {
  11393. $dimmable.addClass(className.scrolling);
  11394. $module.addClass(className.scrolling);
  11395. module.unbind.scrollLock();
  11396. },
  11397. legacy: function() {
  11398. $module.addClass(className.legacy);
  11399. },
  11400. type: function() {
  11401. if(module.can.fit()) {
  11402. module.verbose('Modal fits on screen');
  11403. if(!module.others.active() && !module.others.animating()) {
  11404. module.remove.scrolling();
  11405. module.bind.scrollLock();
  11406. }
  11407. }
  11408. else if (!$module.hasClass('bottom')){
  11409. module.verbose('Modal cannot fit on screen setting to scrolling');
  11410. module.set.scrolling();
  11411. } else {
  11412. module.verbose('Bottom aligned modal not fitting on screen is unsupported for scrolling');
  11413. }
  11414. },
  11415. undetached: function() {
  11416. $dimmable.addClass(className.undetached);
  11417. }
  11418. },
  11419. setting: function(name, value) {
  11420. module.debug('Changing setting', name, value);
  11421. if( $.isPlainObject(name) ) {
  11422. $.extend(true, settings, name);
  11423. }
  11424. else if(value !== undefined) {
  11425. if($.isPlainObject(settings[name])) {
  11426. $.extend(true, settings[name], value);
  11427. }
  11428. else {
  11429. settings[name] = value;
  11430. }
  11431. }
  11432. else {
  11433. return settings[name];
  11434. }
  11435. },
  11436. internal: function(name, value) {
  11437. if( $.isPlainObject(name) ) {
  11438. $.extend(true, module, name);
  11439. }
  11440. else if(value !== undefined) {
  11441. module[name] = value;
  11442. }
  11443. else {
  11444. return module[name];
  11445. }
  11446. },
  11447. debug: function() {
  11448. if(!settings.silent && settings.debug) {
  11449. if(settings.performance) {
  11450. module.performance.log(arguments);
  11451. }
  11452. else {
  11453. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11454. module.debug.apply(console, arguments);
  11455. }
  11456. }
  11457. },
  11458. verbose: function() {
  11459. if(!settings.silent && settings.verbose && settings.debug) {
  11460. if(settings.performance) {
  11461. module.performance.log(arguments);
  11462. }
  11463. else {
  11464. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11465. module.verbose.apply(console, arguments);
  11466. }
  11467. }
  11468. },
  11469. error: function() {
  11470. if(!settings.silent) {
  11471. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  11472. module.error.apply(console, arguments);
  11473. }
  11474. },
  11475. performance: {
  11476. log: function(message) {
  11477. var
  11478. currentTime,
  11479. executionTime,
  11480. previousTime
  11481. ;
  11482. if(settings.performance) {
  11483. currentTime = new Date().getTime();
  11484. previousTime = time || currentTime;
  11485. executionTime = currentTime - previousTime;
  11486. time = currentTime;
  11487. performance.push({
  11488. 'Name' : message[0],
  11489. 'Arguments' : [].slice.call(message, 1) || '',
  11490. 'Element' : element,
  11491. 'Execution Time' : executionTime
  11492. });
  11493. }
  11494. clearTimeout(module.performance.timer);
  11495. module.performance.timer = setTimeout(module.performance.display, 500);
  11496. },
  11497. display: function() {
  11498. var
  11499. title = settings.name + ':',
  11500. totalTime = 0
  11501. ;
  11502. time = false;
  11503. clearTimeout(module.performance.timer);
  11504. $.each(performance, function(index, data) {
  11505. totalTime += data['Execution Time'];
  11506. });
  11507. title += ' ' + totalTime + 'ms';
  11508. if(moduleSelector) {
  11509. title += ' \'' + moduleSelector + '\'';
  11510. }
  11511. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  11512. console.groupCollapsed(title);
  11513. if(console.table) {
  11514. console.table(performance);
  11515. }
  11516. else {
  11517. $.each(performance, function(index, data) {
  11518. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  11519. });
  11520. }
  11521. console.groupEnd();
  11522. }
  11523. performance = [];
  11524. }
  11525. },
  11526. invoke: function(query, passedArguments, context) {
  11527. var
  11528. object = instance,
  11529. maxDepth,
  11530. found,
  11531. response
  11532. ;
  11533. passedArguments = passedArguments || queryArguments;
  11534. context = element || context;
  11535. if(typeof query == 'string' && object !== undefined) {
  11536. query = query.split(/[\. ]/);
  11537. maxDepth = query.length - 1;
  11538. $.each(query, function(depth, value) {
  11539. var camelCaseValue = (depth != maxDepth)
  11540. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  11541. : query
  11542. ;
  11543. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  11544. object = object[camelCaseValue];
  11545. }
  11546. else if( object[camelCaseValue] !== undefined ) {
  11547. found = object[camelCaseValue];
  11548. return false;
  11549. }
  11550. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  11551. object = object[value];
  11552. }
  11553. else if( object[value] !== undefined ) {
  11554. found = object[value];
  11555. return false;
  11556. }
  11557. else {
  11558. return false;
  11559. }
  11560. });
  11561. }
  11562. if ( $.isFunction( found ) ) {
  11563. response = found.apply(context, passedArguments);
  11564. }
  11565. else if(found !== undefined) {
  11566. response = found;
  11567. }
  11568. if(Array.isArray(returnedValue)) {
  11569. returnedValue.push(response);
  11570. }
  11571. else if(returnedValue !== undefined) {
  11572. returnedValue = [returnedValue, response];
  11573. }
  11574. else if(response !== undefined) {
  11575. returnedValue = response;
  11576. }
  11577. return found;
  11578. }
  11579. };
  11580. if(methodInvoked) {
  11581. if(instance === undefined) {
  11582. module.initialize();
  11583. }
  11584. module.invoke(query);
  11585. }
  11586. else {
  11587. if(instance !== undefined) {
  11588. instance.invoke('destroy');
  11589. }
  11590. module.initialize();
  11591. }
  11592. })
  11593. ;
  11594. return (returnedValue !== undefined)
  11595. ? returnedValue
  11596. : this
  11597. ;
  11598. };
  11599. $.fn.modal.settings = {
  11600. name : 'Modal',
  11601. namespace : 'modal',
  11602. useFlex : 'auto',
  11603. offset : 0,
  11604. silent : false,
  11605. debug : false,
  11606. verbose : false,
  11607. performance : true,
  11608. observeChanges : false,
  11609. allowMultiple : false,
  11610. detachable : true,
  11611. closable : true,
  11612. autofocus : true,
  11613. restoreFocus : true,
  11614. inverted : false,
  11615. blurring : false,
  11616. centered : true,
  11617. dimmerSettings : {
  11618. closable : false,
  11619. useCSS : true
  11620. },
  11621. // whether to use keyboard shortcuts
  11622. keyboardShortcuts: true,
  11623. context : 'body',
  11624. queue : false,
  11625. duration : 500,
  11626. transition : 'scale',
  11627. // padding with edge of page
  11628. padding : 50,
  11629. scrollbarWidth: 10,
  11630. // called before show animation
  11631. onShow : function(){},
  11632. // called after show animation
  11633. onVisible : function(){},
  11634. // called before hide animation
  11635. onHide : function(){ return true; },
  11636. // called after hide animation
  11637. onHidden : function(){},
  11638. // called after approve selector match
  11639. onApprove : function(){ return true; },
  11640. // called after deny selector match
  11641. onDeny : function(){ return true; },
  11642. selector : {
  11643. close : '> .close',
  11644. approve : '.actions .positive, .actions .approve, .actions .ok',
  11645. deny : '.actions .negative, .actions .deny, .actions .cancel',
  11646. modal : '.ui.modal',
  11647. dimmer : '> .ui.dimmer',
  11648. bodyFixed: '> .ui.fixed.menu, > .ui.right.toast-container, > .ui.right.sidebar'
  11649. },
  11650. error : {
  11651. dimmer : 'UI Dimmer, a required component is not included in this page',
  11652. method : 'The method you called is not defined.',
  11653. notFound : 'The element you specified could not be found'
  11654. },
  11655. className : {
  11656. active : 'active',
  11657. animating : 'animating',
  11658. blurring : 'blurring',
  11659. inverted : 'inverted',
  11660. legacy : 'legacy',
  11661. loading : 'loading',
  11662. scrolling : 'scrolling',
  11663. undetached : 'undetached',
  11664. front : 'front'
  11665. }
  11666. };
  11667. })( jQuery, window, document );
  11668. /*!
  11669. * # Fomantic-UI - Nag
  11670. * http://github.com/fomantic/Fomantic-UI/
  11671. *
  11672. *
  11673. * Released under the MIT license
  11674. * http://opensource.org/licenses/MIT
  11675. *
  11676. */
  11677. ;(function ($, window, document, undefined) {
  11678. 'use strict';
  11679. $.isFunction = $.isFunction || function(obj) {
  11680. return typeof obj === "function" && typeof obj.nodeType !== "number";
  11681. };
  11682. window = (typeof window != 'undefined' && window.Math == Math)
  11683. ? window
  11684. : (typeof self != 'undefined' && self.Math == Math)
  11685. ? self
  11686. : Function('return this')()
  11687. ;
  11688. $.fn.nag = function(parameters) {
  11689. var
  11690. $allModules = $(this),
  11691. moduleSelector = $allModules.selector || '',
  11692. time = new Date().getTime(),
  11693. performance = [],
  11694. query = arguments[0],
  11695. methodInvoked = (typeof query == 'string'),
  11696. queryArguments = [].slice.call(arguments, 1),
  11697. returnedValue
  11698. ;
  11699. $allModules
  11700. .each(function() {
  11701. var
  11702. settings = ( $.isPlainObject(parameters) )
  11703. ? $.extend(true, {}, $.fn.nag.settings, parameters)
  11704. : $.extend({}, $.fn.nag.settings),
  11705. selector = settings.selector,
  11706. error = settings.error,
  11707. namespace = settings.namespace,
  11708. eventNamespace = '.' + namespace,
  11709. moduleNamespace = namespace + '-module',
  11710. $module = $(this),
  11711. $context = (settings.context)
  11712. ? $(settings.context)
  11713. : $('body'),
  11714. element = this,
  11715. instance = $module.data(moduleNamespace),
  11716. module
  11717. ;
  11718. module = {
  11719. initialize: function() {
  11720. module.verbose('Initializing element');
  11721. $module
  11722. .on('click' + eventNamespace, selector.close, module.dismiss)
  11723. .data(moduleNamespace, module)
  11724. ;
  11725. if(settings.detachable && $module.parent()[0] !== $context[0]) {
  11726. $module
  11727. .detach()
  11728. .prependTo($context)
  11729. ;
  11730. }
  11731. if(settings.displayTime > 0) {
  11732. setTimeout(module.hide, settings.displayTime);
  11733. }
  11734. module.show();
  11735. },
  11736. destroy: function() {
  11737. module.verbose('Destroying instance');
  11738. $module
  11739. .removeData(moduleNamespace)
  11740. .off(eventNamespace)
  11741. ;
  11742. },
  11743. show: function() {
  11744. if( module.should.show() && !$module.is(':visible') ) {
  11745. module.debug('Showing nag', settings.animation.show);
  11746. if(settings.animation.show == 'fade') {
  11747. $module
  11748. .fadeIn(settings.duration, settings.easing)
  11749. ;
  11750. }
  11751. else {
  11752. $module
  11753. .slideDown(settings.duration, settings.easing)
  11754. ;
  11755. }
  11756. }
  11757. },
  11758. hide: function() {
  11759. module.debug('Showing nag', settings.animation.hide);
  11760. if(settings.animation.show == 'fade') {
  11761. $module
  11762. .fadeIn(settings.duration, settings.easing)
  11763. ;
  11764. }
  11765. else {
  11766. $module
  11767. .slideUp(settings.duration, settings.easing)
  11768. ;
  11769. }
  11770. },
  11771. onHide: function() {
  11772. module.debug('Removing nag', settings.animation.hide);
  11773. $module.remove();
  11774. if (settings.onHide) {
  11775. settings.onHide();
  11776. }
  11777. },
  11778. dismiss: function(event) {
  11779. if(settings.storageMethod) {
  11780. module.storage.set(settings.key, settings.value);
  11781. }
  11782. module.hide();
  11783. event.stopImmediatePropagation();
  11784. event.preventDefault();
  11785. },
  11786. should: {
  11787. show: function() {
  11788. if(settings.persist) {
  11789. module.debug('Persistent nag is set, can show nag');
  11790. return true;
  11791. }
  11792. if( module.storage.get(settings.key) != settings.value.toString() ) {
  11793. module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
  11794. return true;
  11795. }
  11796. module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
  11797. return false;
  11798. }
  11799. },
  11800. get: {
  11801. storageOptions: function() {
  11802. var
  11803. options = {}
  11804. ;
  11805. if(settings.expires) {
  11806. options.expires = settings.expires;
  11807. }
  11808. if(settings.domain) {
  11809. options.domain = settings.domain;
  11810. }
  11811. if(settings.path) {
  11812. options.path = settings.path;
  11813. }
  11814. return options;
  11815. }
  11816. },
  11817. clear: function() {
  11818. module.storage.remove(settings.key);
  11819. },
  11820. storage: {
  11821. set: function(key, value) {
  11822. var
  11823. options = module.get.storageOptions()
  11824. ;
  11825. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  11826. window.localStorage.setItem(key, value);
  11827. module.debug('Value stored using local storage', key, value);
  11828. }
  11829. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  11830. window.sessionStorage.setItem(key, value);
  11831. module.debug('Value stored using session storage', key, value);
  11832. }
  11833. else if($.cookie !== undefined) {
  11834. $.cookie(key, value, options);
  11835. module.debug('Value stored using cookie', key, value, options);
  11836. }
  11837. else {
  11838. module.error(error.noCookieStorage);
  11839. return;
  11840. }
  11841. },
  11842. get: function(key, value) {
  11843. var
  11844. storedValue
  11845. ;
  11846. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  11847. storedValue = window.localStorage.getItem(key);
  11848. }
  11849. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  11850. storedValue = window.sessionStorage.getItem(key);
  11851. }
  11852. // get by cookie
  11853. else if($.cookie !== undefined) {
  11854. storedValue = $.cookie(key);
  11855. }
  11856. else {
  11857. module.error(error.noCookieStorage);
  11858. }
  11859. if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
  11860. storedValue = undefined;
  11861. }
  11862. return storedValue;
  11863. },
  11864. remove: function(key) {
  11865. var
  11866. options = module.get.storageOptions()
  11867. ;
  11868. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  11869. window.localStorage.removeItem(key);
  11870. }
  11871. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  11872. window.sessionStorage.removeItem(key);
  11873. }
  11874. // store by cookie
  11875. else if($.cookie !== undefined) {
  11876. $.removeCookie(key, options);
  11877. }
  11878. else {
  11879. module.error(error.noStorage);
  11880. }
  11881. }
  11882. },
  11883. setting: function(name, value) {
  11884. module.debug('Changing setting', name, value);
  11885. if( $.isPlainObject(name) ) {
  11886. $.extend(true, settings, name);
  11887. }
  11888. else if(value !== undefined) {
  11889. if($.isPlainObject(settings[name])) {
  11890. $.extend(true, settings[name], value);
  11891. }
  11892. else {
  11893. settings[name] = value;
  11894. }
  11895. }
  11896. else {
  11897. return settings[name];
  11898. }
  11899. },
  11900. internal: function(name, value) {
  11901. if( $.isPlainObject(name) ) {
  11902. $.extend(true, module, name);
  11903. }
  11904. else if(value !== undefined) {
  11905. module[name] = value;
  11906. }
  11907. else {
  11908. return module[name];
  11909. }
  11910. },
  11911. debug: function() {
  11912. if(!settings.silent && settings.debug) {
  11913. if(settings.performance) {
  11914. module.performance.log(arguments);
  11915. }
  11916. else {
  11917. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11918. module.debug.apply(console, arguments);
  11919. }
  11920. }
  11921. },
  11922. verbose: function() {
  11923. if(!settings.silent && settings.verbose && settings.debug) {
  11924. if(settings.performance) {
  11925. module.performance.log(arguments);
  11926. }
  11927. else {
  11928. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11929. module.verbose.apply(console, arguments);
  11930. }
  11931. }
  11932. },
  11933. error: function() {
  11934. if(!settings.silent) {
  11935. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  11936. module.error.apply(console, arguments);
  11937. }
  11938. },
  11939. performance: {
  11940. log: function(message) {
  11941. var
  11942. currentTime,
  11943. executionTime,
  11944. previousTime
  11945. ;
  11946. if(settings.performance) {
  11947. currentTime = new Date().getTime();
  11948. previousTime = time || currentTime;
  11949. executionTime = currentTime - previousTime;
  11950. time = currentTime;
  11951. performance.push({
  11952. 'Name' : message[0],
  11953. 'Arguments' : [].slice.call(message, 1) || '',
  11954. 'Element' : element,
  11955. 'Execution Time' : executionTime
  11956. });
  11957. }
  11958. clearTimeout(module.performance.timer);
  11959. module.performance.timer = setTimeout(module.performance.display, 500);
  11960. },
  11961. display: function() {
  11962. var
  11963. title = settings.name + ':',
  11964. totalTime = 0
  11965. ;
  11966. time = false;
  11967. clearTimeout(module.performance.timer);
  11968. $.each(performance, function(index, data) {
  11969. totalTime += data['Execution Time'];
  11970. });
  11971. title += ' ' + totalTime + 'ms';
  11972. if(moduleSelector) {
  11973. title += ' \'' + moduleSelector + '\'';
  11974. }
  11975. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  11976. console.groupCollapsed(title);
  11977. if(console.table) {
  11978. console.table(performance);
  11979. }
  11980. else {
  11981. $.each(performance, function(index, data) {
  11982. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  11983. });
  11984. }
  11985. console.groupEnd();
  11986. }
  11987. performance = [];
  11988. }
  11989. },
  11990. invoke: function(query, passedArguments, context) {
  11991. var
  11992. object = instance,
  11993. maxDepth,
  11994. found,
  11995. response
  11996. ;
  11997. passedArguments = passedArguments || queryArguments;
  11998. context = element || context;
  11999. if(typeof query == 'string' && object !== undefined) {
  12000. query = query.split(/[\. ]/);
  12001. maxDepth = query.length - 1;
  12002. $.each(query, function(depth, value) {
  12003. var camelCaseValue = (depth != maxDepth)
  12004. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  12005. : query
  12006. ;
  12007. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  12008. object = object[camelCaseValue];
  12009. }
  12010. else if( object[camelCaseValue] !== undefined ) {
  12011. found = object[camelCaseValue];
  12012. return false;
  12013. }
  12014. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  12015. object = object[value];
  12016. }
  12017. else if( object[value] !== undefined ) {
  12018. found = object[value];
  12019. return false;
  12020. }
  12021. else {
  12022. module.error(error.method, query);
  12023. return false;
  12024. }
  12025. });
  12026. }
  12027. if ( $.isFunction( found ) ) {
  12028. response = found.apply(context, passedArguments);
  12029. }
  12030. else if(found !== undefined) {
  12031. response = found;
  12032. }
  12033. if(Array.isArray(returnedValue)) {
  12034. returnedValue.push(response);
  12035. }
  12036. else if(returnedValue !== undefined) {
  12037. returnedValue = [returnedValue, response];
  12038. }
  12039. else if(response !== undefined) {
  12040. returnedValue = response;
  12041. }
  12042. return found;
  12043. }
  12044. };
  12045. if(methodInvoked) {
  12046. if(instance === undefined) {
  12047. module.initialize();
  12048. }
  12049. module.invoke(query);
  12050. }
  12051. else {
  12052. if(instance !== undefined) {
  12053. instance.invoke('destroy');
  12054. }
  12055. module.initialize();
  12056. }
  12057. })
  12058. ;
  12059. return (returnedValue !== undefined)
  12060. ? returnedValue
  12061. : this
  12062. ;
  12063. };
  12064. $.fn.nag.settings = {
  12065. name : 'Nag',
  12066. silent : false,
  12067. debug : false,
  12068. verbose : false,
  12069. performance : true,
  12070. namespace : 'Nag',
  12071. // allows cookie to be overridden
  12072. persist : false,
  12073. // set to zero to require manually dismissal, otherwise hides on its own
  12074. displayTime : 0,
  12075. animation : {
  12076. show : 'slide',
  12077. hide : 'slide'
  12078. },
  12079. context : false,
  12080. detachable : false,
  12081. expires : 30,
  12082. domain : false,
  12083. path : '/',
  12084. // type of storage to use
  12085. storageMethod : 'cookie',
  12086. // value to store in dismissed localstorage/cookie
  12087. key : 'nag',
  12088. value : 'dismiss',
  12089. error: {
  12090. noCookieStorage : '$.cookie is not included. A storage solution is required.',
  12091. noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
  12092. method : 'The method you called is not defined.'
  12093. },
  12094. className : {
  12095. bottom : 'bottom',
  12096. fixed : 'fixed'
  12097. },
  12098. selector : {
  12099. close : '.close.icon'
  12100. },
  12101. speed : 500,
  12102. easing : 'easeOutQuad',
  12103. onHide: function() {}
  12104. };
  12105. // Adds easing
  12106. $.extend( $.easing, {
  12107. easeOutQuad: function (x, t, b, c, d) {
  12108. return -c *(t/=d)*(t-2) + b;
  12109. }
  12110. });
  12111. })( jQuery, window, document );
  12112. /*!
  12113. * # Fomantic-UI - Popup
  12114. * http://github.com/fomantic/Fomantic-UI/
  12115. *
  12116. *
  12117. * Released under the MIT license
  12118. * http://opensource.org/licenses/MIT
  12119. *
  12120. */
  12121. ;(function ($, window, document, undefined) {
  12122. 'use strict';
  12123. $.isFunction = $.isFunction || function(obj) {
  12124. return typeof obj === "function" && typeof obj.nodeType !== "number";
  12125. };
  12126. window = (typeof window != 'undefined' && window.Math == Math)
  12127. ? window
  12128. : (typeof self != 'undefined' && self.Math == Math)
  12129. ? self
  12130. : Function('return this')()
  12131. ;
  12132. $.fn.popup = function(parameters) {
  12133. var
  12134. $allModules = $(this),
  12135. $document = $(document),
  12136. $window = $(window),
  12137. $body = $('body'),
  12138. moduleSelector = $allModules.selector || '',
  12139. clickEvent = ('ontouchstart' in document.documentElement)
  12140. ? 'touchstart'
  12141. : 'click',
  12142. time = new Date().getTime(),
  12143. performance = [],
  12144. query = arguments[0],
  12145. methodInvoked = (typeof query == 'string'),
  12146. queryArguments = [].slice.call(arguments, 1),
  12147. returnedValue
  12148. ;
  12149. $allModules
  12150. .each(function() {
  12151. var
  12152. settings = ( $.isPlainObject(parameters) )
  12153. ? $.extend(true, {}, $.fn.popup.settings, parameters)
  12154. : $.extend({}, $.fn.popup.settings),
  12155. selector = settings.selector,
  12156. className = settings.className,
  12157. error = settings.error,
  12158. metadata = settings.metadata,
  12159. namespace = settings.namespace,
  12160. eventNamespace = '.' + settings.namespace,
  12161. moduleNamespace = 'module-' + namespace,
  12162. $module = $(this),
  12163. $context = $(settings.context),
  12164. $scrollContext = $(settings.scrollContext),
  12165. $boundary = $(settings.boundary),
  12166. $target = (settings.target)
  12167. ? $(settings.target)
  12168. : $module,
  12169. $popup,
  12170. $offsetParent,
  12171. searchDepth = 0,
  12172. triedPositions = false,
  12173. openedWithTouch = false,
  12174. element = this,
  12175. instance = $module.data(moduleNamespace),
  12176. documentObserver,
  12177. elementNamespace,
  12178. id,
  12179. module
  12180. ;
  12181. module = {
  12182. // binds events
  12183. initialize: function() {
  12184. module.debug('Initializing', $module);
  12185. module.createID();
  12186. module.bind.events();
  12187. if(!module.exists() && settings.preserve) {
  12188. module.create();
  12189. }
  12190. if(settings.observeChanges) {
  12191. module.observeChanges();
  12192. }
  12193. module.instantiate();
  12194. },
  12195. instantiate: function() {
  12196. module.verbose('Storing instance', module);
  12197. instance = module;
  12198. $module
  12199. .data(moduleNamespace, instance)
  12200. ;
  12201. },
  12202. observeChanges: function() {
  12203. if('MutationObserver' in window) {
  12204. documentObserver = new MutationObserver(module.event.documentChanged);
  12205. documentObserver.observe(document, {
  12206. childList : true,
  12207. subtree : true
  12208. });
  12209. module.debug('Setting up mutation observer', documentObserver);
  12210. }
  12211. },
  12212. refresh: function() {
  12213. if(settings.popup) {
  12214. $popup = $(settings.popup).eq(0);
  12215. }
  12216. else {
  12217. if(settings.inline) {
  12218. $popup = $target.nextAll(selector.popup).eq(0);
  12219. settings.popup = $popup;
  12220. }
  12221. }
  12222. if(settings.popup) {
  12223. $popup.addClass(className.loading);
  12224. $offsetParent = module.get.offsetParent();
  12225. $popup.removeClass(className.loading);
  12226. if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
  12227. module.debug('Moving popup to the same offset parent as target');
  12228. $popup
  12229. .detach()
  12230. .appendTo($offsetParent)
  12231. ;
  12232. }
  12233. }
  12234. else {
  12235. $offsetParent = (settings.inline)
  12236. ? module.get.offsetParent($target)
  12237. : module.has.popup()
  12238. ? module.get.offsetParent($popup)
  12239. : $body
  12240. ;
  12241. }
  12242. if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
  12243. module.debug('Setting page as offset parent');
  12244. $offsetParent = $body;
  12245. }
  12246. if( module.get.variation() ) {
  12247. module.set.variation();
  12248. }
  12249. },
  12250. reposition: function() {
  12251. module.refresh();
  12252. module.set.position();
  12253. },
  12254. destroy: function() {
  12255. module.debug('Destroying previous module');
  12256. if(documentObserver) {
  12257. documentObserver.disconnect();
  12258. }
  12259. // remove element only if was created dynamically
  12260. if($popup && !settings.preserve) {
  12261. module.removePopup();
  12262. }
  12263. // clear all timeouts
  12264. clearTimeout(module.hideTimer);
  12265. clearTimeout(module.showTimer);
  12266. // remove events
  12267. module.unbind.close();
  12268. module.unbind.events();
  12269. $module
  12270. .removeData(moduleNamespace)
  12271. ;
  12272. },
  12273. event: {
  12274. start: function(event) {
  12275. var
  12276. delay = ($.isPlainObject(settings.delay))
  12277. ? settings.delay.show
  12278. : settings.delay
  12279. ;
  12280. clearTimeout(module.hideTimer);
  12281. if(!openedWithTouch || (openedWithTouch && settings.addTouchEvents) ) {
  12282. module.showTimer = setTimeout(module.show, delay);
  12283. }
  12284. },
  12285. end: function() {
  12286. var
  12287. delay = ($.isPlainObject(settings.delay))
  12288. ? settings.delay.hide
  12289. : settings.delay
  12290. ;
  12291. clearTimeout(module.showTimer);
  12292. module.hideTimer = setTimeout(module.hide, delay);
  12293. },
  12294. touchstart: function(event) {
  12295. openedWithTouch = true;
  12296. if(settings.addTouchEvents) {
  12297. module.show();
  12298. }
  12299. },
  12300. resize: function() {
  12301. if( module.is.visible() ) {
  12302. module.set.position();
  12303. }
  12304. },
  12305. documentChanged: function(mutations) {
  12306. [].forEach.call(mutations, function(mutation) {
  12307. if(mutation.removedNodes) {
  12308. [].forEach.call(mutation.removedNodes, function(node) {
  12309. if(node == element || $(node).find(element).length > 0) {
  12310. module.debug('Element removed from DOM, tearing down events');
  12311. module.destroy();
  12312. }
  12313. });
  12314. }
  12315. });
  12316. },
  12317. hideGracefully: function(event) {
  12318. var
  12319. $target = $(event.target),
  12320. isInDOM = $.contains(document.documentElement, event.target),
  12321. inPopup = ($target.closest(selector.popup).length > 0)
  12322. ;
  12323. // don't close on clicks inside popup
  12324. if(event && !inPopup && isInDOM) {
  12325. module.debug('Click occurred outside popup hiding popup');
  12326. module.hide();
  12327. }
  12328. else {
  12329. module.debug('Click was inside popup, keeping popup open');
  12330. }
  12331. }
  12332. },
  12333. // generates popup html from metadata
  12334. create: function() {
  12335. var
  12336. html = module.get.html(),
  12337. title = module.get.title(),
  12338. content = module.get.content()
  12339. ;
  12340. if(html || content || title) {
  12341. module.debug('Creating pop-up html');
  12342. if(!html) {
  12343. html = settings.templates.popup({
  12344. title : title,
  12345. content : content
  12346. });
  12347. }
  12348. $popup = $('<div/>')
  12349. .addClass(className.popup)
  12350. .data(metadata.activator, $module)
  12351. .html(html)
  12352. ;
  12353. if(settings.inline) {
  12354. module.verbose('Inserting popup element inline', $popup);
  12355. $popup
  12356. .insertAfter($module)
  12357. ;
  12358. }
  12359. else {
  12360. module.verbose('Appending popup element to body', $popup);
  12361. $popup
  12362. .appendTo( $context )
  12363. ;
  12364. }
  12365. module.refresh();
  12366. module.set.variation();
  12367. if(settings.hoverable) {
  12368. module.bind.popup();
  12369. }
  12370. settings.onCreate.call($popup, element);
  12371. }
  12372. else if(settings.popup) {
  12373. $(settings.popup).data(metadata.activator, $module);
  12374. module.verbose('Used popup specified in settings');
  12375. module.refresh();
  12376. if(settings.hoverable) {
  12377. module.bind.popup();
  12378. }
  12379. }
  12380. else if($target.next(selector.popup).length !== 0) {
  12381. module.verbose('Pre-existing popup found');
  12382. settings.inline = true;
  12383. settings.popup = $target.next(selector.popup).data(metadata.activator, $module);
  12384. module.refresh();
  12385. if(settings.hoverable) {
  12386. module.bind.popup();
  12387. }
  12388. }
  12389. else {
  12390. module.debug('No content specified skipping display', element);
  12391. }
  12392. },
  12393. createID: function() {
  12394. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  12395. elementNamespace = '.' + id;
  12396. module.verbose('Creating unique id for element', id);
  12397. },
  12398. // determines popup state
  12399. toggle: function() {
  12400. module.debug('Toggling pop-up');
  12401. if( module.is.hidden() ) {
  12402. module.debug('Popup is hidden, showing pop-up');
  12403. module.unbind.close();
  12404. module.show();
  12405. }
  12406. else {
  12407. module.debug('Popup is visible, hiding pop-up');
  12408. module.hide();
  12409. }
  12410. },
  12411. show: function(callback) {
  12412. callback = callback || function(){};
  12413. module.debug('Showing pop-up', settings.transition);
  12414. if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
  12415. if( !module.exists() ) {
  12416. module.create();
  12417. }
  12418. if(settings.onShow.call($popup, element) === false) {
  12419. module.debug('onShow callback returned false, cancelling popup animation');
  12420. return;
  12421. }
  12422. else if(!settings.preserve && !settings.popup) {
  12423. module.refresh();
  12424. }
  12425. if( $popup && module.set.position() ) {
  12426. module.save.conditions();
  12427. if(settings.exclusive) {
  12428. module.hideAll();
  12429. }
  12430. module.animate.show(callback);
  12431. }
  12432. }
  12433. },
  12434. hide: function(callback) {
  12435. callback = callback || function(){};
  12436. if( module.is.visible() || module.is.animating() ) {
  12437. if(settings.onHide.call($popup, element) === false) {
  12438. module.debug('onHide callback returned false, cancelling popup animation');
  12439. return;
  12440. }
  12441. module.remove.visible();
  12442. module.unbind.close();
  12443. module.restore.conditions();
  12444. module.animate.hide(callback);
  12445. }
  12446. },
  12447. hideAll: function() {
  12448. $(selector.popup)
  12449. .filter('.' + className.popupVisible)
  12450. .each(function() {
  12451. $(this)
  12452. .data(metadata.activator)
  12453. .popup('hide')
  12454. ;
  12455. })
  12456. ;
  12457. },
  12458. exists: function() {
  12459. if(!$popup) {
  12460. return false;
  12461. }
  12462. if(settings.inline || settings.popup) {
  12463. return ( module.has.popup() );
  12464. }
  12465. else {
  12466. return ( $popup.closest($context).length >= 1 )
  12467. ? true
  12468. : false
  12469. ;
  12470. }
  12471. },
  12472. removePopup: function() {
  12473. if( module.has.popup() && !settings.popup) {
  12474. module.debug('Removing popup', $popup);
  12475. $popup.remove();
  12476. $popup = undefined;
  12477. settings.onRemove.call($popup, element);
  12478. }
  12479. },
  12480. save: {
  12481. conditions: function() {
  12482. module.cache = {
  12483. title: $module.attr('title')
  12484. };
  12485. if (module.cache.title) {
  12486. $module.removeAttr('title');
  12487. }
  12488. module.verbose('Saving original attributes', module.cache.title);
  12489. }
  12490. },
  12491. restore: {
  12492. conditions: function() {
  12493. if(module.cache && module.cache.title) {
  12494. $module.attr('title', module.cache.title);
  12495. module.verbose('Restoring original attributes', module.cache.title);
  12496. }
  12497. return true;
  12498. }
  12499. },
  12500. supports: {
  12501. svg: function() {
  12502. return (typeof SVGGraphicsElement !== 'undefined');
  12503. }
  12504. },
  12505. animate: {
  12506. show: function(callback) {
  12507. callback = $.isFunction(callback) ? callback : function(){};
  12508. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  12509. module.set.visible();
  12510. $popup
  12511. .transition({
  12512. animation : settings.transition + ' in',
  12513. queue : false,
  12514. debug : settings.debug,
  12515. verbose : settings.verbose,
  12516. duration : settings.duration,
  12517. onComplete : function() {
  12518. module.bind.close();
  12519. callback.call($popup, element);
  12520. settings.onVisible.call($popup, element);
  12521. }
  12522. })
  12523. ;
  12524. }
  12525. else {
  12526. module.error(error.noTransition);
  12527. }
  12528. },
  12529. hide: function(callback) {
  12530. callback = $.isFunction(callback) ? callback : function(){};
  12531. module.debug('Hiding pop-up');
  12532. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  12533. $popup
  12534. .transition({
  12535. animation : settings.transition + ' out',
  12536. queue : false,
  12537. duration : settings.duration,
  12538. debug : settings.debug,
  12539. verbose : settings.verbose,
  12540. onComplete : function() {
  12541. module.reset();
  12542. callback.call($popup, element);
  12543. settings.onHidden.call($popup, element);
  12544. }
  12545. })
  12546. ;
  12547. }
  12548. else {
  12549. module.error(error.noTransition);
  12550. }
  12551. }
  12552. },
  12553. change: {
  12554. content: function(html) {
  12555. $popup.html(html);
  12556. }
  12557. },
  12558. get: {
  12559. html: function() {
  12560. $module.removeData(metadata.html);
  12561. return $module.data(metadata.html) || settings.html;
  12562. },
  12563. title: function() {
  12564. $module.removeData(metadata.title);
  12565. return $module.data(metadata.title) || settings.title;
  12566. },
  12567. content: function() {
  12568. $module.removeData(metadata.content);
  12569. return $module.data(metadata.content) || settings.content || $module.attr('title');
  12570. },
  12571. variation: function() {
  12572. $module.removeData(metadata.variation);
  12573. return $module.data(metadata.variation) || settings.variation;
  12574. },
  12575. popup: function() {
  12576. return $popup;
  12577. },
  12578. popupOffset: function() {
  12579. return $popup.offset();
  12580. },
  12581. calculations: function() {
  12582. var
  12583. $popupOffsetParent = module.get.offsetParent($popup),
  12584. targetElement = $target[0],
  12585. isWindow = ($boundary[0] == window),
  12586. targetPosition = (settings.inline || (settings.popup && settings.movePopup))
  12587. ? $target.position()
  12588. : $target.offset(),
  12589. screenPosition = (isWindow)
  12590. ? { top: 0, left: 0 }
  12591. : $boundary.offset(),
  12592. calculations = {},
  12593. scroll = (isWindow)
  12594. ? { top: $window.scrollTop(), left: $window.scrollLeft() }
  12595. : { top: 0, left: 0},
  12596. screen
  12597. ;
  12598. calculations = {
  12599. // element which is launching popup
  12600. target : {
  12601. element : $target[0],
  12602. width : $target.outerWidth(),
  12603. height : $target.outerHeight(),
  12604. top : targetPosition.top,
  12605. left : targetPosition.left,
  12606. margin : {}
  12607. },
  12608. // popup itself
  12609. popup : {
  12610. width : $popup.outerWidth(),
  12611. height : $popup.outerHeight()
  12612. },
  12613. // offset container (or 3d context)
  12614. parent : {
  12615. width : $offsetParent.outerWidth(),
  12616. height : $offsetParent.outerHeight()
  12617. },
  12618. // screen boundaries
  12619. screen : {
  12620. top : screenPosition.top,
  12621. left : screenPosition.left,
  12622. scroll: {
  12623. top : scroll.top,
  12624. left : scroll.left
  12625. },
  12626. width : $boundary.width(),
  12627. height : $boundary.height()
  12628. }
  12629. };
  12630. // if popup offset context is not same as target, then adjust calculations
  12631. if($popupOffsetParent.get(0) !== $offsetParent.get(0)) {
  12632. var
  12633. popupOffset = $popupOffsetParent.offset()
  12634. ;
  12635. calculations.target.top -= popupOffset.top;
  12636. calculations.target.left -= popupOffset.left;
  12637. calculations.parent.width = $popupOffsetParent.outerWidth();
  12638. calculations.parent.height = $popupOffsetParent.outerHeight();
  12639. }
  12640. // add in container calcs if fluid
  12641. if( settings.setFluidWidth && module.is.fluid() ) {
  12642. calculations.container = {
  12643. width: $popup.parent().outerWidth()
  12644. };
  12645. calculations.popup.width = calculations.container.width;
  12646. }
  12647. // add in margins if inline
  12648. calculations.target.margin.top = (settings.inline)
  12649. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
  12650. : 0
  12651. ;
  12652. calculations.target.margin.left = (settings.inline)
  12653. ? module.is.rtl()
  12654. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
  12655. : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
  12656. : 0
  12657. ;
  12658. // calculate screen boundaries
  12659. screen = calculations.screen;
  12660. calculations.boundary = {
  12661. top : screen.top + screen.scroll.top,
  12662. bottom : screen.top + screen.scroll.top + screen.height,
  12663. left : screen.left + screen.scroll.left,
  12664. right : screen.left + screen.scroll.left + screen.width
  12665. };
  12666. return calculations;
  12667. },
  12668. id: function() {
  12669. return id;
  12670. },
  12671. startEvent: function() {
  12672. if(settings.on == 'hover') {
  12673. return 'mouseenter';
  12674. }
  12675. else if(settings.on == 'focus') {
  12676. return 'focus';
  12677. }
  12678. return false;
  12679. },
  12680. scrollEvent: function() {
  12681. return 'scroll';
  12682. },
  12683. endEvent: function() {
  12684. if(settings.on == 'hover') {
  12685. return 'mouseleave';
  12686. }
  12687. else if(settings.on == 'focus') {
  12688. return 'blur';
  12689. }
  12690. return false;
  12691. },
  12692. distanceFromBoundary: function(offset, calculations) {
  12693. var
  12694. distanceFromBoundary = {},
  12695. popup,
  12696. boundary
  12697. ;
  12698. calculations = calculations || module.get.calculations();
  12699. // shorthand
  12700. popup = calculations.popup;
  12701. boundary = calculations.boundary;
  12702. if(offset) {
  12703. distanceFromBoundary = {
  12704. top : (offset.top - boundary.top),
  12705. left : (offset.left - boundary.left),
  12706. right : (boundary.right - (offset.left + popup.width) ),
  12707. bottom : (boundary.bottom - (offset.top + popup.height) )
  12708. };
  12709. module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
  12710. }
  12711. return distanceFromBoundary;
  12712. },
  12713. offsetParent: function($element) {
  12714. var
  12715. element = ($element !== undefined)
  12716. ? $element[0]
  12717. : $target[0],
  12718. parentNode = element.parentNode,
  12719. $node = $(parentNode)
  12720. ;
  12721. if(parentNode) {
  12722. var
  12723. is2D = ($node.css('transform') === 'none'),
  12724. isStatic = ($node.css('position') === 'static'),
  12725. isBody = $node.is('body')
  12726. ;
  12727. while(parentNode && !isBody && isStatic && is2D) {
  12728. parentNode = parentNode.parentNode;
  12729. $node = $(parentNode);
  12730. is2D = ($node.css('transform') === 'none');
  12731. isStatic = ($node.css('position') === 'static');
  12732. isBody = $node.is('body');
  12733. }
  12734. }
  12735. return ($node && $node.length > 0)
  12736. ? $node
  12737. : $()
  12738. ;
  12739. },
  12740. positions: function() {
  12741. return {
  12742. 'top left' : false,
  12743. 'top center' : false,
  12744. 'top right' : false,
  12745. 'bottom left' : false,
  12746. 'bottom center' : false,
  12747. 'bottom right' : false,
  12748. 'left center' : false,
  12749. 'right center' : false
  12750. };
  12751. },
  12752. nextPosition: function(position) {
  12753. var
  12754. positions = position.split(' '),
  12755. verticalPosition = positions[0],
  12756. horizontalPosition = positions[1],
  12757. opposite = {
  12758. top : 'bottom',
  12759. bottom : 'top',
  12760. left : 'right',
  12761. right : 'left'
  12762. },
  12763. adjacent = {
  12764. left : 'center',
  12765. center : 'right',
  12766. right : 'left'
  12767. },
  12768. backup = {
  12769. 'top left' : 'top center',
  12770. 'top center' : 'top right',
  12771. 'top right' : 'right center',
  12772. 'right center' : 'bottom right',
  12773. 'bottom right' : 'bottom center',
  12774. 'bottom center' : 'bottom left',
  12775. 'bottom left' : 'left center',
  12776. 'left center' : 'top left'
  12777. },
  12778. adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
  12779. oppositeTried = false,
  12780. adjacentTried = false,
  12781. nextPosition = false
  12782. ;
  12783. if(!triedPositions) {
  12784. module.verbose('All available positions available');
  12785. triedPositions = module.get.positions();
  12786. }
  12787. module.debug('Recording last position tried', position);
  12788. triedPositions[position] = true;
  12789. if(settings.prefer === 'opposite') {
  12790. nextPosition = [opposite[verticalPosition], horizontalPosition];
  12791. nextPosition = nextPosition.join(' ');
  12792. oppositeTried = (triedPositions[nextPosition] === true);
  12793. module.debug('Trying opposite strategy', nextPosition);
  12794. }
  12795. if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
  12796. nextPosition = [verticalPosition, adjacent[horizontalPosition]];
  12797. nextPosition = nextPosition.join(' ');
  12798. adjacentTried = (triedPositions[nextPosition] === true);
  12799. module.debug('Trying adjacent strategy', nextPosition);
  12800. }
  12801. if(adjacentTried || oppositeTried) {
  12802. module.debug('Using backup position', nextPosition);
  12803. nextPosition = backup[position];
  12804. }
  12805. return nextPosition;
  12806. }
  12807. },
  12808. set: {
  12809. position: function(position, calculations) {
  12810. // exit conditions
  12811. if($target.length === 0 || $popup.length === 0) {
  12812. module.error(error.notFound);
  12813. return;
  12814. }
  12815. var
  12816. offset,
  12817. distanceAway,
  12818. target,
  12819. popup,
  12820. parent,
  12821. positioning,
  12822. popupOffset,
  12823. distanceFromBoundary
  12824. ;
  12825. calculations = calculations || module.get.calculations();
  12826. position = position || $module.data(metadata.position) || settings.position;
  12827. offset = $module.data(metadata.offset) || settings.offset;
  12828. distanceAway = settings.distanceAway;
  12829. // shorthand
  12830. target = calculations.target;
  12831. popup = calculations.popup;
  12832. parent = calculations.parent;
  12833. if(module.should.centerArrow(calculations)) {
  12834. module.verbose('Adjusting offset to center arrow on small target element');
  12835. if(position == 'top left' || position == 'bottom left') {
  12836. offset += (target.width / 2);
  12837. offset -= settings.arrowPixelsFromEdge;
  12838. }
  12839. if(position == 'top right' || position == 'bottom right') {
  12840. offset -= (target.width / 2);
  12841. offset += settings.arrowPixelsFromEdge;
  12842. }
  12843. }
  12844. if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) {
  12845. module.debug('Popup target is hidden, no action taken');
  12846. return false;
  12847. }
  12848. if(settings.inline) {
  12849. module.debug('Adding margin to calculation', target.margin);
  12850. if(position == 'left center' || position == 'right center') {
  12851. offset += target.margin.top;
  12852. distanceAway += -target.margin.left;
  12853. }
  12854. else if (position == 'top left' || position == 'top center' || position == 'top right') {
  12855. offset += target.margin.left;
  12856. distanceAway -= target.margin.top;
  12857. }
  12858. else {
  12859. offset += target.margin.left;
  12860. distanceAway += target.margin.top;
  12861. }
  12862. }
  12863. module.debug('Determining popup position from calculations', position, calculations);
  12864. if (module.is.rtl()) {
  12865. position = position.replace(/left|right/g, function (match) {
  12866. return (match == 'left')
  12867. ? 'right'
  12868. : 'left'
  12869. ;
  12870. });
  12871. module.debug('RTL: Popup position updated', position);
  12872. }
  12873. // if last attempt use specified last resort position
  12874. if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
  12875. position = settings.lastResort;
  12876. }
  12877. switch (position) {
  12878. case 'top left':
  12879. positioning = {
  12880. top : 'auto',
  12881. bottom : parent.height - target.top + distanceAway,
  12882. left : target.left + offset,
  12883. right : 'auto'
  12884. };
  12885. break;
  12886. case 'top center':
  12887. positioning = {
  12888. bottom : parent.height - target.top + distanceAway,
  12889. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  12890. top : 'auto',
  12891. right : 'auto'
  12892. };
  12893. break;
  12894. case 'top right':
  12895. positioning = {
  12896. bottom : parent.height - target.top + distanceAway,
  12897. right : parent.width - target.left - target.width - offset,
  12898. top : 'auto',
  12899. left : 'auto'
  12900. };
  12901. break;
  12902. case 'left center':
  12903. positioning = {
  12904. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  12905. right : parent.width - target.left + distanceAway,
  12906. left : 'auto',
  12907. bottom : 'auto'
  12908. };
  12909. break;
  12910. case 'right center':
  12911. positioning = {
  12912. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  12913. left : target.left + target.width + distanceAway,
  12914. bottom : 'auto',
  12915. right : 'auto'
  12916. };
  12917. break;
  12918. case 'bottom left':
  12919. positioning = {
  12920. top : target.top + target.height + distanceAway,
  12921. left : target.left + offset,
  12922. bottom : 'auto',
  12923. right : 'auto'
  12924. };
  12925. break;
  12926. case 'bottom center':
  12927. positioning = {
  12928. top : target.top + target.height + distanceAway,
  12929. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  12930. bottom : 'auto',
  12931. right : 'auto'
  12932. };
  12933. break;
  12934. case 'bottom right':
  12935. positioning = {
  12936. top : target.top + target.height + distanceAway,
  12937. right : parent.width - target.left - target.width - offset,
  12938. left : 'auto',
  12939. bottom : 'auto'
  12940. };
  12941. break;
  12942. }
  12943. if(positioning === undefined) {
  12944. module.error(error.invalidPosition, position);
  12945. }
  12946. module.debug('Calculated popup positioning values', positioning);
  12947. // tentatively place on stage
  12948. $popup
  12949. .css(positioning)
  12950. .removeClass(className.position)
  12951. .addClass(position)
  12952. .addClass(className.loading)
  12953. ;
  12954. popupOffset = module.get.popupOffset();
  12955. // see if any boundaries are surpassed with this tentative position
  12956. distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
  12957. if(!settings.forcePosition && module.is.offstage(distanceFromBoundary, position) ) {
  12958. module.debug('Position is outside viewport', position);
  12959. if(searchDepth < settings.maxSearchDepth) {
  12960. searchDepth++;
  12961. position = module.get.nextPosition(position);
  12962. module.debug('Trying new position', position);
  12963. return ($popup)
  12964. ? module.set.position(position, calculations)
  12965. : false
  12966. ;
  12967. }
  12968. else {
  12969. if(settings.lastResort) {
  12970. module.debug('No position found, showing with last position');
  12971. }
  12972. else {
  12973. module.debug('Popup could not find a position to display', $popup);
  12974. module.error(error.cannotPlace, element);
  12975. module.remove.attempts();
  12976. module.remove.loading();
  12977. module.reset();
  12978. settings.onUnplaceable.call($popup, element);
  12979. return false;
  12980. }
  12981. }
  12982. }
  12983. module.debug('Position is on stage', position);
  12984. module.remove.attempts();
  12985. module.remove.loading();
  12986. if( settings.setFluidWidth && module.is.fluid() ) {
  12987. module.set.fluidWidth(calculations);
  12988. }
  12989. return true;
  12990. },
  12991. fluidWidth: function(calculations) {
  12992. calculations = calculations || module.get.calculations();
  12993. module.debug('Automatically setting element width to parent width', calculations.parent.width);
  12994. $popup.css('width', calculations.container.width);
  12995. },
  12996. variation: function(variation) {
  12997. variation = variation || module.get.variation();
  12998. if(variation && module.has.popup() ) {
  12999. module.verbose('Adding variation to popup', variation);
  13000. $popup.addClass(variation);
  13001. }
  13002. },
  13003. visible: function() {
  13004. $module.addClass(className.visible);
  13005. }
  13006. },
  13007. remove: {
  13008. loading: function() {
  13009. $popup.removeClass(className.loading);
  13010. },
  13011. variation: function(variation) {
  13012. variation = variation || module.get.variation();
  13013. if(variation) {
  13014. module.verbose('Removing variation', variation);
  13015. $popup.removeClass(variation);
  13016. }
  13017. },
  13018. visible: function() {
  13019. $module.removeClass(className.visible);
  13020. },
  13021. attempts: function() {
  13022. module.verbose('Resetting all searched positions');
  13023. searchDepth = 0;
  13024. triedPositions = false;
  13025. }
  13026. },
  13027. bind: {
  13028. events: function() {
  13029. module.debug('Binding popup events to module');
  13030. if(settings.on == 'click') {
  13031. $module
  13032. .on(clickEvent + eventNamespace, module.toggle)
  13033. ;
  13034. }
  13035. if(settings.on == 'hover') {
  13036. $module
  13037. .on('touchstart' + eventNamespace, module.event.touchstart)
  13038. ;
  13039. }
  13040. if( module.get.startEvent() ) {
  13041. $module
  13042. .on(module.get.startEvent() + eventNamespace, module.event.start)
  13043. .on(module.get.endEvent() + eventNamespace, module.event.end)
  13044. ;
  13045. }
  13046. if(settings.target) {
  13047. module.debug('Target set to element', $target);
  13048. }
  13049. $window.on('resize' + elementNamespace, module.event.resize);
  13050. },
  13051. popup: function() {
  13052. module.verbose('Allowing hover events on popup to prevent closing');
  13053. if( $popup && module.has.popup() ) {
  13054. $popup
  13055. .on('mouseenter' + eventNamespace, module.event.start)
  13056. .on('mouseleave' + eventNamespace, module.event.end)
  13057. ;
  13058. }
  13059. },
  13060. close: function() {
  13061. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  13062. module.bind.closeOnScroll();
  13063. }
  13064. if(module.is.closable()) {
  13065. module.bind.clickaway();
  13066. }
  13067. else if(settings.on == 'hover' && openedWithTouch) {
  13068. module.bind.touchClose();
  13069. }
  13070. },
  13071. closeOnScroll: function() {
  13072. module.verbose('Binding scroll close event to document');
  13073. $scrollContext
  13074. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  13075. ;
  13076. },
  13077. touchClose: function() {
  13078. module.verbose('Binding popup touchclose event to document');
  13079. $document
  13080. .on('touchstart' + elementNamespace, function(event) {
  13081. module.verbose('Touched away from popup');
  13082. module.event.hideGracefully.call(element, event);
  13083. })
  13084. ;
  13085. },
  13086. clickaway: function() {
  13087. module.verbose('Binding popup close event to document');
  13088. $document
  13089. .on(clickEvent + elementNamespace, function(event) {
  13090. module.verbose('Clicked away from popup');
  13091. module.event.hideGracefully.call(element, event);
  13092. })
  13093. ;
  13094. }
  13095. },
  13096. unbind: {
  13097. events: function() {
  13098. $window
  13099. .off(elementNamespace)
  13100. ;
  13101. $module
  13102. .off(eventNamespace)
  13103. ;
  13104. },
  13105. close: function() {
  13106. $document
  13107. .off(elementNamespace)
  13108. ;
  13109. $scrollContext
  13110. .off(elementNamespace)
  13111. ;
  13112. },
  13113. },
  13114. has: {
  13115. popup: function() {
  13116. return ($popup && $popup.length > 0);
  13117. }
  13118. },
  13119. should: {
  13120. centerArrow: function(calculations) {
  13121. return !module.is.basic() && calculations.target.width <= (settings.arrowPixelsFromEdge * 2);
  13122. },
  13123. },
  13124. is: {
  13125. closable: function() {
  13126. if(settings.closable == 'auto') {
  13127. if(settings.on == 'hover') {
  13128. return false;
  13129. }
  13130. return true;
  13131. }
  13132. return settings.closable;
  13133. },
  13134. offstage: function(distanceFromBoundary, position) {
  13135. var
  13136. offstage = []
  13137. ;
  13138. // return boundaries that have been surpassed
  13139. $.each(distanceFromBoundary, function(direction, distance) {
  13140. if(distance < -settings.jitter) {
  13141. module.debug('Position exceeds allowable distance from edge', direction, distance, position);
  13142. offstage.push(direction);
  13143. }
  13144. });
  13145. if(offstage.length > 0) {
  13146. return true;
  13147. }
  13148. else {
  13149. return false;
  13150. }
  13151. },
  13152. svg: function(element) {
  13153. return module.supports.svg() && (element instanceof SVGGraphicsElement);
  13154. },
  13155. basic: function() {
  13156. return $module.hasClass(className.basic);
  13157. },
  13158. active: function() {
  13159. return $module.hasClass(className.active);
  13160. },
  13161. animating: function() {
  13162. return ($popup !== undefined && $popup.hasClass(className.animating) );
  13163. },
  13164. fluid: function() {
  13165. return ($popup !== undefined && $popup.hasClass(className.fluid));
  13166. },
  13167. visible: function() {
  13168. return ($popup !== undefined && $popup.hasClass(className.popupVisible));
  13169. },
  13170. dropdown: function() {
  13171. return $module.hasClass(className.dropdown);
  13172. },
  13173. hidden: function() {
  13174. return !module.is.visible();
  13175. },
  13176. rtl: function () {
  13177. return $module.attr('dir') === 'rtl' || $module.css('direction') === 'rtl';
  13178. }
  13179. },
  13180. reset: function() {
  13181. module.remove.visible();
  13182. if(settings.preserve) {
  13183. if($.fn.transition !== undefined) {
  13184. $popup
  13185. .transition('remove transition')
  13186. ;
  13187. }
  13188. }
  13189. else {
  13190. module.removePopup();
  13191. }
  13192. },
  13193. setting: function(name, value) {
  13194. if( $.isPlainObject(name) ) {
  13195. $.extend(true, settings, name);
  13196. }
  13197. else if(value !== undefined) {
  13198. settings[name] = value;
  13199. }
  13200. else {
  13201. return settings[name];
  13202. }
  13203. },
  13204. internal: function(name, value) {
  13205. if( $.isPlainObject(name) ) {
  13206. $.extend(true, module, name);
  13207. }
  13208. else if(value !== undefined) {
  13209. module[name] = value;
  13210. }
  13211. else {
  13212. return module[name];
  13213. }
  13214. },
  13215. debug: function() {
  13216. if(!settings.silent && settings.debug) {
  13217. if(settings.performance) {
  13218. module.performance.log(arguments);
  13219. }
  13220. else {
  13221. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13222. module.debug.apply(console, arguments);
  13223. }
  13224. }
  13225. },
  13226. verbose: function() {
  13227. if(!settings.silent && settings.verbose && settings.debug) {
  13228. if(settings.performance) {
  13229. module.performance.log(arguments);
  13230. }
  13231. else {
  13232. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13233. module.verbose.apply(console, arguments);
  13234. }
  13235. }
  13236. },
  13237. error: function() {
  13238. if(!settings.silent) {
  13239. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  13240. module.error.apply(console, arguments);
  13241. }
  13242. },
  13243. performance: {
  13244. log: function(message) {
  13245. var
  13246. currentTime,
  13247. executionTime,
  13248. previousTime
  13249. ;
  13250. if(settings.performance) {
  13251. currentTime = new Date().getTime();
  13252. previousTime = time || currentTime;
  13253. executionTime = currentTime - previousTime;
  13254. time = currentTime;
  13255. performance.push({
  13256. 'Name' : message[0],
  13257. 'Arguments' : [].slice.call(message, 1) || '',
  13258. 'Element' : element,
  13259. 'Execution Time' : executionTime
  13260. });
  13261. }
  13262. clearTimeout(module.performance.timer);
  13263. module.performance.timer = setTimeout(module.performance.display, 500);
  13264. },
  13265. display: function() {
  13266. var
  13267. title = settings.name + ':',
  13268. totalTime = 0
  13269. ;
  13270. time = false;
  13271. clearTimeout(module.performance.timer);
  13272. $.each(performance, function(index, data) {
  13273. totalTime += data['Execution Time'];
  13274. });
  13275. title += ' ' + totalTime + 'ms';
  13276. if(moduleSelector) {
  13277. title += ' \'' + moduleSelector + '\'';
  13278. }
  13279. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  13280. console.groupCollapsed(title);
  13281. if(console.table) {
  13282. console.table(performance);
  13283. }
  13284. else {
  13285. $.each(performance, function(index, data) {
  13286. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  13287. });
  13288. }
  13289. console.groupEnd();
  13290. }
  13291. performance = [];
  13292. }
  13293. },
  13294. invoke: function(query, passedArguments, context) {
  13295. var
  13296. object = instance,
  13297. maxDepth,
  13298. found,
  13299. response
  13300. ;
  13301. passedArguments = passedArguments || queryArguments;
  13302. context = element || context;
  13303. if(typeof query == 'string' && object !== undefined) {
  13304. query = query.split(/[\. ]/);
  13305. maxDepth = query.length - 1;
  13306. $.each(query, function(depth, value) {
  13307. var camelCaseValue = (depth != maxDepth)
  13308. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  13309. : query
  13310. ;
  13311. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  13312. object = object[camelCaseValue];
  13313. }
  13314. else if( object[camelCaseValue] !== undefined ) {
  13315. found = object[camelCaseValue];
  13316. return false;
  13317. }
  13318. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  13319. object = object[value];
  13320. }
  13321. else if( object[value] !== undefined ) {
  13322. found = object[value];
  13323. return false;
  13324. }
  13325. else {
  13326. return false;
  13327. }
  13328. });
  13329. }
  13330. if ( $.isFunction( found ) ) {
  13331. response = found.apply(context, passedArguments);
  13332. }
  13333. else if(found !== undefined) {
  13334. response = found;
  13335. }
  13336. if(Array.isArray(returnedValue)) {
  13337. returnedValue.push(response);
  13338. }
  13339. else if(returnedValue !== undefined) {
  13340. returnedValue = [returnedValue, response];
  13341. }
  13342. else if(response !== undefined) {
  13343. returnedValue = response;
  13344. }
  13345. return found;
  13346. }
  13347. };
  13348. if(methodInvoked) {
  13349. if(instance === undefined) {
  13350. module.initialize();
  13351. }
  13352. module.invoke(query);
  13353. }
  13354. else {
  13355. if(instance !== undefined) {
  13356. instance.invoke('destroy');
  13357. }
  13358. module.initialize();
  13359. }
  13360. })
  13361. ;
  13362. return (returnedValue !== undefined)
  13363. ? returnedValue
  13364. : this
  13365. ;
  13366. };
  13367. $.fn.popup.settings = {
  13368. name : 'Popup',
  13369. // module settings
  13370. silent : false,
  13371. debug : false,
  13372. verbose : false,
  13373. performance : true,
  13374. namespace : 'popup',
  13375. // whether it should use dom mutation observers
  13376. observeChanges : true,
  13377. // callback only when element added to dom
  13378. onCreate : function(){},
  13379. // callback before element removed from dom
  13380. onRemove : function(){},
  13381. // callback before show animation
  13382. onShow : function(){},
  13383. // callback after show animation
  13384. onVisible : function(){},
  13385. // callback before hide animation
  13386. onHide : function(){},
  13387. // callback when popup cannot be positioned in visible screen
  13388. onUnplaceable : function(){},
  13389. // callback after hide animation
  13390. onHidden : function(){},
  13391. // when to show popup
  13392. on : 'hover',
  13393. // element to use to determine if popup is out of boundary
  13394. boundary : window,
  13395. // whether to add touchstart events when using hover
  13396. addTouchEvents : true,
  13397. // default position relative to element
  13398. position : 'top left',
  13399. // if given position should be used regardless if popup fits
  13400. forcePosition : false,
  13401. // name of variation to use
  13402. variation : '',
  13403. // whether popup should be moved to context
  13404. movePopup : true,
  13405. // element which popup should be relative to
  13406. target : false,
  13407. // jq selector or element that should be used as popup
  13408. popup : false,
  13409. // popup should remain inline next to activator
  13410. inline : false,
  13411. // popup should be removed from page on hide
  13412. preserve : false,
  13413. // popup should not close when being hovered on
  13414. hoverable : false,
  13415. // explicitly set content
  13416. content : false,
  13417. // explicitly set html
  13418. html : false,
  13419. // explicitly set title
  13420. title : false,
  13421. // whether automatically close on clickaway when on click
  13422. closable : true,
  13423. // automatically hide on scroll
  13424. hideOnScroll : 'auto',
  13425. // hide other popups on show
  13426. exclusive : false,
  13427. // context to attach popups
  13428. context : 'body',
  13429. // context for binding scroll events
  13430. scrollContext : window,
  13431. // position to prefer when calculating new position
  13432. prefer : 'opposite',
  13433. // specify position to appear even if it doesn't fit
  13434. lastResort : false,
  13435. // number of pixels from edge of popup to pointing arrow center (used from centering)
  13436. arrowPixelsFromEdge: 20,
  13437. // delay used to prevent accidental refiring of animations due to user error
  13438. delay : {
  13439. show : 50,
  13440. hide : 70
  13441. },
  13442. // whether fluid variation should assign width explicitly
  13443. setFluidWidth : true,
  13444. // transition settings
  13445. duration : 200,
  13446. transition : 'scale',
  13447. // distance away from activating element in px
  13448. distanceAway : 0,
  13449. // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
  13450. jitter : 2,
  13451. // offset on aligning axis from calculated position
  13452. offset : 0,
  13453. // maximum times to look for a position before failing (9 positions total)
  13454. maxSearchDepth : 15,
  13455. error: {
  13456. invalidPosition : 'The position you specified is not a valid position',
  13457. cannotPlace : 'Popup does not fit within the boundaries of the viewport',
  13458. method : 'The method you called is not defined.',
  13459. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  13460. notFound : 'The target or popup you specified does not exist on the page'
  13461. },
  13462. metadata: {
  13463. activator : 'activator',
  13464. content : 'content',
  13465. html : 'html',
  13466. offset : 'offset',
  13467. position : 'position',
  13468. title : 'title',
  13469. variation : 'variation'
  13470. },
  13471. className : {
  13472. active : 'active',
  13473. basic : 'basic',
  13474. animating : 'animating',
  13475. dropdown : 'dropdown',
  13476. fluid : 'fluid',
  13477. loading : 'loading',
  13478. popup : 'ui popup',
  13479. position : 'top left center bottom right',
  13480. visible : 'visible',
  13481. popupVisible : 'visible'
  13482. },
  13483. selector : {
  13484. popup : '.ui.popup'
  13485. },
  13486. templates: {
  13487. escape: function(string) {
  13488. var
  13489. badChars = /[&<>"'`]/g,
  13490. shouldEscape = /[&<>"'`]/,
  13491. escape = {
  13492. "&": "&amp;",
  13493. "<": "&lt;",
  13494. ">": "&gt;",
  13495. '"': "&quot;",
  13496. "'": "&#x27;",
  13497. "`": "&#x60;"
  13498. },
  13499. escapedChar = function(chr) {
  13500. return escape[chr];
  13501. }
  13502. ;
  13503. if(shouldEscape.test(string)) {
  13504. return string.replace(badChars, escapedChar);
  13505. }
  13506. return string;
  13507. },
  13508. popup: function(text) {
  13509. var
  13510. html = '',
  13511. escape = $.fn.popup.settings.templates.escape
  13512. ;
  13513. if(typeof text !== undefined) {
  13514. if(typeof text.title !== undefined && text.title) {
  13515. text.title = escape(text.title);
  13516. html += '<div class="header">' + text.title + '</div>';
  13517. }
  13518. if(typeof text.content !== undefined && text.content) {
  13519. text.content = escape(text.content);
  13520. html += '<div class="content">' + text.content + '</div>';
  13521. }
  13522. }
  13523. return html;
  13524. }
  13525. }
  13526. };
  13527. })( jQuery, window, document );
  13528. /*!
  13529. * # Fomantic-UI - Progress
  13530. * http://github.com/fomantic/Fomantic-UI/
  13531. *
  13532. *
  13533. * Released under the MIT license
  13534. * http://opensource.org/licenses/MIT
  13535. *
  13536. */
  13537. ;(function ($, window, document, undefined) {
  13538. 'use strict';
  13539. $.isFunction = $.isFunction || function(obj) {
  13540. return typeof obj === "function" && typeof obj.nodeType !== "number";
  13541. };
  13542. window = (typeof window != 'undefined' && window.Math == Math)
  13543. ? window
  13544. : (typeof self != 'undefined' && self.Math == Math)
  13545. ? self
  13546. : Function('return this')()
  13547. ;
  13548. $.fn.progress = function(parameters) {
  13549. var
  13550. $allModules = $(this),
  13551. moduleSelector = $allModules.selector || '',
  13552. time = new Date().getTime(),
  13553. performance = [],
  13554. query = arguments[0],
  13555. methodInvoked = (typeof query == 'string'),
  13556. queryArguments = [].slice.call(arguments, 1),
  13557. returnedValue
  13558. ;
  13559. $allModules
  13560. .each(function() {
  13561. var
  13562. settings = ( $.isPlainObject(parameters) )
  13563. ? $.extend(true, {}, $.fn.progress.settings, parameters)
  13564. : $.extend({}, $.fn.progress.settings),
  13565. className = settings.className,
  13566. metadata = settings.metadata,
  13567. namespace = settings.namespace,
  13568. selector = settings.selector,
  13569. error = settings.error,
  13570. eventNamespace = '.' + namespace,
  13571. moduleNamespace = 'module-' + namespace,
  13572. $module = $(this),
  13573. $bars = $(this).find(selector.bar),
  13574. $progresses = $(this).find(selector.progress),
  13575. $label = $(this).find(selector.label),
  13576. element = this,
  13577. instance = $module.data(moduleNamespace),
  13578. animating = false,
  13579. transitionEnd,
  13580. module
  13581. ;
  13582. module = {
  13583. helper: {
  13584. sum: function (nums) {
  13585. return Array.isArray(nums) ? nums.reduce(function (left, right) {
  13586. return left + Number(right);
  13587. }, 0) : 0;
  13588. },
  13589. /**
  13590. * Derive precision for multiple progress with total and values.
  13591. *
  13592. * This helper dervices a precision that is sufficiently large to show minimum value of multiple progress.
  13593. *
  13594. * Example1
  13595. * - total: 1122
  13596. * - values: [325, 111, 74, 612]
  13597. * - min ratio: 74/1122 = 0.0659...
  13598. * - required precision: 100
  13599. *
  13600. * Example2
  13601. * - total: 10541
  13602. * - values: [3235, 1111, 74, 6121]
  13603. * - min ratio: 74/10541 = 0.0070...
  13604. * - required precision: 1000
  13605. *
  13606. * @param min A minimum value within multiple values
  13607. * @param total A total amount of multiple values
  13608. * @returns {number} A precison. Could be 1, 10, 100, ... 1e+10.
  13609. */
  13610. derivePrecision: function(min, total) {
  13611. var precisionPower = 0
  13612. var precision = 1;
  13613. var ratio = min / total;
  13614. while (precisionPower < 10) {
  13615. ratio = ratio * precision;
  13616. if (ratio > 1) {
  13617. break;
  13618. }
  13619. precision = Math.pow(10, precisionPower++);
  13620. }
  13621. return precision;
  13622. },
  13623. forceArray: function (element) {
  13624. return Array.isArray(element)
  13625. ? element
  13626. : !isNaN(element)
  13627. ? [element]
  13628. : typeof element == 'string'
  13629. ? element.split(',')
  13630. : []
  13631. ;
  13632. }
  13633. },
  13634. initialize: function() {
  13635. module.set.duration();
  13636. module.set.transitionEvent();
  13637. module.debug(element);
  13638. module.read.metadata();
  13639. module.read.settings();
  13640. module.instantiate();
  13641. },
  13642. instantiate: function() {
  13643. module.verbose('Storing instance of progress', module);
  13644. instance = module;
  13645. $module
  13646. .data(moduleNamespace, module)
  13647. ;
  13648. },
  13649. destroy: function() {
  13650. module.verbose('Destroying previous progress for', $module);
  13651. clearInterval(instance.interval);
  13652. module.remove.state();
  13653. $module.removeData(moduleNamespace);
  13654. instance = undefined;
  13655. },
  13656. reset: function() {
  13657. module.remove.nextValue();
  13658. module.update.progress(0);
  13659. },
  13660. complete: function(keepState) {
  13661. if(module.percent === undefined || module.percent < 100) {
  13662. module.remove.progressPoll();
  13663. if(keepState !== true){
  13664. module.set.percent(100);
  13665. }
  13666. }
  13667. },
  13668. read: {
  13669. metadata: function() {
  13670. var
  13671. data = {
  13672. percent : module.helper.forceArray($module.data(metadata.percent)),
  13673. total : $module.data(metadata.total),
  13674. value : module.helper.forceArray($module.data(metadata.value))
  13675. }
  13676. ;
  13677. if(data.total) {
  13678. module.debug('Total value set from metadata', data.total);
  13679. module.set.total(data.total);
  13680. }
  13681. if(data.value.length > 0) {
  13682. module.debug('Current value set from metadata', data.value);
  13683. module.set.value(data.value);
  13684. module.set.progress(data.value);
  13685. }
  13686. if(data.percent.length > 0) {
  13687. module.debug('Current percent value set from metadata', data.percent);
  13688. module.set.percent(data.percent);
  13689. }
  13690. },
  13691. settings: function() {
  13692. if(settings.total !== false) {
  13693. module.debug('Current total set in settings', settings.total);
  13694. module.set.total(settings.total);
  13695. }
  13696. if(settings.value !== false) {
  13697. module.debug('Current value set in settings', settings.value);
  13698. module.set.value(settings.value);
  13699. module.set.progress(module.value);
  13700. }
  13701. if(settings.percent !== false) {
  13702. module.debug('Current percent set in settings', settings.percent);
  13703. module.set.percent(settings.percent);
  13704. }
  13705. }
  13706. },
  13707. bind: {
  13708. transitionEnd: function(callback) {
  13709. var
  13710. transitionEnd = module.get.transitionEnd()
  13711. ;
  13712. $bars
  13713. .one(transitionEnd + eventNamespace, function(event) {
  13714. clearTimeout(module.failSafeTimer);
  13715. callback.call(this, event);
  13716. })
  13717. ;
  13718. module.failSafeTimer = setTimeout(function() {
  13719. $bars.triggerHandler(transitionEnd);
  13720. }, settings.duration + settings.failSafeDelay);
  13721. module.verbose('Adding fail safe timer', module.timer);
  13722. }
  13723. },
  13724. increment: function(incrementValue) {
  13725. var
  13726. startValue,
  13727. newValue
  13728. ;
  13729. if( module.has.total() ) {
  13730. startValue = module.get.value();
  13731. incrementValue = incrementValue || 1;
  13732. }
  13733. else {
  13734. startValue = module.get.percent();
  13735. incrementValue = incrementValue || module.get.randomValue();
  13736. }
  13737. newValue = startValue + incrementValue;
  13738. module.debug('Incrementing percentage by', startValue, newValue, incrementValue);
  13739. newValue = module.get.normalizedValue(newValue);
  13740. module.set.progress(newValue);
  13741. },
  13742. decrement: function(decrementValue) {
  13743. var
  13744. total = module.get.total(),
  13745. startValue,
  13746. newValue
  13747. ;
  13748. if(total) {
  13749. startValue = module.get.value();
  13750. decrementValue = decrementValue || 1;
  13751. newValue = startValue - decrementValue;
  13752. module.debug('Decrementing value by', decrementValue, startValue);
  13753. }
  13754. else {
  13755. startValue = module.get.percent();
  13756. decrementValue = decrementValue || module.get.randomValue();
  13757. newValue = startValue - decrementValue;
  13758. module.debug('Decrementing percentage by', decrementValue, startValue);
  13759. }
  13760. newValue = module.get.normalizedValue(newValue);
  13761. module.set.progress(newValue);
  13762. },
  13763. has: {
  13764. progressPoll: function() {
  13765. return module.progressPoll;
  13766. },
  13767. total: function() {
  13768. return (module.get.total() !== false);
  13769. }
  13770. },
  13771. get: {
  13772. text: function(templateText, index) {
  13773. var
  13774. index_ = index || 0,
  13775. value = module.get.value(index_),
  13776. total = module.total || 0,
  13777. percent = (animating)
  13778. ? module.get.displayPercent(index_)
  13779. : module.get.percent(index_),
  13780. left = (module.total > 0)
  13781. ? (total - value)
  13782. : (100 - percent)
  13783. ;
  13784. templateText = templateText || '';
  13785. templateText = templateText
  13786. .replace('{value}', value)
  13787. .replace('{total}', total)
  13788. .replace('{left}', left)
  13789. .replace('{percent}', percent)
  13790. .replace('{bar}', settings.text.bars[index_] || '')
  13791. ;
  13792. module.verbose('Adding variables to progress bar text', templateText);
  13793. return templateText;
  13794. },
  13795. normalizedValue: function(value) {
  13796. if(value < 0) {
  13797. module.debug('Value cannot decrement below 0');
  13798. return 0;
  13799. }
  13800. if(module.has.total()) {
  13801. if(value > module.total) {
  13802. module.debug('Value cannot increment above total', module.total);
  13803. return module.total;
  13804. }
  13805. }
  13806. else if(value > 100 ) {
  13807. module.debug('Value cannot increment above 100 percent');
  13808. return 100;
  13809. }
  13810. return value;
  13811. },
  13812. updateInterval: function() {
  13813. if(settings.updateInterval == 'auto') {
  13814. return settings.duration;
  13815. }
  13816. return settings.updateInterval;
  13817. },
  13818. randomValue: function() {
  13819. module.debug('Generating random increment percentage');
  13820. return Math.floor((Math.random() * settings.random.max) + settings.random.min);
  13821. },
  13822. numericValue: function(value) {
  13823. return (typeof value === 'string')
  13824. ? (value.replace(/[^\d.]/g, '') !== '')
  13825. ? +(value.replace(/[^\d.]/g, ''))
  13826. : false
  13827. : value
  13828. ;
  13829. },
  13830. transitionEnd: function() {
  13831. var
  13832. element = document.createElement('element'),
  13833. transitions = {
  13834. 'transition' :'transitionend',
  13835. 'OTransition' :'oTransitionEnd',
  13836. 'MozTransition' :'transitionend',
  13837. 'WebkitTransition' :'webkitTransitionEnd'
  13838. },
  13839. transition
  13840. ;
  13841. for(transition in transitions){
  13842. if( element.style[transition] !== undefined ){
  13843. return transitions[transition];
  13844. }
  13845. }
  13846. },
  13847. // gets current displayed percentage (if animating values this is the intermediary value)
  13848. displayPercent: function(index) {
  13849. var
  13850. $bar = $($bars[index]),
  13851. barWidth = $bar.width(),
  13852. totalWidth = $module.width(),
  13853. minDisplay = parseInt($bar.css('min-width'), 10),
  13854. displayPercent = (barWidth > minDisplay)
  13855. ? (barWidth / totalWidth * 100)
  13856. : module.percent
  13857. ;
  13858. return (settings.precision > 0)
  13859. ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
  13860. : Math.round(displayPercent)
  13861. ;
  13862. },
  13863. percent: function(index) {
  13864. return module.percent && module.percent[index || 0] || 0;
  13865. },
  13866. value: function(index) {
  13867. return module.nextValue || module.value && module.value[index || 0] || 0;
  13868. },
  13869. total: function() {
  13870. return module.total || false;
  13871. }
  13872. },
  13873. create: {
  13874. progressPoll: function() {
  13875. module.progressPoll = setTimeout(function() {
  13876. module.update.toNextValue();
  13877. module.remove.progressPoll();
  13878. }, module.get.updateInterval());
  13879. },
  13880. },
  13881. is: {
  13882. complete: function() {
  13883. return module.is.success() || module.is.warning() || module.is.error();
  13884. },
  13885. success: function() {
  13886. return $module.hasClass(className.success);
  13887. },
  13888. warning: function() {
  13889. return $module.hasClass(className.warning);
  13890. },
  13891. error: function() {
  13892. return $module.hasClass(className.error);
  13893. },
  13894. active: function() {
  13895. return $module.hasClass(className.active);
  13896. },
  13897. visible: function() {
  13898. return $module.is(':visible');
  13899. }
  13900. },
  13901. remove: {
  13902. progressPoll: function() {
  13903. module.verbose('Removing progress poll timer');
  13904. if(module.progressPoll) {
  13905. clearTimeout(module.progressPoll);
  13906. delete module.progressPoll;
  13907. }
  13908. },
  13909. nextValue: function() {
  13910. module.verbose('Removing progress value stored for next update');
  13911. delete module.nextValue;
  13912. },
  13913. state: function() {
  13914. module.verbose('Removing stored state');
  13915. delete module.total;
  13916. delete module.percent;
  13917. delete module.value;
  13918. },
  13919. active: function() {
  13920. module.verbose('Removing active state');
  13921. $module.removeClass(className.active);
  13922. },
  13923. success: function() {
  13924. module.verbose('Removing success state');
  13925. $module.removeClass(className.success);
  13926. },
  13927. warning: function() {
  13928. module.verbose('Removing warning state');
  13929. $module.removeClass(className.warning);
  13930. },
  13931. error: function() {
  13932. module.verbose('Removing error state');
  13933. $module.removeClass(className.error);
  13934. }
  13935. },
  13936. set: {
  13937. barWidth: function(values) {
  13938. module.debug("set bar width with ", values);
  13939. values = module.helper.forceArray(values);
  13940. var firstNonZeroIndex = -1;
  13941. var lastNonZeroIndex = -1;
  13942. var valuesSum = module.helper.sum(values);
  13943. var barCounts = $bars.length;
  13944. var isMultiple = barCounts > 1;
  13945. var percents = values.map(function(value, index) {
  13946. var allZero = (index === barCounts - 1 && valuesSum === 0);
  13947. var $bar = $($bars[index]);
  13948. if (value === 0 && isMultiple && !allZero) {
  13949. $bar.css('display', 'none');
  13950. } else {
  13951. if (isMultiple && allZero) {
  13952. $bar.css('background', 'transparent');
  13953. }
  13954. if (firstNonZeroIndex == -1) {
  13955. firstNonZeroIndex = index;
  13956. }
  13957. lastNonZeroIndex = index;
  13958. $bar.css({
  13959. display: 'block',
  13960. width: value + '%'
  13961. });
  13962. }
  13963. return parseFloat(value);
  13964. });
  13965. values.forEach(function(_, index) {
  13966. var $bar = $($bars[index]);
  13967. $bar.css({
  13968. borderTopLeftRadius: index == firstNonZeroIndex ? '' : 0,
  13969. borderBottomLeftRadius: index == firstNonZeroIndex ? '' : 0,
  13970. borderTopRightRadius: index == lastNonZeroIndex ? '' : 0,
  13971. borderBottomRightRadius: index == lastNonZeroIndex ? '' : 0
  13972. });
  13973. });
  13974. $module
  13975. .attr('data-percent', percents)
  13976. ;
  13977. },
  13978. duration: function(duration) {
  13979. duration = duration || settings.duration;
  13980. duration = (typeof duration == 'number')
  13981. ? duration + 'ms'
  13982. : duration
  13983. ;
  13984. module.verbose('Setting progress bar transition duration', duration);
  13985. $bars
  13986. .css({
  13987. 'transition-duration': duration
  13988. })
  13989. ;
  13990. },
  13991. percent: function(percents) {
  13992. percents = module.helper.forceArray(percents).map(function(percent) {
  13993. return (typeof percent == 'string')
  13994. ? +(percent.replace('%', ''))
  13995. : percent
  13996. ;
  13997. });
  13998. var hasTotal = module.has.total();
  13999. var totalPecent = module.helper.sum(percents);
  14000. var isMultpleValues = percents.length > 1 && hasTotal;
  14001. var sumTotal = module.helper.sum(module.helper.forceArray(module.value));
  14002. if (isMultpleValues && sumTotal > module.total) {
  14003. // Sum values instead of pecents to avoid precision issues when summing floats
  14004. module.error(error.sumExceedsTotal, sumTotal, module.total);
  14005. } else if (!isMultpleValues && totalPecent > 100) {
  14006. // Sum before rouding since sum of rounded may have error though sum of actual is fine
  14007. module.error(error.tooHigh, totalPecent);
  14008. } else if (totalPecent < 0) {
  14009. module.error(error.tooLow, totalPecent);
  14010. } else {
  14011. var autoPrecision = settings.precision > 0
  14012. ? settings.precision
  14013. : isMultpleValues
  14014. ? module.helper.derivePrecision(Math.min.apply(null, module.value), module.total)
  14015. : undefined;
  14016. // round display percentage
  14017. var roundedPercents = percents.map(function (percent) {
  14018. return (autoPrecision > 0)
  14019. ? Math.round(percent * (10 * autoPrecision)) / (10 * autoPrecision)
  14020. : Math.round(percent)
  14021. ;
  14022. });
  14023. module.percent = roundedPercents;
  14024. if (!hasTotal) {
  14025. module.value = roundedPercents.map(function (percent) {
  14026. return (autoPrecision > 0)
  14027. ? Math.round((percent / 100) * module.total * (10 * autoPrecision)) / (10 * autoPrecision)
  14028. : Math.round((percent / 100) * module.total * 10) / 10
  14029. ;
  14030. });
  14031. if (settings.limitValues) {
  14032. module.value = module.value.map(function (value) {
  14033. return (value > 100)
  14034. ? 100
  14035. : (module.value < 0)
  14036. ? 0
  14037. : module.value;
  14038. });
  14039. }
  14040. }
  14041. module.set.barWidth(percents);
  14042. module.set.labelInterval();
  14043. module.set.labels();
  14044. }
  14045. settings.onChange.call(element, percents, module.value, module.total);
  14046. },
  14047. labelInterval: function() {
  14048. var
  14049. animationCallback = function() {
  14050. module.verbose('Bar finished animating, removing continuous label updates');
  14051. clearInterval(module.interval);
  14052. animating = false;
  14053. module.set.labels();
  14054. }
  14055. ;
  14056. clearInterval(module.interval);
  14057. module.bind.transitionEnd(animationCallback);
  14058. animating = true;
  14059. module.interval = setInterval(function() {
  14060. var
  14061. isInDOM = $.contains(document.documentElement, element)
  14062. ;
  14063. if(!isInDOM) {
  14064. clearInterval(module.interval);
  14065. animating = false;
  14066. }
  14067. module.set.labels();
  14068. }, settings.framerate);
  14069. },
  14070. labels: function() {
  14071. module.verbose('Setting both bar progress and outer label text');
  14072. module.set.barLabel();
  14073. module.set.state();
  14074. },
  14075. label: function(text) {
  14076. text = text || '';
  14077. if(text) {
  14078. text = module.get.text(text);
  14079. module.verbose('Setting label to text', text);
  14080. $label.text(text);
  14081. }
  14082. },
  14083. state: function(percent) {
  14084. percent = (percent !== undefined)
  14085. ? percent
  14086. : module.helper.sum(module.percent)
  14087. ;
  14088. if(percent === 100) {
  14089. if(settings.autoSuccess && $bars.length === 1 && !(module.is.warning() || module.is.error() || module.is.success())) {
  14090. module.set.success();
  14091. module.debug('Automatically triggering success at 100%');
  14092. }
  14093. else {
  14094. module.verbose('Reached 100% removing active state');
  14095. module.remove.active();
  14096. module.remove.progressPoll();
  14097. }
  14098. }
  14099. else if(percent > 0) {
  14100. module.verbose('Adjusting active progress bar label', percent);
  14101. module.set.active();
  14102. }
  14103. else {
  14104. module.remove.active();
  14105. module.set.label(settings.text.active);
  14106. }
  14107. },
  14108. barLabel: function(text) {
  14109. $progresses.map(function(index, element){
  14110. var $progress = $(element);
  14111. if (text !== undefined) {
  14112. $progress.text( module.get.text(text, index) );
  14113. }
  14114. else if (settings.label == 'ratio' && module.total) {
  14115. module.verbose('Adding ratio to bar label');
  14116. $progress.text( module.get.text(settings.text.ratio, index) );
  14117. }
  14118. else if (settings.label == 'percent') {
  14119. module.verbose('Adding percentage to bar label');
  14120. $progress.text( module.get.text(settings.text.percent, index) );
  14121. }
  14122. });
  14123. },
  14124. active: function(text) {
  14125. text = text || settings.text.active;
  14126. module.debug('Setting active state');
  14127. if(settings.showActivity && !module.is.active() ) {
  14128. $module.addClass(className.active);
  14129. }
  14130. module.remove.warning();
  14131. module.remove.error();
  14132. module.remove.success();
  14133. text = settings.onLabelUpdate('active', text, module.value, module.total);
  14134. if(text) {
  14135. module.set.label(text);
  14136. }
  14137. module.bind.transitionEnd(function() {
  14138. settings.onActive.call(element, module.value, module.total);
  14139. });
  14140. },
  14141. success : function(text, keepState) {
  14142. text = text || settings.text.success || settings.text.active;
  14143. module.debug('Setting success state');
  14144. $module.addClass(className.success);
  14145. module.remove.active();
  14146. module.remove.warning();
  14147. module.remove.error();
  14148. module.complete(keepState);
  14149. if(settings.text.success) {
  14150. text = settings.onLabelUpdate('success', text, module.value, module.total);
  14151. module.set.label(text);
  14152. }
  14153. else {
  14154. text = settings.onLabelUpdate('active', text, module.value, module.total);
  14155. module.set.label(text);
  14156. }
  14157. module.bind.transitionEnd(function() {
  14158. settings.onSuccess.call(element, module.total);
  14159. });
  14160. },
  14161. warning : function(text, keepState) {
  14162. text = text || settings.text.warning;
  14163. module.debug('Setting warning state');
  14164. $module.addClass(className.warning);
  14165. module.remove.active();
  14166. module.remove.success();
  14167. module.remove.error();
  14168. module.complete(keepState);
  14169. text = settings.onLabelUpdate('warning', text, module.value, module.total);
  14170. if(text) {
  14171. module.set.label(text);
  14172. }
  14173. module.bind.transitionEnd(function() {
  14174. settings.onWarning.call(element, module.value, module.total);
  14175. });
  14176. },
  14177. error : function(text, keepState) {
  14178. text = text || settings.text.error;
  14179. module.debug('Setting error state');
  14180. $module.addClass(className.error);
  14181. module.remove.active();
  14182. module.remove.success();
  14183. module.remove.warning();
  14184. module.complete(keepState);
  14185. text = settings.onLabelUpdate('error', text, module.value, module.total);
  14186. if(text) {
  14187. module.set.label(text);
  14188. }
  14189. module.bind.transitionEnd(function() {
  14190. settings.onError.call(element, module.value, module.total);
  14191. });
  14192. },
  14193. transitionEvent: function() {
  14194. transitionEnd = module.get.transitionEnd();
  14195. },
  14196. total: function(totalValue) {
  14197. module.total = totalValue;
  14198. },
  14199. value: function(value) {
  14200. module.value = module.helper.forceArray(value);
  14201. },
  14202. progress: function(value) {
  14203. if(!module.has.progressPoll()) {
  14204. module.debug('First update in progress update interval, immediately updating', value);
  14205. module.update.progress(value);
  14206. module.create.progressPoll();
  14207. }
  14208. else {
  14209. module.debug('Updated within interval, setting next update to use new value', value);
  14210. module.set.nextValue(value);
  14211. }
  14212. },
  14213. nextValue: function(value) {
  14214. module.nextValue = value;
  14215. }
  14216. },
  14217. update: {
  14218. toNextValue: function() {
  14219. var
  14220. nextValue = module.nextValue
  14221. ;
  14222. if(nextValue) {
  14223. module.debug('Update interval complete using last updated value', nextValue);
  14224. module.update.progress(nextValue);
  14225. module.remove.nextValue();
  14226. }
  14227. },
  14228. progress: function(values) {
  14229. var hasTotal = module.has.total();
  14230. if (hasTotal) {
  14231. module.set.value(values);
  14232. }
  14233. var percentCompletes = module.helper.forceArray(values).map(function(value) {
  14234. var
  14235. percentComplete
  14236. ;
  14237. value = module.get.numericValue(value);
  14238. if (value === false) {
  14239. module.error(error.nonNumeric, value);
  14240. }
  14241. value = module.get.normalizedValue(value);
  14242. if (hasTotal) {
  14243. percentComplete = (value / module.total) * 100;
  14244. module.debug('Calculating percent complete from total', percentComplete);
  14245. }
  14246. else {
  14247. percentComplete = value;
  14248. module.debug('Setting value to exact percentage value', percentComplete);
  14249. }
  14250. return percentComplete;
  14251. });
  14252. module.set.percent( percentCompletes );
  14253. }
  14254. },
  14255. setting: function(name, value) {
  14256. module.debug('Changing setting', name, value);
  14257. if( $.isPlainObject(name) ) {
  14258. $.extend(true, settings, name);
  14259. }
  14260. else if(value !== undefined) {
  14261. if($.isPlainObject(settings[name])) {
  14262. $.extend(true, settings[name], value);
  14263. }
  14264. else {
  14265. settings[name] = value;
  14266. }
  14267. }
  14268. else {
  14269. return settings[name];
  14270. }
  14271. },
  14272. internal: function(name, value) {
  14273. if( $.isPlainObject(name) ) {
  14274. $.extend(true, module, name);
  14275. }
  14276. else if(value !== undefined) {
  14277. module[name] = value;
  14278. }
  14279. else {
  14280. return module[name];
  14281. }
  14282. },
  14283. debug: function() {
  14284. if(!settings.silent && settings.debug) {
  14285. if(settings.performance) {
  14286. module.performance.log(arguments);
  14287. }
  14288. else {
  14289. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14290. module.debug.apply(console, arguments);
  14291. }
  14292. }
  14293. },
  14294. verbose: function() {
  14295. if(!settings.silent && settings.verbose && settings.debug) {
  14296. if(settings.performance) {
  14297. module.performance.log(arguments);
  14298. }
  14299. else {
  14300. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14301. module.verbose.apply(console, arguments);
  14302. }
  14303. }
  14304. },
  14305. error: function() {
  14306. if(!settings.silent) {
  14307. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  14308. module.error.apply(console, arguments);
  14309. }
  14310. },
  14311. performance: {
  14312. log: function(message) {
  14313. var
  14314. currentTime,
  14315. executionTime,
  14316. previousTime
  14317. ;
  14318. if(settings.performance) {
  14319. currentTime = new Date().getTime();
  14320. previousTime = time || currentTime;
  14321. executionTime = currentTime - previousTime;
  14322. time = currentTime;
  14323. performance.push({
  14324. 'Name' : message[0],
  14325. 'Arguments' : [].slice.call(message, 1) || '',
  14326. 'Element' : element,
  14327. 'Execution Time' : executionTime
  14328. });
  14329. }
  14330. clearTimeout(module.performance.timer);
  14331. module.performance.timer = setTimeout(module.performance.display, 500);
  14332. },
  14333. display: function() {
  14334. var
  14335. title = settings.name + ':',
  14336. totalTime = 0
  14337. ;
  14338. time = false;
  14339. clearTimeout(module.performance.timer);
  14340. $.each(performance, function(index, data) {
  14341. totalTime += data['Execution Time'];
  14342. });
  14343. title += ' ' + totalTime + 'ms';
  14344. if(moduleSelector) {
  14345. title += ' \'' + moduleSelector + '\'';
  14346. }
  14347. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  14348. console.groupCollapsed(title);
  14349. if(console.table) {
  14350. console.table(performance);
  14351. }
  14352. else {
  14353. $.each(performance, function(index, data) {
  14354. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  14355. });
  14356. }
  14357. console.groupEnd();
  14358. }
  14359. performance = [];
  14360. }
  14361. },
  14362. invoke: function(query, passedArguments, context) {
  14363. var
  14364. object = instance,
  14365. maxDepth,
  14366. found,
  14367. response
  14368. ;
  14369. passedArguments = passedArguments || queryArguments;
  14370. context = element || context;
  14371. if(typeof query == 'string' && object !== undefined) {
  14372. query = query.split(/[\. ]/);
  14373. maxDepth = query.length - 1;
  14374. $.each(query, function(depth, value) {
  14375. var camelCaseValue = (depth != maxDepth)
  14376. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  14377. : query
  14378. ;
  14379. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  14380. object = object[camelCaseValue];
  14381. }
  14382. else if( object[camelCaseValue] !== undefined ) {
  14383. found = object[camelCaseValue];
  14384. return false;
  14385. }
  14386. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  14387. object = object[value];
  14388. }
  14389. else if( object[value] !== undefined ) {
  14390. found = object[value];
  14391. return false;
  14392. }
  14393. else {
  14394. module.error(error.method, query);
  14395. return false;
  14396. }
  14397. });
  14398. }
  14399. if ( $.isFunction( found ) ) {
  14400. response = found.apply(context, passedArguments);
  14401. }
  14402. else if(found !== undefined) {
  14403. response = found;
  14404. }
  14405. if(Array.isArray(returnedValue)) {
  14406. returnedValue.push(response);
  14407. }
  14408. else if(returnedValue !== undefined) {
  14409. returnedValue = [returnedValue, response];
  14410. }
  14411. else if(response !== undefined) {
  14412. returnedValue = response;
  14413. }
  14414. return found;
  14415. }
  14416. };
  14417. if(methodInvoked) {
  14418. if(instance === undefined) {
  14419. module.initialize();
  14420. }
  14421. module.invoke(query);
  14422. }
  14423. else {
  14424. if(instance !== undefined) {
  14425. instance.invoke('destroy');
  14426. }
  14427. module.initialize();
  14428. }
  14429. })
  14430. ;
  14431. return (returnedValue !== undefined)
  14432. ? returnedValue
  14433. : this
  14434. ;
  14435. };
  14436. $.fn.progress.settings = {
  14437. name : 'Progress',
  14438. namespace : 'progress',
  14439. silent : false,
  14440. debug : false,
  14441. verbose : false,
  14442. performance : true,
  14443. random : {
  14444. min : 2,
  14445. max : 5
  14446. },
  14447. duration : 300,
  14448. updateInterval : 'auto',
  14449. autoSuccess : true,
  14450. showActivity : true,
  14451. limitValues : true,
  14452. label : 'percent',
  14453. precision : 0,
  14454. framerate : (1000 / 30), /// 30 fps
  14455. percent : false,
  14456. total : false,
  14457. value : false,
  14458. // delay in ms for fail safe animation callback
  14459. failSafeDelay : 100,
  14460. onLabelUpdate : function(state, text, value, total){
  14461. return text;
  14462. },
  14463. onChange : function(percent, value, total){},
  14464. onSuccess : function(total){},
  14465. onActive : function(value, total){},
  14466. onError : function(value, total){},
  14467. onWarning : function(value, total){},
  14468. error : {
  14469. method : 'The method you called is not defined.',
  14470. nonNumeric : 'Progress value is non numeric',
  14471. tooHigh : 'Value specified is above 100%',
  14472. tooLow : 'Value specified is below 0%',
  14473. sumExceedsTotal : 'Sum of multple values exceed total',
  14474. },
  14475. regExp: {
  14476. variable: /\{\$*[A-z0-9]+\}/g
  14477. },
  14478. metadata: {
  14479. percent : 'percent',
  14480. total : 'total',
  14481. value : 'value'
  14482. },
  14483. selector : {
  14484. bar : '> .bar',
  14485. label : '> .label',
  14486. progress : '.bar > .progress'
  14487. },
  14488. text : {
  14489. active : false,
  14490. error : false,
  14491. success : false,
  14492. warning : false,
  14493. percent : '{percent}%',
  14494. ratio : '{value} of {total}',
  14495. bars : ['']
  14496. },
  14497. className : {
  14498. active : 'active',
  14499. error : 'error',
  14500. success : 'success',
  14501. warning : 'warning'
  14502. }
  14503. };
  14504. })( jQuery, window, document );
  14505. /*!
  14506. * # Fomantic-UI - Slider
  14507. * http://github.com/fomantic/Fomantic-UI/
  14508. *
  14509. *
  14510. * Released under the MIT license
  14511. * http://opensource.org/licenses/MIT
  14512. *
  14513. */
  14514. ;(function ( $, window, document, undefined ) {
  14515. "use strict";
  14516. window = (typeof window != 'undefined' && window.Math == Math)
  14517. ? window
  14518. : (typeof self != 'undefined' && self.Math == Math)
  14519. ? self
  14520. : Function('return this')()
  14521. ;
  14522. $.fn.slider = function(parameters) {
  14523. var
  14524. $allModules = $(this),
  14525. $window = $(window),
  14526. moduleSelector = $allModules.selector || '',
  14527. time = new Date().getTime(),
  14528. performance = [],
  14529. query = arguments[0],
  14530. methodInvoked = (typeof query == 'string'),
  14531. queryArguments = [].slice.call(arguments, 1),
  14532. alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
  14533. SINGLE_STEP = 1,
  14534. BIG_STEP = 2,
  14535. NO_STEP = 0,
  14536. SINGLE_BACKSTEP = -1,
  14537. BIG_BACKSTEP = -2,
  14538. // Used to manage document bound events.
  14539. // Use this so that we can distinguish between which document events are bound to which range.
  14540. currentRange = 0,
  14541. returnedValue
  14542. ;
  14543. $allModules
  14544. .each(function() {
  14545. var
  14546. settings = ( $.isPlainObject(parameters) )
  14547. ? $.extend(true, {}, $.fn.slider.settings, parameters)
  14548. : $.extend({}, $.fn.slider.settings),
  14549. className = settings.className,
  14550. metadata = settings.metadata,
  14551. namespace = settings.namespace,
  14552. error = settings.error,
  14553. keys = settings.keys,
  14554. interpretLabel = settings.interpretLabel,
  14555. isHover = false,
  14556. eventNamespace = '.' + namespace,
  14557. moduleNamespace = 'module-' + namespace,
  14558. $module = $(this),
  14559. $currThumb,
  14560. $thumb,
  14561. $secondThumb,
  14562. $track,
  14563. $trackFill,
  14564. $labels,
  14565. element = this,
  14566. instance = $module.data(moduleNamespace),
  14567. documentEventID,
  14568. value,
  14569. position,
  14570. secondPos,
  14571. offset,
  14572. precision,
  14573. isTouch,
  14574. gapRatio = 1,
  14575. initialPosition,
  14576. initialLoad,
  14577. module
  14578. ;
  14579. module = {
  14580. initialize: function() {
  14581. module.debug('Initializing slider', settings);
  14582. initialLoad = true;
  14583. currentRange += 1;
  14584. documentEventID = currentRange;
  14585. isTouch = module.setup.testOutTouch();
  14586. module.setup.layout();
  14587. module.setup.labels();
  14588. if(!module.is.disabled()) {
  14589. module.bind.events();
  14590. }
  14591. module.read.metadata();
  14592. module.read.settings();
  14593. initialLoad = false;
  14594. module.instantiate();
  14595. },
  14596. instantiate: function() {
  14597. module.verbose('Storing instance of slider', module);
  14598. instance = module;
  14599. $module
  14600. .data(moduleNamespace, module)
  14601. ;
  14602. },
  14603. destroy: function() {
  14604. module.verbose('Destroying previous slider for', $module);
  14605. clearInterval(instance.interval);
  14606. module.unbind.events();
  14607. module.unbind.slidingEvents();
  14608. $module.removeData(moduleNamespace);
  14609. instance = undefined;
  14610. },
  14611. setup: {
  14612. layout: function() {
  14613. if( $module.attr('tabindex') === undefined) {
  14614. $module.attr('tabindex', 0);
  14615. }
  14616. if($module.find('.inner').length == 0) {
  14617. $module.append("<div class='inner'>"
  14618. + "<div class='track'></div>"
  14619. + "<div class='track-fill'></div>"
  14620. + "<div class='thumb'></div>"
  14621. + "</div>");
  14622. }
  14623. precision = module.get.precision();
  14624. $thumb = $module.find('.thumb:not(.second)');
  14625. $currThumb = $thumb;
  14626. if(module.is.range()) {
  14627. if($module.find('.thumb.second').length == 0) {
  14628. $module.find('.inner').append("<div class='thumb second'></div>");
  14629. }
  14630. $secondThumb = $module.find('.thumb.second');
  14631. }
  14632. $track = $module.find('.track');
  14633. $trackFill = $module.find('.track-fill');
  14634. offset = $thumb.width() / 2;
  14635. },
  14636. labels: function() {
  14637. if(module.is.labeled()) {
  14638. $labels = $module.find('.labels:not(.auto)');
  14639. if($labels.length != 0) {
  14640. module.setup.customLabel();
  14641. } else {
  14642. module.setup.autoLabel();
  14643. }
  14644. if (settings.showLabelTicks) {
  14645. $module.addClass(className.ticked)
  14646. }
  14647. }
  14648. },
  14649. testOutTouch: function() {
  14650. try {
  14651. document.createEvent('TouchEvent');
  14652. return true;
  14653. } catch (e) {
  14654. return false;
  14655. }
  14656. },
  14657. customLabel: function() {
  14658. var
  14659. $children = $labels.find('.label'),
  14660. numChildren = $children.length,
  14661. min = module.get.min(),
  14662. max = module.get.max(),
  14663. ratio
  14664. ;
  14665. $children.each(function(index) {
  14666. var
  14667. $child = $(this),
  14668. attrValue = $child.attr('data-value')
  14669. ;
  14670. if(attrValue) {
  14671. attrValue = attrValue > max ? max : attrValue < min ? min : attrValue;
  14672. ratio = (attrValue - min) / (max - min);
  14673. } else {
  14674. ratio = (index + 1) / (numChildren + 1);
  14675. }
  14676. module.update.labelPosition(ratio, $(this));
  14677. });
  14678. },
  14679. autoLabel: function() {
  14680. if(module.get.step() != 0) {
  14681. $labels = $module.find('.labels');
  14682. if($labels.length != 0) {
  14683. $labels.empty();
  14684. }
  14685. else {
  14686. $labels = $module.append('<ul class="auto labels"></ul>').find('.labels');
  14687. }
  14688. for(var i = 0, len = module.get.numLabels(); i <= len; i++) {
  14689. var
  14690. labelText = module.get.label(i),
  14691. $label = (labelText !== "")
  14692. ? !(i % module.get.gapRatio())
  14693. ? $('<li class="label">' + labelText + '</li>')
  14694. : $('<li class="halftick label"></li>')
  14695. : null,
  14696. ratio = i / len
  14697. ;
  14698. if($label) {
  14699. module.update.labelPosition(ratio, $label);
  14700. $labels.append($label);
  14701. }
  14702. }
  14703. }
  14704. }
  14705. },
  14706. bind: {
  14707. events: function() {
  14708. module.bind.globalKeyboardEvents();
  14709. module.bind.keyboardEvents();
  14710. module.bind.mouseEvents();
  14711. if(module.is.touch()) {
  14712. module.bind.touchEvents();
  14713. }
  14714. if (settings.autoAdjustLabels) {
  14715. module.bind.windowEvents();
  14716. }
  14717. },
  14718. keyboardEvents: function() {
  14719. module.verbose('Binding keyboard events');
  14720. $module.on('keydown' + eventNamespace, module.event.keydown);
  14721. },
  14722. globalKeyboardEvents: function() {
  14723. $(document).on('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
  14724. },
  14725. mouseEvents: function() {
  14726. module.verbose('Binding mouse events');
  14727. $module.find('.track, .thumb, .inner').on('mousedown' + eventNamespace, function(event) {
  14728. event.stopImmediatePropagation();
  14729. event.preventDefault();
  14730. module.event.down(event);
  14731. });
  14732. $module.on('mousedown' + eventNamespace, module.event.down);
  14733. $module.on('mouseenter' + eventNamespace, function(event) {
  14734. isHover = true;
  14735. });
  14736. $module.on('mouseleave' + eventNamespace, function(event) {
  14737. isHover = false;
  14738. });
  14739. },
  14740. touchEvents: function() {
  14741. module.verbose('Binding touch events');
  14742. $module.find('.track, .thumb, .inner').on('touchstart' + eventNamespace, function(event) {
  14743. event.stopImmediatePropagation();
  14744. event.preventDefault();
  14745. module.event.down(event);
  14746. });
  14747. $module.on('touchstart' + eventNamespace, module.event.down);
  14748. },
  14749. slidingEvents: function() {
  14750. // these don't need the identifier because we only ever want one of them to be registered with document
  14751. module.verbose('Binding page wide events while handle is being draged');
  14752. if(module.is.touch()) {
  14753. $(document).on('touchmove' + eventNamespace, module.event.move);
  14754. $(document).on('touchend' + eventNamespace, module.event.up);
  14755. }
  14756. else {
  14757. $(document).on('mousemove' + eventNamespace, module.event.move);
  14758. $(document).on('mouseup' + eventNamespace, module.event.up);
  14759. }
  14760. },
  14761. windowEvents: function() {
  14762. $window.on('resize' + eventNamespace, module.event.resize);
  14763. }
  14764. },
  14765. unbind: {
  14766. events: function() {
  14767. $module.find('.track, .thumb, .inner').off('mousedown' + eventNamespace);
  14768. $module.find('.track, .thumb, .inner').off('touchstart' + eventNamespace);
  14769. $module.off('mousedown' + eventNamespace);
  14770. $module.off('mouseenter' + eventNamespace);
  14771. $module.off('mouseleave' + eventNamespace);
  14772. $module.off('touchstart' + eventNamespace);
  14773. $module.off('keydown' + eventNamespace);
  14774. $module.off('focusout' + eventNamespace);
  14775. $(document).off('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
  14776. $window.off('resize' + eventNamespace);
  14777. },
  14778. slidingEvents: function() {
  14779. if(module.is.touch()) {
  14780. $(document).off('touchmove' + eventNamespace);
  14781. $(document).off('touchend' + eventNamespace);
  14782. } else {
  14783. $(document).off('mousemove' + eventNamespace);
  14784. $(document).off('mouseup' + eventNamespace);
  14785. }
  14786. },
  14787. },
  14788. event: {
  14789. down: function(event) {
  14790. event.preventDefault();
  14791. if(module.is.range()) {
  14792. var
  14793. eventPos = module.determine.eventPos(event),
  14794. newPos = module.determine.pos(eventPos)
  14795. ;
  14796. // Special handling if range mode and both thumbs have the same value
  14797. if(module.is.range() && settings.preventCrossover && module.thumbVal === module.secondThumbVal) {
  14798. initialPosition = newPos;
  14799. $currThumb = undefined;
  14800. } else {
  14801. $currThumb = module.determine.closestThumb(newPos);
  14802. }
  14803. }
  14804. if(!module.is.disabled()) {
  14805. module.bind.slidingEvents();
  14806. }
  14807. },
  14808. move: function(event) {
  14809. event.preventDefault();
  14810. var value = module.determine.valueFromEvent(event);
  14811. if($currThumb === undefined) {
  14812. var
  14813. eventPos = module.determine.eventPos(event),
  14814. newPos = module.determine.pos(eventPos)
  14815. ;
  14816. $currThumb = initialPosition > newPos ? $thumb : $secondThumb;
  14817. }
  14818. if(module.get.step() == 0 || module.is.smooth()) {
  14819. var
  14820. thumbVal = module.thumbVal,
  14821. secondThumbVal = module.secondThumbVal,
  14822. thumbSmoothVal = module.determine.smoothValueFromEvent(event)
  14823. ;
  14824. if(!$currThumb.hasClass('second')) {
  14825. if(settings.preventCrossover) {
  14826. value = Math.min(secondThumbVal, value);
  14827. thumbSmoothVal = Math.min(secondThumbVal, thumbSmoothVal);
  14828. }
  14829. thumbVal = value;
  14830. } else {
  14831. if(settings.preventCrossover) {
  14832. value = Math.max(thumbVal, value);
  14833. thumbSmoothVal = Math.max(thumbVal, thumbSmoothVal);
  14834. }
  14835. secondThumbVal = value;
  14836. }
  14837. value = Math.abs(thumbVal - (secondThumbVal || 0));
  14838. module.update.position(thumbSmoothVal);
  14839. settings.onMove.call(element, value, thumbVal, secondThumbVal);
  14840. } else {
  14841. module.update.value(value, function(value, thumbVal, secondThumbVal) {
  14842. settings.onMove.call(element, value, thumbVal, secondThumbVal);
  14843. });
  14844. }
  14845. },
  14846. up: function(event) {
  14847. event.preventDefault();
  14848. var value = module.determine.valueFromEvent(event);
  14849. module.set.value(value);
  14850. module.unbind.slidingEvents();
  14851. },
  14852. keydown: function(event, first) {
  14853. if(module.is.range() && settings.preventCrossover && module.thumbVal === module.secondThumbVal) {
  14854. $currThumb = undefined;
  14855. }
  14856. if(module.is.focused()) {
  14857. $(document).trigger(event);
  14858. }
  14859. if(first || module.is.focused()) {
  14860. var step = module.determine.keyMovement(event);
  14861. if(step != NO_STEP) {
  14862. event.preventDefault();
  14863. switch(step) {
  14864. case SINGLE_STEP:
  14865. module.takeStep();
  14866. break;
  14867. case BIG_STEP:
  14868. module.takeStep(module.get.multiplier());
  14869. break;
  14870. case SINGLE_BACKSTEP:
  14871. module.backStep();
  14872. break;
  14873. case BIG_BACKSTEP:
  14874. module.backStep(module.get.multiplier());
  14875. break;
  14876. }
  14877. }
  14878. }
  14879. },
  14880. activateFocus: function(event) {
  14881. if(!module.is.focused() && module.is.hover() && module.determine.keyMovement(event) != NO_STEP) {
  14882. event.preventDefault();
  14883. module.event.keydown(event, true);
  14884. $module.focus();
  14885. }
  14886. },
  14887. resize: function(_event) {
  14888. // To avoid a useless performance cost, we only call the label refresh when its necessary
  14889. if (gapRatio != module.get.gapRatio()) {
  14890. module.setup.labels();
  14891. gapRatio = module.get.gapRatio();
  14892. }
  14893. }
  14894. },
  14895. resync: function() {
  14896. module.verbose('Resyncing thumb position based on value');
  14897. if(module.is.range()) {
  14898. module.update.position(module.secondThumbVal, $secondThumb);
  14899. }
  14900. module.update.position(module.thumbVal, $thumb);
  14901. module.setup.labels();
  14902. },
  14903. takeStep: function(multiplier) {
  14904. var
  14905. multiplier = multiplier != undefined ? multiplier : 1,
  14906. step = module.get.step(),
  14907. currValue = module.get.currentThumbValue()
  14908. ;
  14909. module.verbose('Taking a step');
  14910. if(step > 0) {
  14911. module.set.value(currValue + step * multiplier);
  14912. } else if (step == 0){
  14913. var
  14914. precision = module.get.precision(),
  14915. newValue = currValue + (multiplier/precision)
  14916. ;
  14917. module.set.value(Math.round(newValue * precision) / precision);
  14918. }
  14919. },
  14920. backStep: function(multiplier) {
  14921. var
  14922. multiplier = multiplier != undefined ? multiplier : 1,
  14923. step = module.get.step(),
  14924. currValue = module.get.currentThumbValue()
  14925. ;
  14926. module.verbose('Going back a step');
  14927. if(step > 0) {
  14928. module.set.value(currValue - step * multiplier);
  14929. } else if (step == 0) {
  14930. var
  14931. precision = module.get.precision(),
  14932. newValue = currValue - (multiplier/precision)
  14933. ;
  14934. module.set.value(Math.round(newValue * precision) / precision);
  14935. }
  14936. },
  14937. is: {
  14938. range: function() {
  14939. return $module.hasClass(settings.className.range);
  14940. },
  14941. hover: function() {
  14942. return isHover;
  14943. },
  14944. focused: function() {
  14945. return $module.is(':focus');
  14946. },
  14947. disabled: function() {
  14948. return $module.hasClass(settings.className.disabled);
  14949. },
  14950. labeled: function() {
  14951. return $module.hasClass(settings.className.labeled);
  14952. },
  14953. reversed: function() {
  14954. return $module.hasClass(settings.className.reversed);
  14955. },
  14956. vertical: function() {
  14957. return $module.hasClass(settings.className.vertical);
  14958. },
  14959. smooth: function() {
  14960. return settings.smooth || $module.hasClass(settings.className.smooth);
  14961. },
  14962. touch: function() {
  14963. return isTouch;
  14964. }
  14965. },
  14966. get: {
  14967. trackOffset: function() {
  14968. if (module.is.vertical()) {
  14969. return $track.offset().top;
  14970. } else {
  14971. return $track.offset().left;
  14972. }
  14973. },
  14974. trackLength: function() {
  14975. if (module.is.vertical()) {
  14976. return $track.height();
  14977. } else {
  14978. return $track.width();
  14979. }
  14980. },
  14981. trackLeft: function() {
  14982. if (module.is.vertical()) {
  14983. return $track.position().top;
  14984. } else {
  14985. return $track.position().left;
  14986. }
  14987. },
  14988. trackStartPos: function() {
  14989. return module.is.reversed() ? module.get.trackLeft() + module.get.trackLength() : module.get.trackLeft();
  14990. },
  14991. trackEndPos: function() {
  14992. return module.is.reversed() ? module.get.trackLeft() : module.get.trackLeft() + module.get.trackLength();
  14993. },
  14994. trackStartMargin: function () {
  14995. var margin;
  14996. if (module.is.vertical()) {
  14997. margin = module.is.reversed() ? $module.css('padding-bottom') : $module.css('padding-top');
  14998. } else {
  14999. margin = module.is.reversed() ? $module.css('padding-right') : $module.css('padding-left');
  15000. }
  15001. return margin || '0px';
  15002. },
  15003. trackEndMargin: function () {
  15004. var margin;
  15005. if (module.is.vertical()) {
  15006. margin = module.is.reversed() ? $module.css('padding-top') : $module.css('padding-bottom');
  15007. } else {
  15008. margin = module.is.reversed() ? $module.css('padding-left') : $module.css('padding-right');
  15009. }
  15010. return margin || '0px';
  15011. },
  15012. precision: function() {
  15013. var
  15014. decimalPlaces,
  15015. step = module.get.step()
  15016. ;
  15017. if(step != 0) {
  15018. var split = String(step).split('.');
  15019. if(split.length == 2) {
  15020. decimalPlaces = split[1].length;
  15021. } else {
  15022. decimalPlaces = 0;
  15023. }
  15024. } else {
  15025. decimalPlaces = settings.decimalPlaces;
  15026. }
  15027. var precision = Math.pow(10, decimalPlaces);
  15028. module.debug('Precision determined', precision);
  15029. return precision;
  15030. },
  15031. min: function() {
  15032. return settings.min;
  15033. },
  15034. max: function() {
  15035. var step = module.get.step(),
  15036. min = module.get.min(),
  15037. quotient = step === 0 ? 0 : Math.floor((settings.max - min) / step),
  15038. remainder = step === 0 ? 0 : (settings.max - min) % step;
  15039. return remainder === 0 ? settings.max : min + quotient * step;
  15040. },
  15041. step: function() {
  15042. return settings.step;
  15043. },
  15044. numLabels: function() {
  15045. var value = Math.round((module.get.max() - module.get.min()) / module.get.step());
  15046. module.debug('Determined that there should be ' + value + ' labels');
  15047. return value;
  15048. },
  15049. labelType: function() {
  15050. return settings.labelType;
  15051. },
  15052. label: function(value) {
  15053. if(interpretLabel) {
  15054. return interpretLabel(value);
  15055. }
  15056. switch (settings.labelType) {
  15057. case settings.labelTypes.number:
  15058. return Math.round(((value * module.get.step()) + module.get.min()) * precision ) / precision;
  15059. case settings.labelTypes.letter:
  15060. return alphabet[(value) % 26];
  15061. default:
  15062. return value;
  15063. }
  15064. },
  15065. value: function() {
  15066. return value;
  15067. },
  15068. currentThumbValue: function() {
  15069. return $currThumb !== undefined && $currThumb.hasClass('second') ? module.secondThumbVal : module.thumbVal;
  15070. },
  15071. thumbValue: function(which) {
  15072. switch(which) {
  15073. case 'second':
  15074. if(module.is.range()) {
  15075. return module.secondThumbVal;
  15076. }
  15077. else {
  15078. module.error(error.notrange);
  15079. break;
  15080. }
  15081. case 'first':
  15082. default:
  15083. return module.thumbVal;
  15084. }
  15085. },
  15086. multiplier: function() {
  15087. return settings.pageMultiplier;
  15088. },
  15089. thumbPosition: function(which) {
  15090. switch(which) {
  15091. case 'second':
  15092. if(module.is.range()) {
  15093. return secondPos;
  15094. }
  15095. else {
  15096. module.error(error.notrange);
  15097. break;
  15098. }
  15099. case 'first':
  15100. default:
  15101. return position;
  15102. }
  15103. },
  15104. gapRatio: function() {
  15105. var gapRatio = 1;
  15106. if( settings.autoAdjustLabels ) {
  15107. var
  15108. numLabels = module.get.numLabels(),
  15109. trackLength = module.get.trackLength(),
  15110. gapCounter = 1
  15111. ;
  15112. // While the distance between two labels is too short,
  15113. // we divide the number of labels at each iteration
  15114. // and apply only if the modulo of the operation is an odd number.
  15115. if(trackLength>0){
  15116. while ((trackLength / numLabels) * gapCounter < settings.labelDistance) {
  15117. if( !(numLabels % gapCounter) ) {
  15118. gapRatio = gapCounter;
  15119. }
  15120. gapCounter += 1;
  15121. }
  15122. }
  15123. }
  15124. return gapRatio;
  15125. }
  15126. },
  15127. determine: {
  15128. pos: function(pagePos) {
  15129. return module.is.reversed()
  15130. ?
  15131. module.get.trackStartPos() - pagePos + module.get.trackOffset()
  15132. :
  15133. pagePos - module.get.trackOffset() - module.get.trackStartPos()
  15134. ;
  15135. },
  15136. closestThumb: function(eventPos) {
  15137. var
  15138. thumbPos = parseFloat(module.determine.thumbPos($thumb)),
  15139. thumbDelta = Math.abs(eventPos - thumbPos),
  15140. secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
  15141. secondThumbDelta = Math.abs(eventPos - secondThumbPos)
  15142. ;
  15143. if(thumbDelta === secondThumbDelta && module.get.thumbValue() === module.get.min()) {
  15144. return $secondThumb;
  15145. }
  15146. return thumbDelta <= secondThumbDelta ? $thumb : $secondThumb;
  15147. },
  15148. closestThumbPos: function(eventPos) {
  15149. var
  15150. thumbPos = parseFloat(module.determine.thumbPos($thumb)),
  15151. thumbDelta = Math.abs(eventPos - thumbPos),
  15152. secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
  15153. secondThumbDelta = Math.abs(eventPos - secondThumbPos)
  15154. ;
  15155. return thumbDelta <= secondThumbDelta ? thumbPos : secondThumbPos;
  15156. },
  15157. thumbPos: function($element) {
  15158. var pos =
  15159. module.is.vertical()
  15160. ?
  15161. module.is.reversed() ? $element.css('bottom') : $element.css('top')
  15162. :
  15163. module.is.reversed() ? $element.css('right') : $element.css('left')
  15164. ;
  15165. return pos;
  15166. },
  15167. positionFromValue: function(value) {
  15168. var
  15169. min = module.get.min(),
  15170. max = module.get.max(),
  15171. value = value > max ? max : value < min ? min : value,
  15172. trackLength = module.get.trackLength(),
  15173. ratio = (value - min) / (max - min),
  15174. position = Math.round(ratio * trackLength)
  15175. ;
  15176. module.verbose('Determined position: ' + position + ' from value: ' + value);
  15177. return position;
  15178. },
  15179. positionFromRatio: function(ratio) {
  15180. var
  15181. trackLength = module.get.trackLength(),
  15182. step = module.get.step(),
  15183. position = Math.round(ratio * trackLength),
  15184. adjustedPos = (step == 0) ? position : Math.round(position / step) * step
  15185. ;
  15186. return adjustedPos;
  15187. },
  15188. valueFromEvent: function(event) {
  15189. var
  15190. eventPos = module.determine.eventPos(event),
  15191. newPos = module.determine.pos(eventPos),
  15192. value
  15193. ;
  15194. if(eventPos < module.get.trackOffset()) {
  15195. value = module.is.reversed() ? module.get.max() : module.get.min();
  15196. } else if(eventPos > module.get.trackOffset() + module.get.trackLength()) {
  15197. value = module.is.reversed() ? module.get.min() : module.get.max();
  15198. } else {
  15199. value = module.determine.value(newPos);
  15200. }
  15201. return value;
  15202. },
  15203. smoothValueFromEvent: function(event) {
  15204. var
  15205. min = module.get.min(),
  15206. max = module.get.max(),
  15207. trackLength = module.get.trackLength(),
  15208. eventPos = module.determine.eventPos(event),
  15209. newPos = eventPos - module.get.trackOffset(),
  15210. ratio,
  15211. value
  15212. ;
  15213. newPos = newPos < 0 ? 0 : newPos > trackLength ? trackLength : newPos;
  15214. ratio = newPos / trackLength;
  15215. if (module.is.reversed()) {
  15216. ratio = 1 - ratio;
  15217. }
  15218. value = ratio * (max - min) + min;
  15219. return value;
  15220. },
  15221. eventPos: function(event) {
  15222. if(module.is.touch()) {
  15223. var
  15224. touchEvent = event.changedTouches ? event : event.originalEvent,
  15225. touches = touchEvent.changedTouches[0] ? touchEvent.changedTouches : touchEvent.touches,
  15226. touchY = touches[0].pageY,
  15227. touchX = touches[0].pageX
  15228. ;
  15229. return module.is.vertical() ? touchY : touchX;
  15230. }
  15231. var
  15232. clickY = event.pageY || event.originalEvent.pageY,
  15233. clickX = event.pageX || event.originalEvent.pageX
  15234. ;
  15235. return module.is.vertical() ? clickY : clickX;
  15236. },
  15237. value: function(position) {
  15238. var
  15239. startPos = module.is.reversed() ? module.get.trackEndPos() : module.get.trackStartPos(),
  15240. endPos = module.is.reversed() ? module.get.trackStartPos() : module.get.trackEndPos(),
  15241. ratio = (position - startPos) / (endPos - startPos),
  15242. range = module.get.max() - module.get.min(),
  15243. step = module.get.step(),
  15244. value = (ratio * range),
  15245. difference = (step == 0) ? value : Math.round(value / step) * step
  15246. ;
  15247. module.verbose('Determined value based upon position: ' + position + ' as: ' + value);
  15248. if(value != difference) {
  15249. module.verbose('Rounding value to closest step: ' + difference);
  15250. }
  15251. // Use precision to avoid ugly Javascript floating point rounding issues
  15252. // (like 35 * .01 = 0.35000000000000003)
  15253. difference = Math.round(difference * precision) / precision;
  15254. module.verbose('Cutting off additional decimal places');
  15255. return difference + module.get.min();
  15256. },
  15257. keyMovement: function(event) {
  15258. var
  15259. key = event.which,
  15260. downArrow =
  15261. module.is.vertical()
  15262. ?
  15263. module.is.reversed() ? keys.downArrow : keys.upArrow
  15264. :
  15265. keys.downArrow
  15266. ,
  15267. upArrow =
  15268. module.is.vertical()
  15269. ?
  15270. module.is.reversed() ? keys.upArrow : keys.downArrow
  15271. :
  15272. keys.upArrow
  15273. ,
  15274. leftArrow =
  15275. !module.is.vertical()
  15276. ?
  15277. module.is.reversed() ? keys.rightArrow : keys.leftArrow
  15278. :
  15279. keys.leftArrow
  15280. ,
  15281. rightArrow =
  15282. !module.is.vertical()
  15283. ?
  15284. module.is.reversed() ? keys.leftArrow : keys.rightArrow
  15285. :
  15286. keys.rightArrow
  15287. ;
  15288. if(key == downArrow || key == leftArrow) {
  15289. return SINGLE_BACKSTEP;
  15290. } else if(key == upArrow || key == rightArrow) {
  15291. return SINGLE_STEP;
  15292. } else if (key == keys.pageDown) {
  15293. return BIG_BACKSTEP;
  15294. } else if (key == keys.pageUp) {
  15295. return BIG_STEP;
  15296. } else {
  15297. return NO_STEP;
  15298. }
  15299. }
  15300. },
  15301. handleNewValuePosition: function(val) {
  15302. var
  15303. min = module.get.min(),
  15304. max = module.get.max(),
  15305. newPos
  15306. ;
  15307. if (val <= min) {
  15308. val = min;
  15309. } else if (val >= max) {
  15310. val = max;
  15311. }
  15312. newPos = module.determine.positionFromValue(val);
  15313. return newPos;
  15314. },
  15315. set: {
  15316. value: function(newValue) {
  15317. module.update.value(newValue, function(value, thumbVal, secondThumbVal) {
  15318. if (!initialLoad || settings.fireOnInit){
  15319. settings.onChange.call(element, value, thumbVal, secondThumbVal);
  15320. settings.onMove.call(element, value, thumbVal, secondThumbVal);
  15321. }
  15322. });
  15323. },
  15324. rangeValue: function(first, second) {
  15325. if(module.is.range()) {
  15326. var
  15327. min = module.get.min(),
  15328. max = module.get.max()
  15329. ;
  15330. if (first <= min) {
  15331. first = min;
  15332. } else if(first >= max){
  15333. first = max;
  15334. }
  15335. if (second <= min) {
  15336. second = min;
  15337. } else if(second >= max){
  15338. second = max;
  15339. }
  15340. module.thumbVal = first;
  15341. module.secondThumbVal = second;
  15342. value = Math.abs(module.thumbVal - module.secondThumbVal);
  15343. module.update.position(module.thumbVal, $thumb);
  15344. module.update.position(module.secondThumbVal, $secondThumb);
  15345. if (!initialLoad || settings.fireOnInit) {
  15346. settings.onChange.call(element, value, module.thumbVal, module.secondThumbVal);
  15347. settings.onMove.call(element, value, module.thumbVal, module.secondThumbVal);
  15348. }
  15349. } else {
  15350. module.error(error.notrange);
  15351. }
  15352. },
  15353. position: function(position, which) {
  15354. var thumbVal = module.determine.value(position);
  15355. switch (which) {
  15356. case 'second':
  15357. module.secondThumbVal = thumbVal;
  15358. module.update.position(thumbVal, $secondThumb);
  15359. break;
  15360. default:
  15361. module.thumbVal = thumbVal;
  15362. module.update.position(thumbVal, $thumb);
  15363. }
  15364. value = Math.abs(module.thumbVal - (module.secondThumbVal || 0));
  15365. module.set.value(value);
  15366. }
  15367. },
  15368. update: {
  15369. value: function(newValue, callback) {
  15370. var
  15371. min = module.get.min(),
  15372. max = module.get.max()
  15373. ;
  15374. if (newValue <= min) {
  15375. newValue = min;
  15376. } else if(newValue >= max){
  15377. newValue = max;
  15378. }
  15379. if(!module.is.range()) {
  15380. value = newValue;
  15381. module.thumbVal = value;
  15382. } else {
  15383. if($currThumb === undefined) {
  15384. $currThumb = newValue <= module.get.currentThumbValue() ? $thumb : $secondThumb;
  15385. }
  15386. if(!$currThumb.hasClass('second')) {
  15387. if(settings.preventCrossover) {
  15388. newValue = Math.min(module.secondThumbVal, newValue);
  15389. }
  15390. module.thumbVal = newValue;
  15391. } else {
  15392. if(settings.preventCrossover) {
  15393. newValue = Math.max(module.thumbVal, newValue);
  15394. }
  15395. module.secondThumbVal = newValue;
  15396. }
  15397. value = Math.abs(module.thumbVal - module.secondThumbVal);
  15398. }
  15399. module.update.position(newValue);
  15400. module.debug('Setting slider value to ' + value);
  15401. if(typeof callback === 'function') {
  15402. callback(value, module.thumbVal, module.secondThumbVal);
  15403. }
  15404. },
  15405. position: function(newValue, $element) {
  15406. var
  15407. newPos = module.handleNewValuePosition(newValue),
  15408. $targetThumb = $element != undefined ? $element : $currThumb,
  15409. thumbVal = module.thumbVal || module.get.min(),
  15410. secondThumbVal = module.secondThumbVal || module.get.min()
  15411. ;
  15412. if(module.is.range()) {
  15413. if(!$targetThumb.hasClass('second')) {
  15414. position = newPos;
  15415. thumbVal = newValue;
  15416. } else {
  15417. secondPos = newPos;
  15418. secondThumbVal = newValue;
  15419. }
  15420. } else {
  15421. position = newPos;
  15422. thumbVal = newValue;
  15423. }
  15424. var
  15425. trackPosValue,
  15426. thumbPosValue,
  15427. min = module.get.min(),
  15428. max = module.get.max(),
  15429. thumbPosPercent = 100 * (newValue - min) / (max - min),
  15430. trackStartPosPercent = 100 * (Math.min(thumbVal, secondThumbVal) - min) / (max - min),
  15431. trackEndPosPercent = 100 * (1 - (Math.max(thumbVal, secondThumbVal) - min) / (max - min))
  15432. ;
  15433. if (module.is.vertical()) {
  15434. if (module.is.reversed()) {
  15435. thumbPosValue = {bottom: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', top: 'auto'};
  15436. trackPosValue = {bottom: trackStartPosPercent + '%', top: trackEndPosPercent + '%'};
  15437. }
  15438. else {
  15439. thumbPosValue = {top: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', bottom: 'auto'};
  15440. trackPosValue = {top: trackStartPosPercent + '%', bottom: trackEndPosPercent + '%'};
  15441. }
  15442. } else {
  15443. if (module.is.reversed()) {
  15444. thumbPosValue = {right: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', left: 'auto'};
  15445. trackPosValue = {right: trackStartPosPercent + '%', left: trackEndPosPercent + '%'};
  15446. }
  15447. else {
  15448. thumbPosValue = {left: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', right: 'auto'};
  15449. trackPosValue = {left: trackStartPosPercent + '%', right: trackEndPosPercent + '%'};
  15450. }
  15451. }
  15452. $targetThumb.css(thumbPosValue);
  15453. $trackFill.css(trackPosValue);
  15454. module.debug('Setting slider position to ' + newPos);
  15455. },
  15456. labelPosition: function (ratio, $label) {
  15457. var
  15458. startMargin = module.get.trackStartMargin(),
  15459. endMargin = module.get.trackEndMargin(),
  15460. posDir =
  15461. module.is.vertical()
  15462. ?
  15463. module.is.reversed() ? 'bottom' : 'top'
  15464. :
  15465. module.is.reversed() ? 'right' : 'left',
  15466. startMarginMod = module.is.reversed() && !module.is.vertical() ? ' - ' : ' + '
  15467. ;
  15468. var position = '(100% - ' + startMargin + ' - ' + endMargin + ') * ' + ratio;
  15469. $label.css(posDir, 'calc(' + position + startMarginMod + startMargin + ')');
  15470. }
  15471. },
  15472. goto: {
  15473. max: function() {
  15474. module.set.value(module.get.max());
  15475. },
  15476. min: function() {
  15477. module.set.value(module.get.min());
  15478. },
  15479. },
  15480. read: {
  15481. metadata: function() {
  15482. var
  15483. data = {
  15484. thumbVal : $module.data(metadata.thumbVal),
  15485. secondThumbVal : $module.data(metadata.secondThumbVal)
  15486. }
  15487. ;
  15488. if(data.thumbVal) {
  15489. if(module.is.range() && data.secondThumbVal) {
  15490. module.debug('Current value set from metadata', data.thumbVal, data.secondThumbVal);
  15491. module.set.rangeValue(data.thumbVal, data.secondThumbVal);
  15492. } else {
  15493. module.debug('Current value set from metadata', data.thumbVal);
  15494. module.set.value(data.thumbVal);
  15495. }
  15496. }
  15497. },
  15498. settings: function() {
  15499. if(settings.start !== false) {
  15500. if(module.is.range()) {
  15501. module.debug('Start position set from settings', settings.start, settings.end);
  15502. module.set.rangeValue(settings.start, settings.end);
  15503. } else {
  15504. module.debug('Start position set from settings', settings.start);
  15505. module.set.value(settings.start);
  15506. }
  15507. }
  15508. }
  15509. },
  15510. setting: function(name, value) {
  15511. module.debug('Changing setting', name, value);
  15512. if( $.isPlainObject(name) ) {
  15513. $.extend(true, settings, name);
  15514. }
  15515. else if(value !== undefined) {
  15516. if($.isPlainObject(settings[name])) {
  15517. $.extend(true, settings[name], value);
  15518. }
  15519. else {
  15520. settings[name] = value;
  15521. }
  15522. }
  15523. else {
  15524. return settings[name];
  15525. }
  15526. },
  15527. internal: function(name, value) {
  15528. if( $.isPlainObject(name) ) {
  15529. $.extend(true, module, name);
  15530. }
  15531. else if(value !== undefined) {
  15532. module[name] = value;
  15533. }
  15534. else {
  15535. return module[name];
  15536. }
  15537. },
  15538. debug: function() {
  15539. if(!settings.silent && settings.debug) {
  15540. if(settings.performance) {
  15541. module.performance.log(arguments);
  15542. }
  15543. else {
  15544. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15545. module.debug.apply(console, arguments);
  15546. }
  15547. }
  15548. },
  15549. verbose: function() {
  15550. if(!settings.silent && settings.verbose && settings.debug) {
  15551. if(settings.performance) {
  15552. module.performance.log(arguments);
  15553. }
  15554. else {
  15555. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15556. module.verbose.apply(console, arguments);
  15557. }
  15558. }
  15559. },
  15560. error: function() {
  15561. if(!settings.silent) {
  15562. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  15563. module.error.apply(console, arguments);
  15564. }
  15565. },
  15566. performance: {
  15567. log: function(message) {
  15568. var
  15569. currentTime,
  15570. executionTime,
  15571. previousTime
  15572. ;
  15573. if(settings.performance) {
  15574. currentTime = new Date().getTime();
  15575. previousTime = time || currentTime;
  15576. executionTime = currentTime - previousTime;
  15577. time = currentTime;
  15578. performance.push({
  15579. 'Name' : message[0],
  15580. 'Arguments' : [].slice.call(message, 1) || '',
  15581. 'Element' : element,
  15582. 'Execution Time' : executionTime
  15583. });
  15584. }
  15585. clearTimeout(module.performance.timer);
  15586. module.performance.timer = setTimeout(module.performance.display, 500);
  15587. },
  15588. display: function() {
  15589. var
  15590. title = settings.name + ':',
  15591. totalTime = 0
  15592. ;
  15593. time = false;
  15594. clearTimeout(module.performance.timer);
  15595. $.each(performance, function(index, data) {
  15596. totalTime += data['Execution Time'];
  15597. });
  15598. title += ' ' + totalTime + 'ms';
  15599. if(moduleSelector) {
  15600. title += ' \'' + moduleSelector + '\'';
  15601. }
  15602. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  15603. console.groupCollapsed(title);
  15604. if(console.table) {
  15605. console.table(performance);
  15606. }
  15607. else {
  15608. $.each(performance, function(index, data) {
  15609. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  15610. });
  15611. }
  15612. console.groupEnd();
  15613. }
  15614. performance = [];
  15615. }
  15616. },
  15617. invoke: function(query, passedArguments, context) {
  15618. var
  15619. object = instance,
  15620. maxDepth,
  15621. found,
  15622. response
  15623. ;
  15624. passedArguments = passedArguments || queryArguments;
  15625. context = element || context;
  15626. if(typeof query == 'string' && object !== undefined) {
  15627. query = query.split(/[\. ]/);
  15628. maxDepth = query.length - 1;
  15629. $.each(query, function(depth, value) {
  15630. var camelCaseValue = (depth != maxDepth)
  15631. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  15632. : query
  15633. ;
  15634. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  15635. object = object[camelCaseValue];
  15636. }
  15637. else if( object[camelCaseValue] !== undefined ) {
  15638. found = object[camelCaseValue];
  15639. return false;
  15640. }
  15641. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  15642. object = object[value];
  15643. }
  15644. else if( object[value] !== undefined ) {
  15645. found = object[value];
  15646. return false;
  15647. }
  15648. else {
  15649. module.error(error.method, query);
  15650. return false;
  15651. }
  15652. });
  15653. }
  15654. if ( $.isFunction( found ) ) {
  15655. response = found.apply(context, passedArguments);
  15656. }
  15657. else if(found !== undefined) {
  15658. response = found;
  15659. }
  15660. if($.isArray(returnedValue)) {
  15661. returnedValue.push(response);
  15662. }
  15663. else if(returnedValue !== undefined) {
  15664. returnedValue = [returnedValue, response];
  15665. }
  15666. else if(response !== undefined) {
  15667. returnedValue = response;
  15668. }
  15669. return found;
  15670. }
  15671. };
  15672. if(methodInvoked) {
  15673. if(instance === undefined) {
  15674. module.initialize();
  15675. }
  15676. module.invoke(query);
  15677. }
  15678. else {
  15679. if(instance !== undefined) {
  15680. instance.invoke('destroy');
  15681. }
  15682. module.initialize();
  15683. }
  15684. })
  15685. ;
  15686. return (returnedValue !== undefined)
  15687. ? returnedValue
  15688. : this
  15689. ;
  15690. };
  15691. $.fn.slider.settings = {
  15692. silent : false,
  15693. debug : false,
  15694. verbose : false,
  15695. performance : true,
  15696. name : 'Slider',
  15697. namespace : 'slider',
  15698. error : {
  15699. method : 'The method you called is not defined.',
  15700. notrange : 'This slider is not a range slider'
  15701. },
  15702. metadata: {
  15703. thumbVal : 'thumbVal',
  15704. secondThumbVal : 'secondThumbVal'
  15705. },
  15706. min : 0,
  15707. max : 20,
  15708. step : 1,
  15709. start : 0,
  15710. end : 20,
  15711. labelType : 'number',
  15712. showLabelTicks : false,
  15713. smooth : false,
  15714. autoAdjustLabels : true,
  15715. labelDistance : 100,
  15716. preventCrossover : true,
  15717. fireOnInit : false,
  15718. //the decimal place to round to if step is undefined
  15719. decimalPlaces : 2,
  15720. // page up/down multiplier. How many more times the steps to take on page up/down press
  15721. pageMultiplier : 2,
  15722. selector: {
  15723. },
  15724. className : {
  15725. reversed : 'reversed',
  15726. disabled : 'disabled',
  15727. labeled : 'labeled',
  15728. ticked : 'ticked',
  15729. vertical : 'vertical',
  15730. range : 'range',
  15731. smooth : 'smooth'
  15732. },
  15733. keys : {
  15734. pageUp : 33,
  15735. pageDown : 34,
  15736. leftArrow : 37,
  15737. upArrow : 38,
  15738. rightArrow : 39,
  15739. downArrow : 40
  15740. },
  15741. labelTypes : {
  15742. number : 'number',
  15743. letter : 'letter'
  15744. },
  15745. onChange : function(value, thumbVal, secondThumbVal){},
  15746. onMove : function(value, thumbVal, secondThumbVal){},
  15747. };
  15748. })( jQuery, window, document );
  15749. /*!
  15750. * # Fomantic-UI - Rating
  15751. * http://github.com/fomantic/Fomantic-UI/
  15752. *
  15753. *
  15754. * Released under the MIT license
  15755. * http://opensource.org/licenses/MIT
  15756. *
  15757. */
  15758. ;(function ($, window, document, undefined) {
  15759. 'use strict';
  15760. $.isFunction = $.isFunction || function(obj) {
  15761. return typeof obj === "function" && typeof obj.nodeType !== "number";
  15762. };
  15763. window = (typeof window != 'undefined' && window.Math == Math)
  15764. ? window
  15765. : (typeof self != 'undefined' && self.Math == Math)
  15766. ? self
  15767. : Function('return this')()
  15768. ;
  15769. $.fn.rating = function(parameters) {
  15770. var
  15771. $allModules = $(this),
  15772. moduleSelector = $allModules.selector || '',
  15773. time = new Date().getTime(),
  15774. performance = [],
  15775. query = arguments[0],
  15776. methodInvoked = (typeof query == 'string'),
  15777. queryArguments = [].slice.call(arguments, 1),
  15778. returnedValue
  15779. ;
  15780. $allModules
  15781. .each(function() {
  15782. var
  15783. settings = ( $.isPlainObject(parameters) )
  15784. ? $.extend(true, {}, $.fn.rating.settings, parameters)
  15785. : $.extend({}, $.fn.rating.settings),
  15786. namespace = settings.namespace,
  15787. className = settings.className,
  15788. metadata = settings.metadata,
  15789. selector = settings.selector,
  15790. cssVars = settings.cssVars,
  15791. eventNamespace = '.' + namespace,
  15792. moduleNamespace = 'module-' + namespace,
  15793. element = this,
  15794. instance = $(this).data(moduleNamespace),
  15795. $module = $(this),
  15796. $icon = $module.find(selector.icon),
  15797. initialLoad,
  15798. module
  15799. ;
  15800. module = {
  15801. initialize: function() {
  15802. module.verbose('Initializing rating module', settings);
  15803. if($icon.length === 0) {
  15804. module.setup.layout();
  15805. }
  15806. if(settings.interactive && !module.is.disabled()) {
  15807. module.enable();
  15808. }
  15809. else {
  15810. module.disable();
  15811. }
  15812. module.set.initialLoad();
  15813. module.set.rating( module.get.initialRating() );
  15814. module.remove.initialLoad();
  15815. module.instantiate();
  15816. },
  15817. instantiate: function() {
  15818. module.verbose('Instantiating module', settings);
  15819. instance = module;
  15820. $module
  15821. .data(moduleNamespace, module)
  15822. ;
  15823. },
  15824. destroy: function() {
  15825. module.verbose('Destroying previous instance', instance);
  15826. module.remove.events();
  15827. $module
  15828. .removeData(moduleNamespace)
  15829. ;
  15830. },
  15831. refresh: function() {
  15832. $icon = $module.find(selector.icon);
  15833. },
  15834. setup: {
  15835. layout: function() {
  15836. var
  15837. maxRating = module.get.maxRating(),
  15838. icon = module.get.icon(),
  15839. html = $.fn.rating.settings.templates.icon(maxRating, icon)
  15840. ;
  15841. module.debug('Generating icon html dynamically');
  15842. $module
  15843. .html(html)
  15844. ;
  15845. module.refresh();
  15846. }
  15847. },
  15848. event: {
  15849. mouseenter: function() {
  15850. var
  15851. $activeIcon = $(this)
  15852. ;
  15853. $activeIcon
  15854. .nextAll()
  15855. .removeClass(className.selected)
  15856. ;
  15857. $module
  15858. .addClass(className.selected)
  15859. ;
  15860. $activeIcon
  15861. .addClass(className.selected)
  15862. .prevAll()
  15863. .addClass(className.selected)
  15864. ;
  15865. },
  15866. mouseleave: function() {
  15867. $module
  15868. .removeClass(className.selected)
  15869. ;
  15870. $icon
  15871. .removeClass(className.selected)
  15872. ;
  15873. },
  15874. click: function() {
  15875. var
  15876. $activeIcon = $(this),
  15877. currentRating = module.get.rating(),
  15878. rating = $icon.index($activeIcon) + 1,
  15879. canClear = (settings.clearable == 'auto')
  15880. ? ($icon.length === 1)
  15881. : settings.clearable
  15882. ;
  15883. if(canClear && currentRating == rating) {
  15884. module.clearRating();
  15885. }
  15886. else {
  15887. module.set.rating( rating );
  15888. }
  15889. }
  15890. },
  15891. clearRating: function() {
  15892. module.debug('Clearing current rating');
  15893. module.set.rating(0);
  15894. },
  15895. bind: {
  15896. events: function() {
  15897. module.verbose('Binding events');
  15898. $module
  15899. .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
  15900. .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
  15901. .on('click' + eventNamespace, selector.icon, module.event.click)
  15902. ;
  15903. }
  15904. },
  15905. remove: {
  15906. events: function() {
  15907. module.verbose('Removing events');
  15908. $module
  15909. .off(eventNamespace)
  15910. ;
  15911. },
  15912. initialLoad: function() {
  15913. initialLoad = false;
  15914. }
  15915. },
  15916. enable: function() {
  15917. module.debug('Setting rating to interactive mode');
  15918. module.bind.events();
  15919. $module
  15920. .removeClass(className.disabled)
  15921. ;
  15922. },
  15923. disable: function() {
  15924. module.debug('Setting rating to read-only mode');
  15925. module.remove.events();
  15926. $module
  15927. .addClass(className.disabled)
  15928. ;
  15929. },
  15930. is: {
  15931. initialLoad: function() {
  15932. return initialLoad;
  15933. },
  15934. disabled: function() {
  15935. return $module.hasClass(className.disabled);
  15936. }
  15937. },
  15938. get: {
  15939. icon: function(){
  15940. var icon = $module.data(metadata.icon);
  15941. if (icon) {
  15942. $module.removeData(metadata.icon);
  15943. }
  15944. return icon || settings.icon;
  15945. },
  15946. initialRating: function() {
  15947. if($module.data(metadata.rating) !== undefined) {
  15948. $module.removeData(metadata.rating);
  15949. return $module.data(metadata.rating);
  15950. }
  15951. return settings.initialRating;
  15952. },
  15953. maxRating: function() {
  15954. if($module.data(metadata.maxRating) !== undefined) {
  15955. $module.removeData(metadata.maxRating);
  15956. return $module.data(metadata.maxRating);
  15957. }
  15958. return settings.maxRating;
  15959. },
  15960. rating: function() {
  15961. var
  15962. currentRating = $icon.filter('.' + className.active).length
  15963. ;
  15964. module.verbose('Current rating retrieved', currentRating);
  15965. return currentRating;
  15966. }
  15967. },
  15968. set: {
  15969. rating: function(rating) {
  15970. var
  15971. ratingIndex = Math.floor(
  15972. (rating - 1 >= 0)
  15973. ? (rating - 1)
  15974. : 0
  15975. ),
  15976. $activeIcon = $icon.eq(ratingIndex),
  15977. $partialActiveIcon = rating <= 1
  15978. ? $activeIcon
  15979. : $activeIcon.next()
  15980. ,
  15981. filledPercentage = (rating % 1) * 100
  15982. ;
  15983. $module
  15984. .removeClass(className.selected)
  15985. ;
  15986. $icon
  15987. .removeClass(className.selected)
  15988. .removeClass(className.active)
  15989. .removeClass(className.partiallyActive)
  15990. ;
  15991. if(rating > 0) {
  15992. module.verbose('Setting current rating to', rating);
  15993. $activeIcon
  15994. .prevAll()
  15995. .addBack()
  15996. .addClass(className.active)
  15997. ;
  15998. if($activeIcon.next() && rating % 1 !== 0) {
  15999. $partialActiveIcon
  16000. .addClass(className.partiallyActive)
  16001. .addClass(className.active)
  16002. ;
  16003. $partialActiveIcon
  16004. .css(cssVars.filledCustomPropName, filledPercentage + '%')
  16005. ;
  16006. if($partialActiveIcon.css('backgroundColor') === 'transparent') {
  16007. $partialActiveIcon
  16008. .removeClass(className.partiallyActive)
  16009. .removeClass(className.active)
  16010. ;
  16011. }
  16012. }
  16013. }
  16014. if(!module.is.initialLoad()) {
  16015. settings.onRate.call(element, rating);
  16016. }
  16017. },
  16018. initialLoad: function() {
  16019. initialLoad = true;
  16020. }
  16021. },
  16022. setting: function(name, value) {
  16023. module.debug('Changing setting', name, value);
  16024. if( $.isPlainObject(name) ) {
  16025. $.extend(true, settings, name);
  16026. }
  16027. else if(value !== undefined) {
  16028. if($.isPlainObject(settings[name])) {
  16029. $.extend(true, settings[name], value);
  16030. }
  16031. else {
  16032. settings[name] = value;
  16033. }
  16034. }
  16035. else {
  16036. return settings[name];
  16037. }
  16038. },
  16039. internal: function(name, value) {
  16040. if( $.isPlainObject(name) ) {
  16041. $.extend(true, module, name);
  16042. }
  16043. else if(value !== undefined) {
  16044. module[name] = value;
  16045. }
  16046. else {
  16047. return module[name];
  16048. }
  16049. },
  16050. debug: function() {
  16051. if(!settings.silent && settings.debug) {
  16052. if(settings.performance) {
  16053. module.performance.log(arguments);
  16054. }
  16055. else {
  16056. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16057. module.debug.apply(console, arguments);
  16058. }
  16059. }
  16060. },
  16061. verbose: function() {
  16062. if(!settings.silent && settings.verbose && settings.debug) {
  16063. if(settings.performance) {
  16064. module.performance.log(arguments);
  16065. }
  16066. else {
  16067. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16068. module.verbose.apply(console, arguments);
  16069. }
  16070. }
  16071. },
  16072. error: function() {
  16073. if(!settings.silent) {
  16074. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  16075. module.error.apply(console, arguments);
  16076. }
  16077. },
  16078. performance: {
  16079. log: function(message) {
  16080. var
  16081. currentTime,
  16082. executionTime,
  16083. previousTime
  16084. ;
  16085. if(settings.performance) {
  16086. currentTime = new Date().getTime();
  16087. previousTime = time || currentTime;
  16088. executionTime = currentTime - previousTime;
  16089. time = currentTime;
  16090. performance.push({
  16091. 'Name' : message[0],
  16092. 'Arguments' : [].slice.call(message, 1) || '',
  16093. 'Element' : element,
  16094. 'Execution Time' : executionTime
  16095. });
  16096. }
  16097. clearTimeout(module.performance.timer);
  16098. module.performance.timer = setTimeout(module.performance.display, 500);
  16099. },
  16100. display: function() {
  16101. var
  16102. title = settings.name + ':',
  16103. totalTime = 0
  16104. ;
  16105. time = false;
  16106. clearTimeout(module.performance.timer);
  16107. $.each(performance, function(index, data) {
  16108. totalTime += data['Execution Time'];
  16109. });
  16110. title += ' ' + totalTime + 'ms';
  16111. if(moduleSelector) {
  16112. title += ' \'' + moduleSelector + '\'';
  16113. }
  16114. if($allModules.length > 1) {
  16115. title += ' ' + '(' + $allModules.length + ')';
  16116. }
  16117. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  16118. console.groupCollapsed(title);
  16119. if(console.table) {
  16120. console.table(performance);
  16121. }
  16122. else {
  16123. $.each(performance, function(index, data) {
  16124. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  16125. });
  16126. }
  16127. console.groupEnd();
  16128. }
  16129. performance = [];
  16130. }
  16131. },
  16132. invoke: function(query, passedArguments, context) {
  16133. var
  16134. object = instance,
  16135. maxDepth,
  16136. found,
  16137. response
  16138. ;
  16139. passedArguments = passedArguments || queryArguments;
  16140. context = element || context;
  16141. if(typeof query == 'string' && object !== undefined) {
  16142. query = query.split(/[\. ]/);
  16143. maxDepth = query.length - 1;
  16144. $.each(query, function(depth, value) {
  16145. var camelCaseValue = (depth != maxDepth)
  16146. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  16147. : query
  16148. ;
  16149. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  16150. object = object[camelCaseValue];
  16151. }
  16152. else if( object[camelCaseValue] !== undefined ) {
  16153. found = object[camelCaseValue];
  16154. return false;
  16155. }
  16156. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  16157. object = object[value];
  16158. }
  16159. else if( object[value] !== undefined ) {
  16160. found = object[value];
  16161. return false;
  16162. }
  16163. else {
  16164. return false;
  16165. }
  16166. });
  16167. }
  16168. if ( $.isFunction( found ) ) {
  16169. response = found.apply(context, passedArguments);
  16170. }
  16171. else if(found !== undefined) {
  16172. response = found;
  16173. }
  16174. if(Array.isArray(returnedValue)) {
  16175. returnedValue.push(response);
  16176. }
  16177. else if(returnedValue !== undefined) {
  16178. returnedValue = [returnedValue, response];
  16179. }
  16180. else if(response !== undefined) {
  16181. returnedValue = response;
  16182. }
  16183. return found;
  16184. }
  16185. };
  16186. if(methodInvoked) {
  16187. if(instance === undefined) {
  16188. module.initialize();
  16189. }
  16190. module.invoke(query);
  16191. }
  16192. else {
  16193. if(instance !== undefined) {
  16194. instance.invoke('destroy');
  16195. }
  16196. module.initialize();
  16197. }
  16198. })
  16199. ;
  16200. return (returnedValue !== undefined)
  16201. ? returnedValue
  16202. : this
  16203. ;
  16204. };
  16205. $.fn.rating.settings = {
  16206. name : 'Rating',
  16207. namespace : 'rating',
  16208. icon : 'star',
  16209. silent : false,
  16210. debug : false,
  16211. verbose : false,
  16212. performance : true,
  16213. initialRating : 0,
  16214. interactive : true,
  16215. maxRating : 4,
  16216. clearable : 'auto',
  16217. fireOnInit : false,
  16218. onRate : function(rating){},
  16219. error : {
  16220. method : 'The method you called is not defined',
  16221. noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
  16222. },
  16223. metadata: {
  16224. rating : 'rating',
  16225. maxRating : 'maxRating',
  16226. icon : 'icon'
  16227. },
  16228. className : {
  16229. active : 'active',
  16230. disabled : 'disabled',
  16231. selected : 'selected',
  16232. loading : 'loading',
  16233. partiallyActive : 'partial'
  16234. },
  16235. cssVars : {
  16236. filledCustomPropName : '--full'
  16237. },
  16238. selector : {
  16239. icon : '.icon'
  16240. },
  16241. templates: {
  16242. icon: function(maxRating, iconClass) {
  16243. var
  16244. icon = 1,
  16245. html = ''
  16246. ;
  16247. while(icon <= maxRating) {
  16248. html += '<i class="'+iconClass+' icon"></i>';
  16249. icon++;
  16250. }
  16251. return html;
  16252. }
  16253. }
  16254. };
  16255. })( jQuery, window, document );
  16256. /*!
  16257. * # Fomantic-UI - Search
  16258. * http://github.com/fomantic/Fomantic-UI/
  16259. *
  16260. *
  16261. * Released under the MIT license
  16262. * http://opensource.org/licenses/MIT
  16263. *
  16264. */
  16265. ;(function ($, window, document, undefined) {
  16266. 'use strict';
  16267. $.isFunction = $.isFunction || function(obj) {
  16268. return typeof obj === "function" && typeof obj.nodeType !== "number";
  16269. };
  16270. window = (typeof window != 'undefined' && window.Math == Math)
  16271. ? window
  16272. : (typeof self != 'undefined' && self.Math == Math)
  16273. ? self
  16274. : Function('return this')()
  16275. ;
  16276. $.fn.search = function(parameters) {
  16277. var
  16278. $allModules = $(this),
  16279. moduleSelector = $allModules.selector || '',
  16280. time = new Date().getTime(),
  16281. performance = [],
  16282. query = arguments[0],
  16283. methodInvoked = (typeof query == 'string'),
  16284. queryArguments = [].slice.call(arguments, 1),
  16285. returnedValue
  16286. ;
  16287. $(this)
  16288. .each(function() {
  16289. var
  16290. settings = ( $.isPlainObject(parameters) )
  16291. ? $.extend(true, {}, $.fn.search.settings, parameters)
  16292. : $.extend({}, $.fn.search.settings),
  16293. className = settings.className,
  16294. metadata = settings.metadata,
  16295. regExp = settings.regExp,
  16296. fields = settings.fields,
  16297. selector = settings.selector,
  16298. error = settings.error,
  16299. namespace = settings.namespace,
  16300. eventNamespace = '.' + namespace,
  16301. moduleNamespace = namespace + '-module',
  16302. $module = $(this),
  16303. $prompt = $module.find(selector.prompt),
  16304. $searchButton = $module.find(selector.searchButton),
  16305. $results = $module.find(selector.results),
  16306. $result = $module.find(selector.result),
  16307. $category = $module.find(selector.category),
  16308. element = this,
  16309. instance = $module.data(moduleNamespace),
  16310. disabledBubbled = false,
  16311. resultsDismissed = false,
  16312. module
  16313. ;
  16314. module = {
  16315. initialize: function() {
  16316. module.verbose('Initializing module');
  16317. module.get.settings();
  16318. module.determine.searchFields();
  16319. module.bind.events();
  16320. module.set.type();
  16321. module.create.results();
  16322. module.instantiate();
  16323. },
  16324. instantiate: function() {
  16325. module.verbose('Storing instance of module', module);
  16326. instance = module;
  16327. $module
  16328. .data(moduleNamespace, module)
  16329. ;
  16330. },
  16331. destroy: function() {
  16332. module.verbose('Destroying instance');
  16333. $module
  16334. .off(eventNamespace)
  16335. .removeData(moduleNamespace)
  16336. ;
  16337. },
  16338. refresh: function() {
  16339. module.debug('Refreshing selector cache');
  16340. $prompt = $module.find(selector.prompt);
  16341. $searchButton = $module.find(selector.searchButton);
  16342. $category = $module.find(selector.category);
  16343. $results = $module.find(selector.results);
  16344. $result = $module.find(selector.result);
  16345. },
  16346. refreshResults: function() {
  16347. $results = $module.find(selector.results);
  16348. $result = $module.find(selector.result);
  16349. },
  16350. bind: {
  16351. events: function() {
  16352. module.verbose('Binding events to search');
  16353. if(settings.automatic) {
  16354. $module
  16355. .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
  16356. ;
  16357. $prompt
  16358. .attr('autocomplete', 'off')
  16359. ;
  16360. }
  16361. $module
  16362. // prompt
  16363. .on('focus' + eventNamespace, selector.prompt, module.event.focus)
  16364. .on('blur' + eventNamespace, selector.prompt, module.event.blur)
  16365. .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
  16366. // search button
  16367. .on('click' + eventNamespace, selector.searchButton, module.query)
  16368. // results
  16369. .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
  16370. .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
  16371. .on('click' + eventNamespace, selector.result, module.event.result.click)
  16372. ;
  16373. }
  16374. },
  16375. determine: {
  16376. searchFields: function() {
  16377. // this makes sure $.extend does not add specified search fields to default fields
  16378. // this is the only setting which should not extend defaults
  16379. if(parameters && parameters.searchFields !== undefined) {
  16380. settings.searchFields = parameters.searchFields;
  16381. }
  16382. }
  16383. },
  16384. event: {
  16385. input: function() {
  16386. if(settings.searchDelay) {
  16387. clearTimeout(module.timer);
  16388. module.timer = setTimeout(function() {
  16389. if(module.is.focused()) {
  16390. module.query();
  16391. }
  16392. }, settings.searchDelay);
  16393. }
  16394. else {
  16395. module.query();
  16396. }
  16397. },
  16398. focus: function() {
  16399. module.set.focus();
  16400. if(settings.searchOnFocus && module.has.minimumCharacters() ) {
  16401. module.query(function() {
  16402. if(module.can.show() ) {
  16403. module.showResults();
  16404. }
  16405. });
  16406. }
  16407. },
  16408. blur: function(event) {
  16409. var
  16410. pageLostFocus = (document.activeElement === this),
  16411. callback = function() {
  16412. module.cancel.query();
  16413. module.remove.focus();
  16414. module.timer = setTimeout(module.hideResults, settings.hideDelay);
  16415. }
  16416. ;
  16417. if(pageLostFocus) {
  16418. return;
  16419. }
  16420. resultsDismissed = false;
  16421. if(module.resultsClicked) {
  16422. module.debug('Determining if user action caused search to close');
  16423. $module
  16424. .one('click.close' + eventNamespace, selector.results, function(event) {
  16425. if(module.is.inMessage(event) || disabledBubbled) {
  16426. $prompt.focus();
  16427. return;
  16428. }
  16429. disabledBubbled = false;
  16430. if( !module.is.animating() && !module.is.hidden()) {
  16431. callback();
  16432. }
  16433. })
  16434. ;
  16435. }
  16436. else {
  16437. module.debug('Input blurred without user action, closing results');
  16438. callback();
  16439. }
  16440. },
  16441. result: {
  16442. mousedown: function() {
  16443. module.resultsClicked = true;
  16444. },
  16445. mouseup: function() {
  16446. module.resultsClicked = false;
  16447. },
  16448. click: function(event) {
  16449. module.debug('Search result selected');
  16450. var
  16451. $result = $(this),
  16452. $title = $result.find(selector.title).eq(0),
  16453. $link = $result.is('a[href]')
  16454. ? $result
  16455. : $result.find('a[href]').eq(0),
  16456. href = $link.attr('href') || false,
  16457. target = $link.attr('target') || false,
  16458. // title is used for result lookup
  16459. value = ($title.length > 0)
  16460. ? $title.text()
  16461. : false,
  16462. results = module.get.results(),
  16463. result = $result.data(metadata.result) || module.get.result(value, results)
  16464. ;
  16465. if(value) {
  16466. module.set.value(value);
  16467. }
  16468. if( $.isFunction(settings.onSelect) ) {
  16469. if(settings.onSelect.call(element, result, results) === false) {
  16470. module.debug('Custom onSelect callback cancelled default select action');
  16471. disabledBubbled = true;
  16472. return;
  16473. }
  16474. }
  16475. module.hideResults();
  16476. if(href) {
  16477. module.verbose('Opening search link found in result', $link);
  16478. if(target == '_blank' || event.ctrlKey) {
  16479. window.open(href);
  16480. }
  16481. else {
  16482. window.location.href = (href);
  16483. }
  16484. }
  16485. }
  16486. }
  16487. },
  16488. handleKeyboard: function(event) {
  16489. var
  16490. // force selector refresh
  16491. $result = $module.find(selector.result),
  16492. $category = $module.find(selector.category),
  16493. $activeResult = $result.filter('.' + className.active),
  16494. currentIndex = $result.index( $activeResult ),
  16495. resultSize = $result.length,
  16496. hasActiveResult = $activeResult.length > 0,
  16497. keyCode = event.which,
  16498. keys = {
  16499. backspace : 8,
  16500. enter : 13,
  16501. escape : 27,
  16502. upArrow : 38,
  16503. downArrow : 40
  16504. },
  16505. newIndex
  16506. ;
  16507. // search shortcuts
  16508. if(keyCode == keys.escape) {
  16509. module.verbose('Escape key pressed, blurring search field');
  16510. module.hideResults();
  16511. resultsDismissed = true;
  16512. }
  16513. if( module.is.visible() ) {
  16514. if(keyCode == keys.enter) {
  16515. module.verbose('Enter key pressed, selecting active result');
  16516. if( $result.filter('.' + className.active).length > 0 ) {
  16517. module.event.result.click.call($result.filter('.' + className.active), event);
  16518. event.preventDefault();
  16519. return false;
  16520. }
  16521. }
  16522. else if(keyCode == keys.upArrow && hasActiveResult) {
  16523. module.verbose('Up key pressed, changing active result');
  16524. newIndex = (currentIndex - 1 < 0)
  16525. ? currentIndex
  16526. : currentIndex - 1
  16527. ;
  16528. $category
  16529. .removeClass(className.active)
  16530. ;
  16531. $result
  16532. .removeClass(className.active)
  16533. .eq(newIndex)
  16534. .addClass(className.active)
  16535. .closest($category)
  16536. .addClass(className.active)
  16537. ;
  16538. event.preventDefault();
  16539. }
  16540. else if(keyCode == keys.downArrow) {
  16541. module.verbose('Down key pressed, changing active result');
  16542. newIndex = (currentIndex + 1 >= resultSize)
  16543. ? currentIndex
  16544. : currentIndex + 1
  16545. ;
  16546. $category
  16547. .removeClass(className.active)
  16548. ;
  16549. $result
  16550. .removeClass(className.active)
  16551. .eq(newIndex)
  16552. .addClass(className.active)
  16553. .closest($category)
  16554. .addClass(className.active)
  16555. ;
  16556. event.preventDefault();
  16557. }
  16558. }
  16559. else {
  16560. // query shortcuts
  16561. if(keyCode == keys.enter) {
  16562. module.verbose('Enter key pressed, executing query');
  16563. module.query();
  16564. module.set.buttonPressed();
  16565. $prompt.one('keyup', module.remove.buttonFocus);
  16566. }
  16567. }
  16568. },
  16569. setup: {
  16570. api: function(searchTerm, callback) {
  16571. var
  16572. apiSettings = {
  16573. debug : settings.debug,
  16574. on : false,
  16575. cache : settings.cache,
  16576. action : 'search',
  16577. urlData : {
  16578. query : searchTerm
  16579. },
  16580. onSuccess : function(response) {
  16581. module.parse.response.call(element, response, searchTerm);
  16582. callback();
  16583. },
  16584. onFailure : function() {
  16585. module.displayMessage(error.serverError);
  16586. callback();
  16587. },
  16588. onAbort : function(response) {
  16589. },
  16590. onError : module.error
  16591. }
  16592. ;
  16593. $.extend(true, apiSettings, settings.apiSettings);
  16594. module.verbose('Setting up API request', apiSettings);
  16595. $module.api(apiSettings);
  16596. }
  16597. },
  16598. can: {
  16599. useAPI: function() {
  16600. return $.fn.api !== undefined;
  16601. },
  16602. show: function() {
  16603. return module.is.focused() && !module.is.visible() && !module.is.empty();
  16604. },
  16605. transition: function() {
  16606. return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
  16607. }
  16608. },
  16609. is: {
  16610. animating: function() {
  16611. return $results.hasClass(className.animating);
  16612. },
  16613. hidden: function() {
  16614. return $results.hasClass(className.hidden);
  16615. },
  16616. inMessage: function(event) {
  16617. if(!event.target) {
  16618. return;
  16619. }
  16620. var
  16621. $target = $(event.target),
  16622. isInDOM = $.contains(document.documentElement, event.target)
  16623. ;
  16624. return (isInDOM && $target.closest(selector.message).length > 0);
  16625. },
  16626. empty: function() {
  16627. return ($results.html() === '');
  16628. },
  16629. visible: function() {
  16630. return ($results.filter(':visible').length > 0);
  16631. },
  16632. focused: function() {
  16633. return ($prompt.filter(':focus').length > 0);
  16634. }
  16635. },
  16636. get: {
  16637. settings: function() {
  16638. if($.isPlainObject(parameters) && parameters.searchFullText) {
  16639. settings.fullTextSearch = parameters.searchFullText;
  16640. module.error(settings.error.oldSearchSyntax, element);
  16641. }
  16642. if (settings.ignoreDiacritics && !String.prototype.normalize) {
  16643. settings.ignoreDiacritics = false;
  16644. module.error(error.noNormalize, element);
  16645. }
  16646. },
  16647. inputEvent: function() {
  16648. var
  16649. prompt = $prompt[0],
  16650. inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
  16651. ? 'input'
  16652. : (prompt !== undefined && prompt.onpropertychange !== undefined)
  16653. ? 'propertychange'
  16654. : 'keyup'
  16655. ;
  16656. return inputEvent;
  16657. },
  16658. value: function() {
  16659. return $prompt.val();
  16660. },
  16661. results: function() {
  16662. var
  16663. results = $module.data(metadata.results)
  16664. ;
  16665. return results;
  16666. },
  16667. result: function(value, results) {
  16668. var
  16669. result = false
  16670. ;
  16671. value = (value !== undefined)
  16672. ? value
  16673. : module.get.value()
  16674. ;
  16675. results = (results !== undefined)
  16676. ? results
  16677. : module.get.results()
  16678. ;
  16679. if(settings.type === 'category') {
  16680. module.debug('Finding result that matches', value);
  16681. $.each(results, function(index, category) {
  16682. if(Array.isArray(category.results)) {
  16683. result = module.search.object(value, category.results)[0];
  16684. // don't continue searching if a result is found
  16685. if(result) {
  16686. return false;
  16687. }
  16688. }
  16689. });
  16690. }
  16691. else {
  16692. module.debug('Finding result in results object', value);
  16693. result = module.search.object(value, results)[0];
  16694. }
  16695. return result || false;
  16696. },
  16697. },
  16698. select: {
  16699. firstResult: function() {
  16700. module.verbose('Selecting first result');
  16701. $result.first().addClass(className.active);
  16702. }
  16703. },
  16704. set: {
  16705. focus: function() {
  16706. $module.addClass(className.focus);
  16707. },
  16708. loading: function() {
  16709. $module.addClass(className.loading);
  16710. },
  16711. value: function(value) {
  16712. module.verbose('Setting search input value', value);
  16713. $prompt
  16714. .val(value)
  16715. ;
  16716. },
  16717. type: function(type) {
  16718. type = type || settings.type;
  16719. if(settings.type == 'category') {
  16720. $module.addClass(settings.type);
  16721. }
  16722. },
  16723. buttonPressed: function() {
  16724. $searchButton.addClass(className.pressed);
  16725. }
  16726. },
  16727. remove: {
  16728. loading: function() {
  16729. $module.removeClass(className.loading);
  16730. },
  16731. focus: function() {
  16732. $module.removeClass(className.focus);
  16733. },
  16734. buttonPressed: function() {
  16735. $searchButton.removeClass(className.pressed);
  16736. },
  16737. diacritics: function(text) {
  16738. return settings.ignoreDiacritics ? text.normalize('NFD').replace(/[\u0300-\u036f]/g, '') : text;
  16739. }
  16740. },
  16741. query: function(callback) {
  16742. callback = $.isFunction(callback)
  16743. ? callback
  16744. : function(){}
  16745. ;
  16746. var
  16747. searchTerm = module.get.value(),
  16748. cache = module.read.cache(searchTerm)
  16749. ;
  16750. callback = callback || function() {};
  16751. if( module.has.minimumCharacters() ) {
  16752. if(cache) {
  16753. module.debug('Reading result from cache', searchTerm);
  16754. module.save.results(cache.results);
  16755. module.addResults(cache.html);
  16756. module.inject.id(cache.results);
  16757. callback();
  16758. }
  16759. else {
  16760. module.debug('Querying for', searchTerm);
  16761. if($.isPlainObject(settings.source) || Array.isArray(settings.source)) {
  16762. module.search.local(searchTerm);
  16763. callback();
  16764. }
  16765. else if( module.can.useAPI() ) {
  16766. module.search.remote(searchTerm, callback);
  16767. }
  16768. else {
  16769. module.error(error.source);
  16770. callback();
  16771. }
  16772. }
  16773. settings.onSearchQuery.call(element, searchTerm);
  16774. }
  16775. else {
  16776. module.hideResults();
  16777. }
  16778. },
  16779. search: {
  16780. local: function(searchTerm) {
  16781. var
  16782. results = module.search.object(searchTerm, settings.source),
  16783. searchHTML
  16784. ;
  16785. module.set.loading();
  16786. module.save.results(results);
  16787. module.debug('Returned full local search results', results);
  16788. if(settings.maxResults > 0) {
  16789. module.debug('Using specified max results', results);
  16790. results = results.slice(0, settings.maxResults);
  16791. }
  16792. if(settings.type == 'category') {
  16793. results = module.create.categoryResults(results);
  16794. }
  16795. searchHTML = module.generateResults({
  16796. results: results
  16797. });
  16798. module.remove.loading();
  16799. module.addResults(searchHTML);
  16800. module.inject.id(results);
  16801. module.write.cache(searchTerm, {
  16802. html : searchHTML,
  16803. results : results
  16804. });
  16805. },
  16806. remote: function(searchTerm, callback) {
  16807. callback = $.isFunction(callback)
  16808. ? callback
  16809. : function(){}
  16810. ;
  16811. if($module.api('is loading')) {
  16812. $module.api('abort');
  16813. }
  16814. module.setup.api(searchTerm, callback);
  16815. $module
  16816. .api('query')
  16817. ;
  16818. },
  16819. object: function(searchTerm, source, searchFields) {
  16820. searchTerm = module.remove.diacritics(String(searchTerm));
  16821. var
  16822. results = [],
  16823. exactResults = [],
  16824. fuzzyResults = [],
  16825. searchExp = searchTerm.replace(regExp.escape, '\\$&'),
  16826. matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
  16827. // avoid duplicates when pushing results
  16828. addResult = function(array, result) {
  16829. var
  16830. notResult = ($.inArray(result, results) == -1),
  16831. notFuzzyResult = ($.inArray(result, fuzzyResults) == -1),
  16832. notExactResults = ($.inArray(result, exactResults) == -1)
  16833. ;
  16834. if(notResult && notFuzzyResult && notExactResults) {
  16835. array.push(result);
  16836. }
  16837. }
  16838. ;
  16839. source = source || settings.source;
  16840. searchFields = (searchFields !== undefined)
  16841. ? searchFields
  16842. : settings.searchFields
  16843. ;
  16844. // search fields should be array to loop correctly
  16845. if(!Array.isArray(searchFields)) {
  16846. searchFields = [searchFields];
  16847. }
  16848. // exit conditions if no source
  16849. if(source === undefined || source === false) {
  16850. module.error(error.source);
  16851. return [];
  16852. }
  16853. // iterate through search fields looking for matches
  16854. $.each(searchFields, function(index, field) {
  16855. $.each(source, function(label, content) {
  16856. var
  16857. fieldExists = (typeof content[field] == 'string') || (typeof content[field] == 'number')
  16858. ;
  16859. if(fieldExists) {
  16860. var text;
  16861. if (typeof content[field] === 'string'){
  16862. text = module.remove.diacritics(content[field]);
  16863. } else {
  16864. text = content[field].toString();
  16865. }
  16866. if( text.search(matchRegExp) !== -1) {
  16867. // content starts with value (first in results)
  16868. addResult(results, content);
  16869. }
  16870. else if(settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text) ) {
  16871. // content fuzzy matches (last in results)
  16872. addResult(exactResults, content);
  16873. }
  16874. else if(settings.fullTextSearch == true && module.fuzzySearch(searchTerm, text) ) {
  16875. // content fuzzy matches (last in results)
  16876. addResult(fuzzyResults, content);
  16877. }
  16878. }
  16879. });
  16880. });
  16881. $.merge(exactResults, fuzzyResults);
  16882. $.merge(results, exactResults);
  16883. return results;
  16884. }
  16885. },
  16886. exactSearch: function (query, term) {
  16887. query = query.toLowerCase();
  16888. term = term.toLowerCase();
  16889. return term.indexOf(query) > -1;
  16890. },
  16891. fuzzySearch: function(query, term) {
  16892. var
  16893. termLength = term.length,
  16894. queryLength = query.length
  16895. ;
  16896. if(typeof query !== 'string') {
  16897. return false;
  16898. }
  16899. query = query.toLowerCase();
  16900. term = term.toLowerCase();
  16901. if(queryLength > termLength) {
  16902. return false;
  16903. }
  16904. if(queryLength === termLength) {
  16905. return (query === term);
  16906. }
  16907. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  16908. var
  16909. queryCharacter = query.charCodeAt(characterIndex)
  16910. ;
  16911. while(nextCharacterIndex < termLength) {
  16912. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  16913. continue search;
  16914. }
  16915. }
  16916. return false;
  16917. }
  16918. return true;
  16919. },
  16920. parse: {
  16921. response: function(response, searchTerm) {
  16922. if(Array.isArray(response)){
  16923. var o={};
  16924. o[fields.results]=response;
  16925. response = o;
  16926. }
  16927. var
  16928. searchHTML = module.generateResults(response)
  16929. ;
  16930. module.verbose('Parsing server response', response);
  16931. if(response !== undefined) {
  16932. if(searchTerm !== undefined && response[fields.results] !== undefined) {
  16933. module.addResults(searchHTML);
  16934. module.inject.id(response[fields.results]);
  16935. module.write.cache(searchTerm, {
  16936. html : searchHTML,
  16937. results : response[fields.results]
  16938. });
  16939. module.save.results(response[fields.results]);
  16940. }
  16941. }
  16942. }
  16943. },
  16944. cancel: {
  16945. query: function() {
  16946. if( module.can.useAPI() ) {
  16947. $module.api('abort');
  16948. }
  16949. }
  16950. },
  16951. has: {
  16952. minimumCharacters: function() {
  16953. var
  16954. searchTerm = module.get.value(),
  16955. numCharacters = searchTerm.length
  16956. ;
  16957. return (numCharacters >= settings.minCharacters);
  16958. },
  16959. results: function() {
  16960. if($results.length === 0) {
  16961. return false;
  16962. }
  16963. var
  16964. html = $results.html()
  16965. ;
  16966. return html != '';
  16967. }
  16968. },
  16969. clear: {
  16970. cache: function(value) {
  16971. var
  16972. cache = $module.data(metadata.cache)
  16973. ;
  16974. if(!value) {
  16975. module.debug('Clearing cache', value);
  16976. $module.removeData(metadata.cache);
  16977. }
  16978. else if(value && cache && cache[value]) {
  16979. module.debug('Removing value from cache', value);
  16980. delete cache[value];
  16981. $module.data(metadata.cache, cache);
  16982. }
  16983. }
  16984. },
  16985. read: {
  16986. cache: function(name) {
  16987. var
  16988. cache = $module.data(metadata.cache)
  16989. ;
  16990. if(settings.cache) {
  16991. module.verbose('Checking cache for generated html for query', name);
  16992. return (typeof cache == 'object') && (cache[name] !== undefined)
  16993. ? cache[name]
  16994. : false
  16995. ;
  16996. }
  16997. return false;
  16998. }
  16999. },
  17000. create: {
  17001. categoryResults: function(results) {
  17002. var
  17003. categoryResults = {}
  17004. ;
  17005. $.each(results, function(index, result) {
  17006. if(!result.category) {
  17007. return;
  17008. }
  17009. if(categoryResults[result.category] === undefined) {
  17010. module.verbose('Creating new category of results', result.category);
  17011. categoryResults[result.category] = {
  17012. name : result.category,
  17013. results : [result]
  17014. };
  17015. }
  17016. else {
  17017. categoryResults[result.category].results.push(result);
  17018. }
  17019. });
  17020. return categoryResults;
  17021. },
  17022. id: function(resultIndex, categoryIndex) {
  17023. var
  17024. resultID = (resultIndex + 1), // not zero indexed
  17025. letterID,
  17026. id
  17027. ;
  17028. if(categoryIndex !== undefined) {
  17029. // start char code for "A"
  17030. letterID = String.fromCharCode(97 + categoryIndex);
  17031. id = letterID + resultID;
  17032. module.verbose('Creating category result id', id);
  17033. }
  17034. else {
  17035. id = resultID;
  17036. module.verbose('Creating result id', id);
  17037. }
  17038. return id;
  17039. },
  17040. results: function() {
  17041. if($results.length === 0) {
  17042. $results = $('<div />')
  17043. .addClass(className.results)
  17044. .appendTo($module)
  17045. ;
  17046. }
  17047. }
  17048. },
  17049. inject: {
  17050. result: function(result, resultIndex, categoryIndex) {
  17051. module.verbose('Injecting result into results');
  17052. var
  17053. $selectedResult = (categoryIndex !== undefined)
  17054. ? $results
  17055. .children().eq(categoryIndex)
  17056. .children(selector.results)
  17057. .first()
  17058. .children(selector.result)
  17059. .eq(resultIndex)
  17060. : $results
  17061. .children(selector.result).eq(resultIndex)
  17062. ;
  17063. module.verbose('Injecting results metadata', $selectedResult);
  17064. $selectedResult
  17065. .data(metadata.result, result)
  17066. ;
  17067. },
  17068. id: function(results) {
  17069. module.debug('Injecting unique ids into results');
  17070. var
  17071. // since results may be object, we must use counters
  17072. categoryIndex = 0,
  17073. resultIndex = 0
  17074. ;
  17075. if(settings.type === 'category') {
  17076. // iterate through each category result
  17077. $.each(results, function(index, category) {
  17078. if(category.results.length > 0){
  17079. resultIndex = 0;
  17080. $.each(category.results, function(index, result) {
  17081. if(result.id === undefined) {
  17082. result.id = module.create.id(resultIndex, categoryIndex);
  17083. }
  17084. module.inject.result(result, resultIndex, categoryIndex);
  17085. resultIndex++;
  17086. });
  17087. categoryIndex++;
  17088. }
  17089. });
  17090. }
  17091. else {
  17092. // top level
  17093. $.each(results, function(index, result) {
  17094. if(result.id === undefined) {
  17095. result.id = module.create.id(resultIndex);
  17096. }
  17097. module.inject.result(result, resultIndex);
  17098. resultIndex++;
  17099. });
  17100. }
  17101. return results;
  17102. }
  17103. },
  17104. save: {
  17105. results: function(results) {
  17106. module.verbose('Saving current search results to metadata', results);
  17107. $module.data(metadata.results, results);
  17108. }
  17109. },
  17110. write: {
  17111. cache: function(name, value) {
  17112. var
  17113. cache = ($module.data(metadata.cache) !== undefined)
  17114. ? $module.data(metadata.cache)
  17115. : {}
  17116. ;
  17117. if(settings.cache) {
  17118. module.verbose('Writing generated html to cache', name, value);
  17119. cache[name] = value;
  17120. $module
  17121. .data(metadata.cache, cache)
  17122. ;
  17123. }
  17124. }
  17125. },
  17126. addResults: function(html) {
  17127. if( $.isFunction(settings.onResultsAdd) ) {
  17128. if( settings.onResultsAdd.call($results, html) === false ) {
  17129. module.debug('onResultsAdd callback cancelled default action');
  17130. return false;
  17131. }
  17132. }
  17133. if(html) {
  17134. $results
  17135. .html(html)
  17136. ;
  17137. module.refreshResults();
  17138. if(settings.selectFirstResult) {
  17139. module.select.firstResult();
  17140. }
  17141. module.showResults();
  17142. }
  17143. else {
  17144. module.hideResults(function() {
  17145. $results.empty();
  17146. });
  17147. }
  17148. },
  17149. showResults: function(callback) {
  17150. callback = $.isFunction(callback)
  17151. ? callback
  17152. : function(){}
  17153. ;
  17154. if(resultsDismissed) {
  17155. return;
  17156. }
  17157. if(!module.is.visible() && module.has.results()) {
  17158. if( module.can.transition() ) {
  17159. module.debug('Showing results with css animations');
  17160. $results
  17161. .transition({
  17162. animation : settings.transition + ' in',
  17163. debug : settings.debug,
  17164. verbose : settings.verbose,
  17165. duration : settings.duration,
  17166. onComplete : function() {
  17167. callback();
  17168. },
  17169. queue : true
  17170. })
  17171. ;
  17172. }
  17173. else {
  17174. module.debug('Showing results with javascript');
  17175. $results
  17176. .stop()
  17177. .fadeIn(settings.duration, settings.easing)
  17178. ;
  17179. }
  17180. settings.onResultsOpen.call($results);
  17181. }
  17182. },
  17183. hideResults: function(callback) {
  17184. callback = $.isFunction(callback)
  17185. ? callback
  17186. : function(){}
  17187. ;
  17188. if( module.is.visible() ) {
  17189. if( module.can.transition() ) {
  17190. module.debug('Hiding results with css animations');
  17191. $results
  17192. .transition({
  17193. animation : settings.transition + ' out',
  17194. debug : settings.debug,
  17195. verbose : settings.verbose,
  17196. duration : settings.duration,
  17197. onComplete : function() {
  17198. callback();
  17199. },
  17200. queue : true
  17201. })
  17202. ;
  17203. }
  17204. else {
  17205. module.debug('Hiding results with javascript');
  17206. $results
  17207. .stop()
  17208. .fadeOut(settings.duration, settings.easing)
  17209. ;
  17210. }
  17211. settings.onResultsClose.call($results);
  17212. }
  17213. },
  17214. generateResults: function(response) {
  17215. module.debug('Generating html from response', response);
  17216. var
  17217. template = settings.templates[settings.type],
  17218. isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])),
  17219. isProperArray = (Array.isArray(response[fields.results]) && response[fields.results].length > 0),
  17220. html = ''
  17221. ;
  17222. if(isProperObject || isProperArray ) {
  17223. if(settings.maxResults > 0) {
  17224. if(isProperObject) {
  17225. if(settings.type == 'standard') {
  17226. module.error(error.maxResults);
  17227. }
  17228. }
  17229. else {
  17230. response[fields.results] = response[fields.results].slice(0, settings.maxResults);
  17231. }
  17232. }
  17233. if($.isFunction(template)) {
  17234. html = template(response, fields, settings.preserveHTML);
  17235. }
  17236. else {
  17237. module.error(error.noTemplate, false);
  17238. }
  17239. }
  17240. else if(settings.showNoResults) {
  17241. html = module.displayMessage(error.noResults, 'empty', error.noResultsHeader);
  17242. }
  17243. settings.onResults.call(element, response);
  17244. return html;
  17245. },
  17246. displayMessage: function(text, type, header) {
  17247. type = type || 'standard';
  17248. module.debug('Displaying message', text, type, header);
  17249. module.addResults( settings.templates.message(text, type, header) );
  17250. return settings.templates.message(text, type, header);
  17251. },
  17252. setting: function(name, value) {
  17253. if( $.isPlainObject(name) ) {
  17254. $.extend(true, settings, name);
  17255. }
  17256. else if(value !== undefined) {
  17257. settings[name] = value;
  17258. }
  17259. else {
  17260. return settings[name];
  17261. }
  17262. },
  17263. internal: function(name, value) {
  17264. if( $.isPlainObject(name) ) {
  17265. $.extend(true, module, name);
  17266. }
  17267. else if(value !== undefined) {
  17268. module[name] = value;
  17269. }
  17270. else {
  17271. return module[name];
  17272. }
  17273. },
  17274. debug: function() {
  17275. if(!settings.silent && settings.debug) {
  17276. if(settings.performance) {
  17277. module.performance.log(arguments);
  17278. }
  17279. else {
  17280. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17281. module.debug.apply(console, arguments);
  17282. }
  17283. }
  17284. },
  17285. verbose: function() {
  17286. if(!settings.silent && settings.verbose && settings.debug) {
  17287. if(settings.performance) {
  17288. module.performance.log(arguments);
  17289. }
  17290. else {
  17291. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17292. module.verbose.apply(console, arguments);
  17293. }
  17294. }
  17295. },
  17296. error: function() {
  17297. if(!settings.silent) {
  17298. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  17299. module.error.apply(console, arguments);
  17300. }
  17301. },
  17302. performance: {
  17303. log: function(message) {
  17304. var
  17305. currentTime,
  17306. executionTime,
  17307. previousTime
  17308. ;
  17309. if(settings.performance) {
  17310. currentTime = new Date().getTime();
  17311. previousTime = time || currentTime;
  17312. executionTime = currentTime - previousTime;
  17313. time = currentTime;
  17314. performance.push({
  17315. 'Name' : message[0],
  17316. 'Arguments' : [].slice.call(message, 1) || '',
  17317. 'Element' : element,
  17318. 'Execution Time' : executionTime
  17319. });
  17320. }
  17321. clearTimeout(module.performance.timer);
  17322. module.performance.timer = setTimeout(module.performance.display, 500);
  17323. },
  17324. display: function() {
  17325. var
  17326. title = settings.name + ':',
  17327. totalTime = 0
  17328. ;
  17329. time = false;
  17330. clearTimeout(module.performance.timer);
  17331. $.each(performance, function(index, data) {
  17332. totalTime += data['Execution Time'];
  17333. });
  17334. title += ' ' + totalTime + 'ms';
  17335. if(moduleSelector) {
  17336. title += ' \'' + moduleSelector + '\'';
  17337. }
  17338. if($allModules.length > 1) {
  17339. title += ' ' + '(' + $allModules.length + ')';
  17340. }
  17341. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  17342. console.groupCollapsed(title);
  17343. if(console.table) {
  17344. console.table(performance);
  17345. }
  17346. else {
  17347. $.each(performance, function(index, data) {
  17348. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  17349. });
  17350. }
  17351. console.groupEnd();
  17352. }
  17353. performance = [];
  17354. }
  17355. },
  17356. invoke: function(query, passedArguments, context) {
  17357. var
  17358. object = instance,
  17359. maxDepth,
  17360. found,
  17361. response
  17362. ;
  17363. passedArguments = passedArguments || queryArguments;
  17364. context = element || context;
  17365. if(typeof query == 'string' && object !== undefined) {
  17366. query = query.split(/[\. ]/);
  17367. maxDepth = query.length - 1;
  17368. $.each(query, function(depth, value) {
  17369. var camelCaseValue = (depth != maxDepth)
  17370. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  17371. : query
  17372. ;
  17373. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  17374. object = object[camelCaseValue];
  17375. }
  17376. else if( object[camelCaseValue] !== undefined ) {
  17377. found = object[camelCaseValue];
  17378. return false;
  17379. }
  17380. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  17381. object = object[value];
  17382. }
  17383. else if( object[value] !== undefined ) {
  17384. found = object[value];
  17385. return false;
  17386. }
  17387. else {
  17388. return false;
  17389. }
  17390. });
  17391. }
  17392. if( $.isFunction( found ) ) {
  17393. response = found.apply(context, passedArguments);
  17394. }
  17395. else if(found !== undefined) {
  17396. response = found;
  17397. }
  17398. if(Array.isArray(returnedValue)) {
  17399. returnedValue.push(response);
  17400. }
  17401. else if(returnedValue !== undefined) {
  17402. returnedValue = [returnedValue, response];
  17403. }
  17404. else if(response !== undefined) {
  17405. returnedValue = response;
  17406. }
  17407. return found;
  17408. }
  17409. };
  17410. if(methodInvoked) {
  17411. if(instance === undefined) {
  17412. module.initialize();
  17413. }
  17414. module.invoke(query);
  17415. }
  17416. else {
  17417. if(instance !== undefined) {
  17418. instance.invoke('destroy');
  17419. }
  17420. module.initialize();
  17421. }
  17422. })
  17423. ;
  17424. return (returnedValue !== undefined)
  17425. ? returnedValue
  17426. : this
  17427. ;
  17428. };
  17429. $.fn.search.settings = {
  17430. name : 'Search',
  17431. namespace : 'search',
  17432. silent : false,
  17433. debug : false,
  17434. verbose : false,
  17435. performance : true,
  17436. // template to use (specified in settings.templates)
  17437. type : 'standard',
  17438. // minimum characters required to search
  17439. minCharacters : 1,
  17440. // whether to select first result after searching automatically
  17441. selectFirstResult : false,
  17442. // API config
  17443. apiSettings : false,
  17444. // object to search
  17445. source : false,
  17446. // Whether search should query current term on focus
  17447. searchOnFocus : true,
  17448. // fields to search
  17449. searchFields : [
  17450. 'id',
  17451. 'title',
  17452. 'description'
  17453. ],
  17454. // field to display in standard results template
  17455. displayField : '',
  17456. // search anywhere in value (set to 'exact' to require exact matches
  17457. fullTextSearch : 'exact',
  17458. // match results also if they contain diacritics of the same base character (for example searching for "a" will also match "á" or "â" or "à", etc...)
  17459. ignoreDiacritics : false,
  17460. // whether to add events to prompt automatically
  17461. automatic : true,
  17462. // delay before hiding menu after blur
  17463. hideDelay : 0,
  17464. // delay before searching
  17465. searchDelay : 200,
  17466. // maximum results returned from search
  17467. maxResults : 7,
  17468. // whether to store lookups in local cache
  17469. cache : true,
  17470. // whether no results errors should be shown
  17471. showNoResults : true,
  17472. // preserve possible html of resultset values
  17473. preserveHTML : true,
  17474. // transition settings
  17475. transition : 'scale',
  17476. duration : 200,
  17477. easing : 'easeOutExpo',
  17478. // callbacks
  17479. onSelect : false,
  17480. onResultsAdd : false,
  17481. onSearchQuery : function(query){},
  17482. onResults : function(response){},
  17483. onResultsOpen : function(){},
  17484. onResultsClose : function(){},
  17485. className: {
  17486. animating : 'animating',
  17487. active : 'active',
  17488. empty : 'empty',
  17489. focus : 'focus',
  17490. hidden : 'hidden',
  17491. loading : 'loading',
  17492. results : 'results',
  17493. pressed : 'down'
  17494. },
  17495. error : {
  17496. source : 'Cannot search. No source used, and Semantic API module was not included',
  17497. noResultsHeader : 'No Results',
  17498. noResults : 'Your search returned no results',
  17499. logging : 'Error in debug logging, exiting.',
  17500. noEndpoint : 'No search endpoint was specified',
  17501. noTemplate : 'A valid template name was not specified.',
  17502. oldSearchSyntax : 'searchFullText setting has been renamed fullTextSearch for consistency, please adjust your settings.',
  17503. serverError : 'There was an issue querying the server.',
  17504. maxResults : 'Results must be an array to use maxResults setting',
  17505. method : 'The method you called is not defined.',
  17506. noNormalize : '"ignoreDiacritics" setting will be ignored. Browser does not support String().normalize(). You may consider including <https://cdn.jsdelivr.net/npm/unorm@1.4.1/lib/unorm.min.js> as a polyfill.'
  17507. },
  17508. metadata: {
  17509. cache : 'cache',
  17510. results : 'results',
  17511. result : 'result'
  17512. },
  17513. regExp: {
  17514. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  17515. beginsWith : '(?:\s|^)'
  17516. },
  17517. // maps api response attributes to internal representation
  17518. fields: {
  17519. categories : 'results', // array of categories (category view)
  17520. categoryName : 'name', // name of category (category view)
  17521. categoryResults : 'results', // array of results (category view)
  17522. description : 'description', // result description
  17523. image : 'image', // result image
  17524. price : 'price', // result price
  17525. results : 'results', // array of results (standard)
  17526. title : 'title', // result title
  17527. url : 'url', // result url
  17528. action : 'action', // "view more" object name
  17529. actionText : 'text', // "view more" text
  17530. actionURL : 'url' // "view more" url
  17531. },
  17532. selector : {
  17533. prompt : '.prompt',
  17534. searchButton : '.search.button',
  17535. results : '.results',
  17536. message : '.results > .message',
  17537. category : '.category',
  17538. result : '.result',
  17539. title : '.title, .name'
  17540. },
  17541. templates: {
  17542. escape: function(string, preserveHTML) {
  17543. if (preserveHTML){
  17544. return string;
  17545. }
  17546. var
  17547. badChars = /[&<>"'`]/g,
  17548. shouldEscape = /[&<>"'`]/,
  17549. escape = {
  17550. "&": "&amp;",
  17551. "<": "&lt;",
  17552. ">": "&gt;",
  17553. '"': "&quot;",
  17554. "'": "&#x27;",
  17555. "`": "&#x60;"
  17556. },
  17557. escapedChar = function(chr) {
  17558. return escape[chr];
  17559. }
  17560. ;
  17561. if(shouldEscape.test(string)) {
  17562. return string.replace(badChars, escapedChar);
  17563. }
  17564. return string;
  17565. },
  17566. message: function(message, type, header) {
  17567. var
  17568. html = ''
  17569. ;
  17570. if(message !== undefined && type !== undefined) {
  17571. html += ''
  17572. + '<div class="message ' + type + '">'
  17573. ;
  17574. if(header) {
  17575. html += ''
  17576. + '<div class="header">' + header + '</div>'
  17577. ;
  17578. }
  17579. html += ' <div class="description">' + message + '</div>';
  17580. html += '</div>';
  17581. }
  17582. return html;
  17583. },
  17584. category: function(response, fields, preserveHTML) {
  17585. var
  17586. html = '',
  17587. escape = $.fn.search.settings.templates.escape
  17588. ;
  17589. if(response[fields.categoryResults] !== undefined) {
  17590. // each category
  17591. $.each(response[fields.categoryResults], function(index, category) {
  17592. if(category[fields.results] !== undefined && category.results.length > 0) {
  17593. html += '<div class="category">';
  17594. if(category[fields.categoryName] !== undefined) {
  17595. html += '<div class="name">' + escape(category[fields.categoryName], preserveHTML) + '</div>';
  17596. }
  17597. // each item inside category
  17598. html += '<div class="results">';
  17599. $.each(category.results, function(index, result) {
  17600. if(result[fields.url]) {
  17601. html += '<a class="result" href="' + result[fields.url].replace(/"/g,"") + '">';
  17602. }
  17603. else {
  17604. html += '<a class="result">';
  17605. }
  17606. if(result[fields.image] !== undefined) {
  17607. html += ''
  17608. + '<div class="image">'
  17609. + ' <img src="' + result[fields.image].replace(/"/g,"") + '">'
  17610. + '</div>'
  17611. ;
  17612. }
  17613. html += '<div class="content">';
  17614. if(result[fields.price] !== undefined) {
  17615. html += '<div class="price">' + escape(result[fields.price], preserveHTML) + '</div>';
  17616. }
  17617. if(result[fields.title] !== undefined) {
  17618. html += '<div class="title">' + escape(result[fields.title], preserveHTML) + '</div>';
  17619. }
  17620. if(result[fields.description] !== undefined) {
  17621. html += '<div class="description">' + escape(result[fields.description], preserveHTML) + '</div>';
  17622. }
  17623. html += ''
  17624. + '</div>'
  17625. ;
  17626. html += '</a>';
  17627. });
  17628. html += '</div>';
  17629. html += ''
  17630. + '</div>'
  17631. ;
  17632. }
  17633. });
  17634. if(response[fields.action]) {
  17635. if(fields.actionURL === false) {
  17636. html += ''
  17637. + '<div class="action">'
  17638. + escape(response[fields.action][fields.actionText], preserveHTML)
  17639. + '</div>';
  17640. } else {
  17641. html += ''
  17642. + '<a href="' + response[fields.action][fields.actionURL].replace(/"/g,"") + '" class="action">'
  17643. + escape(response[fields.action][fields.actionText], preserveHTML)
  17644. + '</a>';
  17645. }
  17646. }
  17647. return html;
  17648. }
  17649. return false;
  17650. },
  17651. standard: function(response, fields, preserveHTML) {
  17652. var
  17653. html = '',
  17654. escape = $.fn.search.settings.templates.escape
  17655. ;
  17656. if(response[fields.results] !== undefined) {
  17657. // each result
  17658. $.each(response[fields.results], function(index, result) {
  17659. if(result[fields.url]) {
  17660. html += '<a class="result" href="' + result[fields.url].replace(/"/g,"") + '">';
  17661. }
  17662. else {
  17663. html += '<a class="result">';
  17664. }
  17665. if(result[fields.image] !== undefined) {
  17666. html += ''
  17667. + '<div class="image">'
  17668. + ' <img src="' + result[fields.image].replace(/"/g,"") + '">'
  17669. + '</div>'
  17670. ;
  17671. }
  17672. html += '<div class="content">';
  17673. if(result[fields.price] !== undefined) {
  17674. html += '<div class="price">' + escape(result[fields.price], preserveHTML) + '</div>';
  17675. }
  17676. if(result[fields.title] !== undefined) {
  17677. html += '<div class="title">' + escape(result[fields.title], preserveHTML) + '</div>';
  17678. }
  17679. if(result[fields.description] !== undefined) {
  17680. html += '<div class="description">' + escape(result[fields.description], preserveHTML) + '</div>';
  17681. }
  17682. html += ''
  17683. + '</div>'
  17684. ;
  17685. html += '</a>';
  17686. });
  17687. if(response[fields.action]) {
  17688. if(fields.actionURL === false) {
  17689. html += ''
  17690. + '<div class="action">'
  17691. + escape(response[fields.action][fields.actionText], preserveHTML)
  17692. + '</div>';
  17693. } else {
  17694. html += ''
  17695. + '<a href="' + response[fields.action][fields.actionURL].replace(/"/g,"") + '" class="action">'
  17696. + escape(response[fields.action][fields.actionText], preserveHTML)
  17697. + '</a>';
  17698. }
  17699. }
  17700. return html;
  17701. }
  17702. return false;
  17703. }
  17704. }
  17705. };
  17706. })( jQuery, window, document );
  17707. /*!
  17708. * # Fomantic-UI - Shape
  17709. * http://github.com/fomantic/Fomantic-UI/
  17710. *
  17711. *
  17712. * Released under the MIT license
  17713. * http://opensource.org/licenses/MIT
  17714. *
  17715. */
  17716. ;(function ($, window, document, undefined) {
  17717. 'use strict';
  17718. $.isFunction = $.isFunction || function(obj) {
  17719. return typeof obj === "function" && typeof obj.nodeType !== "number";
  17720. };
  17721. window = (typeof window != 'undefined' && window.Math == Math)
  17722. ? window
  17723. : (typeof self != 'undefined' && self.Math == Math)
  17724. ? self
  17725. : Function('return this')()
  17726. ;
  17727. $.fn.shape = function(parameters) {
  17728. var
  17729. $allModules = $(this),
  17730. time = new Date().getTime(),
  17731. performance = [],
  17732. query = arguments[0],
  17733. methodInvoked = (typeof query == 'string'),
  17734. queryArguments = [].slice.call(arguments, 1),
  17735. requestAnimationFrame = window.requestAnimationFrame
  17736. || window.mozRequestAnimationFrame
  17737. || window.webkitRequestAnimationFrame
  17738. || window.msRequestAnimationFrame
  17739. || function(callback) { setTimeout(callback, 0); },
  17740. returnedValue
  17741. ;
  17742. $allModules
  17743. .each(function() {
  17744. var
  17745. moduleSelector = $allModules.selector || '',
  17746. settings = ( $.isPlainObject(parameters) )
  17747. ? $.extend(true, {}, $.fn.shape.settings, parameters)
  17748. : $.extend({}, $.fn.shape.settings),
  17749. // internal aliases
  17750. namespace = settings.namespace,
  17751. selector = settings.selector,
  17752. error = settings.error,
  17753. className = settings.className,
  17754. // define namespaces for modules
  17755. eventNamespace = '.' + namespace,
  17756. moduleNamespace = 'module-' + namespace,
  17757. // selector cache
  17758. $module = $(this),
  17759. $sides = $module.find('>' + selector.sides),
  17760. $side = $sides.find('>' + selector.side),
  17761. // private variables
  17762. nextIndex = false,
  17763. $activeSide,
  17764. $nextSide,
  17765. // standard module
  17766. element = this,
  17767. instance = $module.data(moduleNamespace),
  17768. module
  17769. ;
  17770. module = {
  17771. initialize: function() {
  17772. module.verbose('Initializing module for', element);
  17773. module.set.defaultSide();
  17774. module.instantiate();
  17775. },
  17776. instantiate: function() {
  17777. module.verbose('Storing instance of module', module);
  17778. instance = module;
  17779. $module
  17780. .data(moduleNamespace, instance)
  17781. ;
  17782. },
  17783. destroy: function() {
  17784. module.verbose('Destroying previous module for', element);
  17785. $module
  17786. .removeData(moduleNamespace)
  17787. .off(eventNamespace)
  17788. ;
  17789. },
  17790. refresh: function() {
  17791. module.verbose('Refreshing selector cache for', element);
  17792. $module = $(element);
  17793. $sides = $(this).find(selector.sides);
  17794. $side = $(this).find(selector.side);
  17795. },
  17796. repaint: function() {
  17797. module.verbose('Forcing repaint event');
  17798. var
  17799. shape = $sides[0] || document.createElement('div'),
  17800. fakeAssignment = shape.offsetWidth
  17801. ;
  17802. },
  17803. animate: function(propertyObject, callback) {
  17804. module.verbose('Animating box with properties', propertyObject);
  17805. callback = callback || function(event) {
  17806. module.verbose('Executing animation callback');
  17807. if(event !== undefined) {
  17808. event.stopPropagation();
  17809. }
  17810. module.reset();
  17811. module.set.active();
  17812. };
  17813. settings.beforeChange.call($nextSide[0]);
  17814. if(module.get.transitionEvent()) {
  17815. module.verbose('Starting CSS animation');
  17816. $module
  17817. .addClass(className.animating)
  17818. ;
  17819. $sides
  17820. .css(propertyObject)
  17821. .one(module.get.transitionEvent(), callback)
  17822. ;
  17823. module.set.duration(settings.duration);
  17824. requestAnimationFrame(function() {
  17825. $module
  17826. .addClass(className.animating)
  17827. ;
  17828. $activeSide
  17829. .addClass(className.hidden)
  17830. ;
  17831. });
  17832. }
  17833. else {
  17834. callback();
  17835. }
  17836. },
  17837. queue: function(method) {
  17838. module.debug('Queueing animation of', method);
  17839. $sides
  17840. .one(module.get.transitionEvent(), function() {
  17841. module.debug('Executing queued animation');
  17842. setTimeout(function(){
  17843. $module.shape(method);
  17844. }, 0);
  17845. })
  17846. ;
  17847. },
  17848. reset: function() {
  17849. module.verbose('Animating states reset');
  17850. $module
  17851. .removeClass(className.animating)
  17852. .attr('style', '')
  17853. .removeAttr('style')
  17854. ;
  17855. // removeAttr style does not consistently work in safari
  17856. $sides
  17857. .attr('style', '')
  17858. .removeAttr('style')
  17859. ;
  17860. $side
  17861. .attr('style', '')
  17862. .removeAttr('style')
  17863. .removeClass(className.hidden)
  17864. ;
  17865. $nextSide
  17866. .removeClass(className.animating)
  17867. .attr('style', '')
  17868. .removeAttr('style')
  17869. ;
  17870. },
  17871. is: {
  17872. complete: function() {
  17873. return ($side.filter('.' + className.active)[0] == $nextSide[0]);
  17874. },
  17875. animating: function() {
  17876. return $module.hasClass(className.animating);
  17877. },
  17878. hidden: function() {
  17879. return $module.closest(':hidden').length > 0;
  17880. }
  17881. },
  17882. set: {
  17883. defaultSide: function() {
  17884. $activeSide = $side.filter('.' + settings.className.active);
  17885. $nextSide = ( $activeSide.next(selector.side).length > 0 )
  17886. ? $activeSide.next(selector.side)
  17887. : $side.first()
  17888. ;
  17889. nextIndex = false;
  17890. module.verbose('Active side set to', $activeSide);
  17891. module.verbose('Next side set to', $nextSide);
  17892. },
  17893. duration: function(duration) {
  17894. duration = duration || settings.duration;
  17895. duration = (typeof duration == 'number')
  17896. ? duration + 'ms'
  17897. : duration
  17898. ;
  17899. module.verbose('Setting animation duration', duration);
  17900. if(settings.duration || settings.duration === 0) {
  17901. $sides.add($side)
  17902. .css({
  17903. '-webkit-transition-duration': duration,
  17904. '-moz-transition-duration': duration,
  17905. '-ms-transition-duration': duration,
  17906. '-o-transition-duration': duration,
  17907. 'transition-duration': duration
  17908. })
  17909. ;
  17910. }
  17911. },
  17912. currentStageSize: function() {
  17913. var
  17914. $activeSide = $side.filter('.' + settings.className.active),
  17915. width = $activeSide.outerWidth(true),
  17916. height = $activeSide.outerHeight(true)
  17917. ;
  17918. $module
  17919. .css({
  17920. width: width,
  17921. height: height
  17922. })
  17923. ;
  17924. },
  17925. stageSize: function() {
  17926. var
  17927. $clone = $module.clone().addClass(className.loading),
  17928. $side = $clone.find('>' + selector.sides + '>' + selector.side),
  17929. $activeSide = $side.filter('.' + settings.className.active),
  17930. $nextSide = (nextIndex)
  17931. ? $side.eq(nextIndex)
  17932. : ( $activeSide.next(selector.side).length > 0 )
  17933. ? $activeSide.next(selector.side)
  17934. : $side.first(),
  17935. newWidth = (settings.width === 'next')
  17936. ? $nextSide.outerWidth(true)
  17937. : (settings.width === 'initial')
  17938. ? $module.width()
  17939. : settings.width,
  17940. newHeight = (settings.height === 'next')
  17941. ? $nextSide.outerHeight(true)
  17942. : (settings.height === 'initial')
  17943. ? $module.height()
  17944. : settings.height
  17945. ;
  17946. $activeSide.removeClass(className.active);
  17947. $nextSide.addClass(className.active);
  17948. $clone.insertAfter($module);
  17949. $clone.remove();
  17950. if(settings.width !== 'auto') {
  17951. $module.css('width', newWidth + settings.jitter);
  17952. module.verbose('Specifying width during animation', newWidth);
  17953. }
  17954. if(settings.height !== 'auto') {
  17955. $module.css('height', newHeight + settings.jitter);
  17956. module.verbose('Specifying height during animation', newHeight);
  17957. }
  17958. },
  17959. nextSide: function(selector) {
  17960. nextIndex = selector;
  17961. $nextSide = $side.filter(selector);
  17962. nextIndex = $side.index($nextSide);
  17963. if($nextSide.length === 0) {
  17964. module.set.defaultSide();
  17965. module.error(error.side);
  17966. }
  17967. module.verbose('Next side manually set to', $nextSide);
  17968. },
  17969. active: function() {
  17970. module.verbose('Setting new side to active', $nextSide);
  17971. $side
  17972. .removeClass(className.active)
  17973. ;
  17974. $nextSide
  17975. .addClass(className.active)
  17976. ;
  17977. settings.onChange.call($nextSide[0]);
  17978. module.set.defaultSide();
  17979. }
  17980. },
  17981. flip: {
  17982. to: function(type,stage){
  17983. if(module.is.hidden()) {
  17984. module.debug('Module not visible', $nextSide);
  17985. return;
  17986. }
  17987. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  17988. module.debug('Side already visible', $nextSide);
  17989. return;
  17990. }
  17991. var
  17992. transform = module.get.transform[type]()
  17993. ;
  17994. if( !module.is.animating()) {
  17995. module.debug('Flipping '+type, $nextSide);
  17996. module.set.stageSize();
  17997. module.stage[stage]();
  17998. module.animate(transform);
  17999. }
  18000. else {
  18001. module.queue('flip '+type);
  18002. }
  18003. },
  18004. up: function() {
  18005. module.flip.to('up','above');
  18006. },
  18007. down: function() {
  18008. module.flip.to('down','below');
  18009. },
  18010. left: function() {
  18011. module.flip.to('left','left');
  18012. },
  18013. right: function() {
  18014. module.flip.to('right','right');
  18015. },
  18016. over: function() {
  18017. module.flip.to('over','behind');
  18018. },
  18019. back: function() {
  18020. module.flip.to('back','behind');
  18021. }
  18022. },
  18023. get: {
  18024. transform: {
  18025. up: function() {
  18026. var
  18027. translateZ = $activeSide.outerHeight(true) / 2,
  18028. translateY = $nextSide.outerHeight(true) - translateZ
  18029. ;
  18030. return {
  18031. transform: 'translateY(' + translateY + 'px) translateZ(-'+ translateZ + 'px) rotateX(-90deg)'
  18032. };
  18033. },
  18034. down: function() {
  18035. var
  18036. translate = {
  18037. z: $activeSide.outerHeight(true) / 2
  18038. }
  18039. ;
  18040. return {
  18041. transform: 'translateY(-' + translate.z + 'px) translateZ(-'+ translate.z + 'px) rotateX(90deg)'
  18042. };
  18043. },
  18044. left: function() {
  18045. var
  18046. translateZ = $activeSide.outerWidth(true) / 2,
  18047. translateX = $nextSide.outerWidth(true) - translateZ
  18048. ;
  18049. return {
  18050. transform: 'translateX(' + translateX + 'px) translateZ(-' + translateZ + 'px) rotateY(90deg)'
  18051. };
  18052. },
  18053. right: function() {
  18054. var
  18055. translate = {
  18056. z : $activeSide.outerWidth(true) / 2
  18057. }
  18058. ;
  18059. return {
  18060. transform: 'translateX(-' + translate.z + 'px) translateZ(-' + translate.z + 'px) rotateY(-90deg)'
  18061. };
  18062. },
  18063. over: function() {
  18064. var
  18065. translate = {
  18066. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  18067. }
  18068. ;
  18069. return {
  18070. transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
  18071. };
  18072. },
  18073. back: function() {
  18074. var
  18075. translate = {
  18076. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  18077. }
  18078. ;
  18079. return {
  18080. transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
  18081. };
  18082. }
  18083. },
  18084. transitionEvent: function() {
  18085. var
  18086. element = document.createElement('element'),
  18087. transitions = {
  18088. 'transition' :'transitionend',
  18089. 'OTransition' :'oTransitionEnd',
  18090. 'MozTransition' :'transitionend',
  18091. 'WebkitTransition' :'webkitTransitionEnd'
  18092. },
  18093. transition
  18094. ;
  18095. for(transition in transitions){
  18096. if( element.style[transition] !== undefined ){
  18097. return transitions[transition];
  18098. }
  18099. }
  18100. },
  18101. nextSide: function() {
  18102. return ( $activeSide.next(selector.side).length > 0 )
  18103. ? $activeSide.next(selector.side)
  18104. : $side.first()
  18105. ;
  18106. }
  18107. },
  18108. stage: {
  18109. above: function() {
  18110. var
  18111. box = {
  18112. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  18113. depth : {
  18114. active : ($nextSide.outerHeight(true) / 2),
  18115. next : ($activeSide.outerHeight(true) / 2)
  18116. }
  18117. }
  18118. ;
  18119. module.verbose('Setting the initial animation position as above', $nextSide, box);
  18120. $activeSide
  18121. .css({
  18122. 'transform' : 'rotateX(0deg)'
  18123. })
  18124. ;
  18125. $nextSide
  18126. .addClass(className.animating)
  18127. .css({
  18128. 'top' : box.origin + 'px',
  18129. 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px) translateY(-' + box.depth.active + 'px)'
  18130. })
  18131. ;
  18132. },
  18133. below: function() {
  18134. var
  18135. box = {
  18136. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  18137. depth : {
  18138. active : ($nextSide.outerHeight(true) / 2),
  18139. next : ($activeSide.outerHeight(true) / 2)
  18140. }
  18141. }
  18142. ;
  18143. module.verbose('Setting the initial animation position as below', $nextSide, box);
  18144. $activeSide
  18145. .css({
  18146. 'transform' : 'rotateX(0deg)'
  18147. })
  18148. ;
  18149. $nextSide
  18150. .addClass(className.animating)
  18151. .css({
  18152. 'top' : box.origin + 'px',
  18153. 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px) translateY(' + box.depth.active + 'px)'
  18154. })
  18155. ;
  18156. },
  18157. left: function() {
  18158. var
  18159. height = {
  18160. active : $activeSide.outerWidth(true),
  18161. next : $nextSide.outerWidth(true)
  18162. },
  18163. box = {
  18164. origin : ( ( height.active - height.next ) / 2),
  18165. depth : {
  18166. active : (height.next / 2),
  18167. next : (height.active / 2)
  18168. }
  18169. }
  18170. ;
  18171. module.verbose('Setting the initial animation position as left', $nextSide, box);
  18172. $activeSide
  18173. .css({
  18174. 'transform' : 'rotateY(0deg)'
  18175. })
  18176. ;
  18177. $nextSide
  18178. .addClass(className.animating)
  18179. .css({
  18180. 'left' : box.origin + 'px',
  18181. 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px) translateX(-' + box.depth.active + 'px)'
  18182. })
  18183. ;
  18184. },
  18185. right: function() {
  18186. var
  18187. height = {
  18188. active : $activeSide.outerWidth(true),
  18189. next : $nextSide.outerWidth(true)
  18190. },
  18191. box = {
  18192. origin : ( ( height.active - height.next ) / 2),
  18193. depth : {
  18194. active : (height.next / 2),
  18195. next : (height.active / 2)
  18196. }
  18197. }
  18198. ;
  18199. module.verbose('Setting the initial animation position as right', $nextSide, box);
  18200. $activeSide
  18201. .css({
  18202. 'transform' : 'rotateY(0deg)'
  18203. })
  18204. ;
  18205. $nextSide
  18206. .addClass(className.animating)
  18207. .css({
  18208. 'left' : box.origin + 'px',
  18209. 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px) translateX(' + box.depth.active + 'px)'
  18210. })
  18211. ;
  18212. },
  18213. behind: function() {
  18214. var
  18215. height = {
  18216. active : $activeSide.outerWidth(true),
  18217. next : $nextSide.outerWidth(true)
  18218. },
  18219. box = {
  18220. origin : ( ( height.active - height.next ) / 2),
  18221. depth : {
  18222. active : (height.next / 2),
  18223. next : (height.active / 2)
  18224. }
  18225. }
  18226. ;
  18227. module.verbose('Setting the initial animation position as behind', $nextSide, box);
  18228. $activeSide
  18229. .css({
  18230. 'transform' : 'rotateY(0deg)'
  18231. })
  18232. ;
  18233. $nextSide
  18234. .addClass(className.animating)
  18235. .css({
  18236. 'left' : box.origin + 'px',
  18237. 'transform' : 'rotateY(-180deg)'
  18238. })
  18239. ;
  18240. }
  18241. },
  18242. setting: function(name, value) {
  18243. module.debug('Changing setting', name, value);
  18244. if( $.isPlainObject(name) ) {
  18245. $.extend(true, settings, name);
  18246. }
  18247. else if(value !== undefined) {
  18248. if($.isPlainObject(settings[name])) {
  18249. $.extend(true, settings[name], value);
  18250. }
  18251. else {
  18252. settings[name] = value;
  18253. }
  18254. }
  18255. else {
  18256. return settings[name];
  18257. }
  18258. },
  18259. internal: function(name, value) {
  18260. if( $.isPlainObject(name) ) {
  18261. $.extend(true, module, name);
  18262. }
  18263. else if(value !== undefined) {
  18264. module[name] = value;
  18265. }
  18266. else {
  18267. return module[name];
  18268. }
  18269. },
  18270. debug: function() {
  18271. if(!settings.silent && settings.debug) {
  18272. if(settings.performance) {
  18273. module.performance.log(arguments);
  18274. }
  18275. else {
  18276. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18277. module.debug.apply(console, arguments);
  18278. }
  18279. }
  18280. },
  18281. verbose: function() {
  18282. if(!settings.silent && settings.verbose && settings.debug) {
  18283. if(settings.performance) {
  18284. module.performance.log(arguments);
  18285. }
  18286. else {
  18287. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18288. module.verbose.apply(console, arguments);
  18289. }
  18290. }
  18291. },
  18292. error: function() {
  18293. if(!settings.silent) {
  18294. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  18295. module.error.apply(console, arguments);
  18296. }
  18297. },
  18298. performance: {
  18299. log: function(message) {
  18300. var
  18301. currentTime,
  18302. executionTime,
  18303. previousTime
  18304. ;
  18305. if(settings.performance) {
  18306. currentTime = new Date().getTime();
  18307. previousTime = time || currentTime;
  18308. executionTime = currentTime - previousTime;
  18309. time = currentTime;
  18310. performance.push({
  18311. 'Name' : message[0],
  18312. 'Arguments' : [].slice.call(message, 1) || '',
  18313. 'Element' : element,
  18314. 'Execution Time' : executionTime
  18315. });
  18316. }
  18317. clearTimeout(module.performance.timer);
  18318. module.performance.timer = setTimeout(module.performance.display, 500);
  18319. },
  18320. display: function() {
  18321. var
  18322. title = settings.name + ':',
  18323. totalTime = 0
  18324. ;
  18325. time = false;
  18326. clearTimeout(module.performance.timer);
  18327. $.each(performance, function(index, data) {
  18328. totalTime += data['Execution Time'];
  18329. });
  18330. title += ' ' + totalTime + 'ms';
  18331. if(moduleSelector) {
  18332. title += ' \'' + moduleSelector + '\'';
  18333. }
  18334. if($allModules.length > 1) {
  18335. title += ' ' + '(' + $allModules.length + ')';
  18336. }
  18337. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  18338. console.groupCollapsed(title);
  18339. if(console.table) {
  18340. console.table(performance);
  18341. }
  18342. else {
  18343. $.each(performance, function(index, data) {
  18344. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  18345. });
  18346. }
  18347. console.groupEnd();
  18348. }
  18349. performance = [];
  18350. }
  18351. },
  18352. invoke: function(query, passedArguments, context) {
  18353. var
  18354. object = instance,
  18355. maxDepth,
  18356. found,
  18357. response
  18358. ;
  18359. passedArguments = passedArguments || queryArguments;
  18360. context = element || context;
  18361. if(typeof query == 'string' && object !== undefined) {
  18362. query = query.split(/[\. ]/);
  18363. maxDepth = query.length - 1;
  18364. $.each(query, function(depth, value) {
  18365. var camelCaseValue = (depth != maxDepth)
  18366. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  18367. : query
  18368. ;
  18369. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  18370. object = object[camelCaseValue];
  18371. }
  18372. else if( object[camelCaseValue] !== undefined ) {
  18373. found = object[camelCaseValue];
  18374. return false;
  18375. }
  18376. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  18377. object = object[value];
  18378. }
  18379. else if( object[value] !== undefined ) {
  18380. found = object[value];
  18381. return false;
  18382. }
  18383. else {
  18384. return false;
  18385. }
  18386. });
  18387. }
  18388. if ( $.isFunction( found ) ) {
  18389. response = found.apply(context, passedArguments);
  18390. }
  18391. else if(found !== undefined) {
  18392. response = found;
  18393. }
  18394. if(Array.isArray(returnedValue)) {
  18395. returnedValue.push(response);
  18396. }
  18397. else if(returnedValue !== undefined) {
  18398. returnedValue = [returnedValue, response];
  18399. }
  18400. else if(response !== undefined) {
  18401. returnedValue = response;
  18402. }
  18403. return found;
  18404. }
  18405. };
  18406. if(methodInvoked) {
  18407. if(instance === undefined) {
  18408. module.initialize();
  18409. }
  18410. var $inputs = $module.find('input');
  18411. if( $inputs.length > 0) {
  18412. $inputs.blur();
  18413. setTimeout(function(){
  18414. module.invoke(query);
  18415. }, 150);
  18416. } else {
  18417. module.invoke(query);
  18418. }
  18419. }
  18420. else {
  18421. if(instance !== undefined) {
  18422. instance.invoke('destroy');
  18423. }
  18424. module.initialize();
  18425. }
  18426. })
  18427. ;
  18428. return (returnedValue !== undefined)
  18429. ? returnedValue
  18430. : this
  18431. ;
  18432. };
  18433. $.fn.shape.settings = {
  18434. // module info
  18435. name : 'Shape',
  18436. // hide all debug content
  18437. silent : false,
  18438. // debug content outputted to console
  18439. debug : false,
  18440. // verbose debug output
  18441. verbose : false,
  18442. // fudge factor in pixels when swapping from 2d to 3d (can be useful to correct rounding errors)
  18443. jitter : 0,
  18444. // performance data output
  18445. performance: true,
  18446. // event namespace
  18447. namespace : 'shape',
  18448. // width during animation, can be set to 'auto', initial', 'next' or pixel amount
  18449. width: 'initial',
  18450. // height during animation, can be set to 'auto', 'initial', 'next' or pixel amount
  18451. height: 'initial',
  18452. // callback occurs on side change
  18453. beforeChange : function() {},
  18454. onChange : function() {},
  18455. // allow animation to same side
  18456. allowRepeats: false,
  18457. // animation duration
  18458. duration : false,
  18459. // possible errors
  18460. error: {
  18461. side : 'You tried to switch to a side that does not exist.',
  18462. method : 'The method you called is not defined'
  18463. },
  18464. // classnames used
  18465. className : {
  18466. animating : 'animating',
  18467. hidden : 'hidden',
  18468. loading : 'loading',
  18469. active : 'active'
  18470. },
  18471. // selectors used
  18472. selector : {
  18473. sides : '.sides',
  18474. side : '.side'
  18475. }
  18476. };
  18477. })( jQuery, window, document );
  18478. /*!
  18479. * # Fomantic-UI - Sidebar
  18480. * http://github.com/fomantic/Fomantic-UI/
  18481. *
  18482. *
  18483. * Released under the MIT license
  18484. * http://opensource.org/licenses/MIT
  18485. *
  18486. */
  18487. ;(function ($, window, document, undefined) {
  18488. 'use strict';
  18489. $.isFunction = $.isFunction || function(obj) {
  18490. return typeof obj === "function" && typeof obj.nodeType !== "number";
  18491. };
  18492. window = (typeof window != 'undefined' && window.Math == Math)
  18493. ? window
  18494. : (typeof self != 'undefined' && self.Math == Math)
  18495. ? self
  18496. : Function('return this')()
  18497. ;
  18498. $.fn.sidebar = function(parameters) {
  18499. var
  18500. $allModules = $(this),
  18501. $window = $(window),
  18502. $document = $(document),
  18503. $html = $('html'),
  18504. $head = $('head'),
  18505. moduleSelector = $allModules.selector || '',
  18506. time = new Date().getTime(),
  18507. performance = [],
  18508. query = arguments[0],
  18509. methodInvoked = (typeof query == 'string'),
  18510. queryArguments = [].slice.call(arguments, 1),
  18511. requestAnimationFrame = window.requestAnimationFrame
  18512. || window.mozRequestAnimationFrame
  18513. || window.webkitRequestAnimationFrame
  18514. || window.msRequestAnimationFrame
  18515. || function(callback) { setTimeout(callback, 0); },
  18516. returnedValue
  18517. ;
  18518. $allModules
  18519. .each(function() {
  18520. var
  18521. settings = ( $.isPlainObject(parameters) )
  18522. ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
  18523. : $.extend({}, $.fn.sidebar.settings),
  18524. selector = settings.selector,
  18525. className = settings.className,
  18526. namespace = settings.namespace,
  18527. regExp = settings.regExp,
  18528. error = settings.error,
  18529. eventNamespace = '.' + namespace,
  18530. moduleNamespace = 'module-' + namespace,
  18531. $module = $(this),
  18532. $context = $(settings.context),
  18533. $sidebars = $module.children(selector.sidebar),
  18534. $fixed = $context.children(selector.fixed),
  18535. $pusher = $context.children(selector.pusher),
  18536. $style,
  18537. element = this,
  18538. instance = $module.data(moduleNamespace),
  18539. elementNamespace,
  18540. id,
  18541. currentScroll,
  18542. transitionEvent,
  18543. module
  18544. ;
  18545. module = {
  18546. initialize: function() {
  18547. module.debug('Initializing sidebar', parameters);
  18548. module.create.id();
  18549. transitionEvent = module.get.transitionEvent();
  18550. // avoids locking rendering if initialized in onReady
  18551. if(settings.delaySetup) {
  18552. requestAnimationFrame(module.setup.layout);
  18553. }
  18554. else {
  18555. module.setup.layout();
  18556. }
  18557. requestAnimationFrame(function() {
  18558. module.setup.cache();
  18559. });
  18560. module.instantiate();
  18561. },
  18562. instantiate: function() {
  18563. module.verbose('Storing instance of module', module);
  18564. instance = module;
  18565. $module
  18566. .data(moduleNamespace, module)
  18567. ;
  18568. },
  18569. create: {
  18570. id: function() {
  18571. id = (Math.random().toString(16) + '000000000').substr(2,8);
  18572. elementNamespace = '.' + id;
  18573. module.verbose('Creating unique id for element', id);
  18574. }
  18575. },
  18576. destroy: function() {
  18577. module.verbose('Destroying previous module for', $module);
  18578. $module
  18579. .off(eventNamespace)
  18580. .removeData(moduleNamespace)
  18581. ;
  18582. if(module.is.ios()) {
  18583. module.remove.ios();
  18584. }
  18585. // bound by uuid
  18586. $context.off(elementNamespace);
  18587. $window.off(elementNamespace);
  18588. $document.off(elementNamespace);
  18589. },
  18590. event: {
  18591. clickaway: function(event) {
  18592. if(settings.closable){
  18593. var
  18594. clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
  18595. clickedContext = ($context.is(event.target))
  18596. ;
  18597. if(clickedInPusher) {
  18598. module.verbose('User clicked on dimmed page');
  18599. module.hide();
  18600. }
  18601. if(clickedContext) {
  18602. module.verbose('User clicked on dimmable context (scaled out page)');
  18603. module.hide();
  18604. }
  18605. }
  18606. },
  18607. touch: function(event) {
  18608. //event.stopPropagation();
  18609. },
  18610. containScroll: function(event) {
  18611. if(element.scrollTop <= 0) {
  18612. element.scrollTop = 1;
  18613. }
  18614. if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
  18615. element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
  18616. }
  18617. },
  18618. scroll: function(event) {
  18619. if( $(event.target).closest(selector.sidebar).length === 0 ) {
  18620. event.preventDefault();
  18621. }
  18622. }
  18623. },
  18624. bind: {
  18625. clickaway: function() {
  18626. module.verbose('Adding clickaway events to context', $context);
  18627. $context
  18628. .on('click' + elementNamespace, module.event.clickaway)
  18629. .on('touchend' + elementNamespace, module.event.clickaway)
  18630. ;
  18631. },
  18632. scrollLock: function() {
  18633. if(settings.scrollLock) {
  18634. module.debug('Disabling page scroll');
  18635. $window
  18636. .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
  18637. ;
  18638. }
  18639. module.verbose('Adding events to contain sidebar scroll');
  18640. $document
  18641. .on('touchmove' + elementNamespace, module.event.touch)
  18642. ;
  18643. $module
  18644. .on('scroll' + eventNamespace, module.event.containScroll)
  18645. ;
  18646. }
  18647. },
  18648. unbind: {
  18649. clickaway: function() {
  18650. module.verbose('Removing clickaway events from context', $context);
  18651. $context.off(elementNamespace);
  18652. },
  18653. scrollLock: function() {
  18654. module.verbose('Removing scroll lock from page');
  18655. $document.off(elementNamespace);
  18656. $window.off(elementNamespace);
  18657. $module.off('scroll' + eventNamespace);
  18658. }
  18659. },
  18660. add: {
  18661. inlineCSS: function() {
  18662. var
  18663. width = module.cache.width || $module.outerWidth(),
  18664. height = module.cache.height || $module.outerHeight(),
  18665. isRTL = module.is.rtl(),
  18666. direction = module.get.direction(),
  18667. distance = {
  18668. left : width,
  18669. right : -width,
  18670. top : height,
  18671. bottom : -height
  18672. },
  18673. style
  18674. ;
  18675. if(isRTL){
  18676. module.verbose('RTL detected, flipping widths');
  18677. distance.left = -width;
  18678. distance.right = width;
  18679. }
  18680. style = '<style>';
  18681. if(direction === 'left' || direction === 'right') {
  18682. module.debug('Adding CSS rules for animation distance', width);
  18683. style += ''
  18684. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  18685. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  18686. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  18687. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  18688. + ' }'
  18689. ;
  18690. }
  18691. else if(direction === 'top' || direction == 'bottom') {
  18692. style += ''
  18693. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  18694. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  18695. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  18696. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  18697. + ' }'
  18698. ;
  18699. }
  18700. /* IE is only browser not to create context with transforms */
  18701. /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
  18702. if( module.is.ie() ) {
  18703. if(direction === 'left' || direction === 'right') {
  18704. module.debug('Adding CSS rules for animation distance', width);
  18705. style += ''
  18706. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  18707. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  18708. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  18709. + ' }'
  18710. ;
  18711. }
  18712. else if(direction === 'top' || direction == 'bottom') {
  18713. style += ''
  18714. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  18715. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  18716. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  18717. + ' }'
  18718. ;
  18719. }
  18720. /* opposite sides visible forces content overlay */
  18721. style += ''
  18722. + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
  18723. + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
  18724. + ' -webkit-transform: translate3d(0, 0, 0);'
  18725. + ' transform: translate3d(0, 0, 0);'
  18726. + ' }'
  18727. ;
  18728. }
  18729. style += '</style>';
  18730. $style = $(style)
  18731. .appendTo($head)
  18732. ;
  18733. module.debug('Adding sizing css to head', $style);
  18734. }
  18735. },
  18736. refresh: function() {
  18737. module.verbose('Refreshing selector cache');
  18738. $context = $(settings.context);
  18739. $sidebars = $context.children(selector.sidebar);
  18740. $pusher = $context.children(selector.pusher);
  18741. $fixed = $context.children(selector.fixed);
  18742. module.clear.cache();
  18743. },
  18744. refreshSidebars: function() {
  18745. module.verbose('Refreshing other sidebars');
  18746. $sidebars = $context.children(selector.sidebar);
  18747. },
  18748. repaint: function() {
  18749. module.verbose('Forcing repaint event');
  18750. element.style.display = 'none';
  18751. var ignored = element.offsetHeight;
  18752. element.scrollTop = element.scrollTop;
  18753. element.style.display = '';
  18754. },
  18755. setup: {
  18756. cache: function() {
  18757. module.cache = {
  18758. width : $module.outerWidth(),
  18759. height : $module.outerHeight()
  18760. };
  18761. },
  18762. layout: function() {
  18763. if( $context.children(selector.pusher).length === 0 ) {
  18764. module.debug('Adding wrapper element for sidebar');
  18765. module.error(error.pusher);
  18766. $pusher = $('<div class="pusher" />');
  18767. $context
  18768. .children()
  18769. .not(selector.omitted)
  18770. .not($sidebars)
  18771. .wrapAll($pusher)
  18772. ;
  18773. module.refresh();
  18774. }
  18775. if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
  18776. module.debug('Moved sidebar to correct parent element');
  18777. module.error(error.movedSidebar, element);
  18778. $module.detach().prependTo($context);
  18779. module.refresh();
  18780. }
  18781. module.clear.cache();
  18782. module.set.pushable();
  18783. module.set.direction();
  18784. }
  18785. },
  18786. attachEvents: function(selector, event) {
  18787. var
  18788. $toggle = $(selector)
  18789. ;
  18790. event = $.isFunction(module[event])
  18791. ? module[event]
  18792. : module.toggle
  18793. ;
  18794. if($toggle.length > 0) {
  18795. module.debug('Attaching sidebar events to element', selector, event);
  18796. $toggle
  18797. .on('click' + eventNamespace, event)
  18798. ;
  18799. }
  18800. else {
  18801. module.error(error.notFound, selector);
  18802. }
  18803. },
  18804. show: function(callback) {
  18805. callback = $.isFunction(callback)
  18806. ? callback
  18807. : function(){}
  18808. ;
  18809. if(module.is.hidden()) {
  18810. module.refreshSidebars();
  18811. if(settings.overlay) {
  18812. module.error(error.overlay);
  18813. settings.transition = 'overlay';
  18814. }
  18815. module.refresh();
  18816. if(module.othersActive()) {
  18817. module.debug('Other sidebars currently visible');
  18818. if(settings.exclusive) {
  18819. // if not overlay queue animation after hide
  18820. if(settings.transition != 'overlay') {
  18821. module.hideOthers(module.show);
  18822. return;
  18823. }
  18824. else {
  18825. module.hideOthers();
  18826. }
  18827. }
  18828. else {
  18829. settings.transition = 'overlay';
  18830. }
  18831. }
  18832. module.pushPage(function() {
  18833. callback.call(element);
  18834. settings.onShow.call(element);
  18835. });
  18836. settings.onChange.call(element);
  18837. settings.onVisible.call(element);
  18838. }
  18839. else {
  18840. module.debug('Sidebar is already visible');
  18841. }
  18842. },
  18843. hide: function(callback) {
  18844. callback = $.isFunction(callback)
  18845. ? callback
  18846. : function(){}
  18847. ;
  18848. if(module.is.visible() || module.is.animating()) {
  18849. module.debug('Hiding sidebar', callback);
  18850. module.refreshSidebars();
  18851. module.pullPage(function() {
  18852. callback.call(element);
  18853. settings.onHidden.call(element);
  18854. });
  18855. settings.onChange.call(element);
  18856. settings.onHide.call(element);
  18857. }
  18858. },
  18859. othersAnimating: function() {
  18860. return ($sidebars.not($module).filter('.' + className.animating).length > 0);
  18861. },
  18862. othersVisible: function() {
  18863. return ($sidebars.not($module).filter('.' + className.visible).length > 0);
  18864. },
  18865. othersActive: function() {
  18866. return(module.othersVisible() || module.othersAnimating());
  18867. },
  18868. hideOthers: function(callback) {
  18869. var
  18870. $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
  18871. sidebarCount = $otherSidebars.length,
  18872. callbackCount = 0
  18873. ;
  18874. callback = callback || function(){};
  18875. $otherSidebars
  18876. .sidebar('hide', function() {
  18877. callbackCount++;
  18878. if(callbackCount == sidebarCount) {
  18879. callback();
  18880. }
  18881. })
  18882. ;
  18883. },
  18884. toggle: function() {
  18885. module.verbose('Determining toggled direction');
  18886. if(module.is.hidden()) {
  18887. module.show();
  18888. }
  18889. else {
  18890. module.hide();
  18891. }
  18892. },
  18893. pushPage: function(callback) {
  18894. var
  18895. transition = module.get.transition(),
  18896. $transition = (transition === 'overlay' || module.othersActive())
  18897. ? $module
  18898. : $pusher,
  18899. animate,
  18900. dim,
  18901. transitionEnd
  18902. ;
  18903. callback = $.isFunction(callback)
  18904. ? callback
  18905. : function(){}
  18906. ;
  18907. if(settings.transition == 'scale down') {
  18908. module.scrollToTop();
  18909. }
  18910. module.set.transition(transition);
  18911. module.repaint();
  18912. animate = function() {
  18913. module.bind.clickaway();
  18914. module.add.inlineCSS();
  18915. module.set.animating();
  18916. module.set.visible();
  18917. };
  18918. dim = function() {
  18919. module.set.dimmed();
  18920. };
  18921. transitionEnd = function(event) {
  18922. if( event.target == $transition[0] ) {
  18923. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  18924. module.remove.animating();
  18925. module.bind.scrollLock();
  18926. callback.call(element);
  18927. }
  18928. };
  18929. $transition.off(transitionEvent + elementNamespace);
  18930. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  18931. requestAnimationFrame(animate);
  18932. if(settings.dimPage && !module.othersVisible()) {
  18933. requestAnimationFrame(dim);
  18934. }
  18935. },
  18936. pullPage: function(callback) {
  18937. var
  18938. transition = module.get.transition(),
  18939. $transition = (transition == 'overlay' || module.othersActive())
  18940. ? $module
  18941. : $pusher,
  18942. animate,
  18943. transitionEnd
  18944. ;
  18945. callback = $.isFunction(callback)
  18946. ? callback
  18947. : function(){}
  18948. ;
  18949. module.verbose('Removing context push state', module.get.direction());
  18950. module.unbind.clickaway();
  18951. module.unbind.scrollLock();
  18952. animate = function() {
  18953. module.set.transition(transition);
  18954. module.set.animating();
  18955. module.remove.visible();
  18956. if(settings.dimPage && !module.othersVisible()) {
  18957. $pusher.removeClass(className.dimmed);
  18958. }
  18959. };
  18960. transitionEnd = function(event) {
  18961. if( event.target == $transition[0] ) {
  18962. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  18963. module.remove.animating();
  18964. module.remove.transition();
  18965. module.remove.inlineCSS();
  18966. if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
  18967. module.scrollBack();
  18968. }
  18969. callback.call(element);
  18970. }
  18971. };
  18972. $transition.off(transitionEvent + elementNamespace);
  18973. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  18974. requestAnimationFrame(animate);
  18975. },
  18976. scrollToTop: function() {
  18977. module.verbose('Scrolling to top of page to avoid animation issues');
  18978. currentScroll = $(window).scrollTop();
  18979. $module.scrollTop(0);
  18980. window.scrollTo(0, 0);
  18981. },
  18982. scrollBack: function() {
  18983. module.verbose('Scrolling back to original page position');
  18984. window.scrollTo(0, currentScroll);
  18985. },
  18986. clear: {
  18987. cache: function() {
  18988. module.verbose('Clearing cached dimensions');
  18989. module.cache = {};
  18990. }
  18991. },
  18992. set: {
  18993. // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
  18994. // (This is no longer necessary in latest iOS)
  18995. ios: function() {
  18996. $html.addClass(className.ios);
  18997. },
  18998. // container
  18999. pushed: function() {
  19000. $context.addClass(className.pushed);
  19001. },
  19002. pushable: function() {
  19003. $context.addClass(className.pushable);
  19004. },
  19005. // pusher
  19006. dimmed: function() {
  19007. $pusher.addClass(className.dimmed);
  19008. },
  19009. // sidebar
  19010. active: function() {
  19011. $module.addClass(className.active);
  19012. },
  19013. animating: function() {
  19014. $module.addClass(className.animating);
  19015. },
  19016. transition: function(transition) {
  19017. transition = transition || module.get.transition();
  19018. $module.addClass(transition);
  19019. },
  19020. direction: function(direction) {
  19021. direction = direction || module.get.direction();
  19022. $module.addClass(className[direction]);
  19023. },
  19024. visible: function() {
  19025. $module.addClass(className.visible);
  19026. },
  19027. overlay: function() {
  19028. $module.addClass(className.overlay);
  19029. }
  19030. },
  19031. remove: {
  19032. inlineCSS: function() {
  19033. module.debug('Removing inline css styles', $style);
  19034. if($style && $style.length > 0) {
  19035. $style.remove();
  19036. }
  19037. },
  19038. // ios scroll on html not document
  19039. ios: function() {
  19040. $html.removeClass(className.ios);
  19041. },
  19042. // context
  19043. pushed: function() {
  19044. $context.removeClass(className.pushed);
  19045. },
  19046. pushable: function() {
  19047. $context.removeClass(className.pushable);
  19048. },
  19049. // sidebar
  19050. active: function() {
  19051. $module.removeClass(className.active);
  19052. },
  19053. animating: function() {
  19054. $module.removeClass(className.animating);
  19055. },
  19056. transition: function(transition) {
  19057. transition = transition || module.get.transition();
  19058. $module.removeClass(transition);
  19059. },
  19060. direction: function(direction) {
  19061. direction = direction || module.get.direction();
  19062. $module.removeClass(className[direction]);
  19063. },
  19064. visible: function() {
  19065. $module.removeClass(className.visible);
  19066. },
  19067. overlay: function() {
  19068. $module.removeClass(className.overlay);
  19069. }
  19070. },
  19071. get: {
  19072. direction: function() {
  19073. if($module.hasClass(className.top)) {
  19074. return className.top;
  19075. }
  19076. else if($module.hasClass(className.right)) {
  19077. return className.right;
  19078. }
  19079. else if($module.hasClass(className.bottom)) {
  19080. return className.bottom;
  19081. }
  19082. return className.left;
  19083. },
  19084. transition: function() {
  19085. var
  19086. direction = module.get.direction(),
  19087. transition
  19088. ;
  19089. transition = ( module.is.mobile() )
  19090. ? (settings.mobileTransition == 'auto')
  19091. ? settings.defaultTransition.mobile[direction]
  19092. : settings.mobileTransition
  19093. : (settings.transition == 'auto')
  19094. ? settings.defaultTransition.computer[direction]
  19095. : settings.transition
  19096. ;
  19097. module.verbose('Determined transition', transition);
  19098. return transition;
  19099. },
  19100. transitionEvent: function() {
  19101. var
  19102. element = document.createElement('element'),
  19103. transitions = {
  19104. 'transition' :'transitionend',
  19105. 'OTransition' :'oTransitionEnd',
  19106. 'MozTransition' :'transitionend',
  19107. 'WebkitTransition' :'webkitTransitionEnd'
  19108. },
  19109. transition
  19110. ;
  19111. for(transition in transitions){
  19112. if( element.style[transition] !== undefined ){
  19113. return transitions[transition];
  19114. }
  19115. }
  19116. }
  19117. },
  19118. is: {
  19119. ie: function() {
  19120. var
  19121. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  19122. isIE = ('ActiveXObject' in window)
  19123. ;
  19124. return (isIE11 || isIE);
  19125. },
  19126. ios: function() {
  19127. var
  19128. userAgent = navigator.userAgent,
  19129. isIOS = userAgent.match(regExp.ios),
  19130. isMobileChrome = userAgent.match(regExp.mobileChrome)
  19131. ;
  19132. if(isIOS && !isMobileChrome) {
  19133. module.verbose('Browser was found to be iOS', userAgent);
  19134. return true;
  19135. }
  19136. else {
  19137. return false;
  19138. }
  19139. },
  19140. mobile: function() {
  19141. var
  19142. userAgent = navigator.userAgent,
  19143. isMobile = userAgent.match(regExp.mobile)
  19144. ;
  19145. if(isMobile) {
  19146. module.verbose('Browser was found to be mobile', userAgent);
  19147. return true;
  19148. }
  19149. else {
  19150. module.verbose('Browser is not mobile, using regular transition', userAgent);
  19151. return false;
  19152. }
  19153. },
  19154. hidden: function() {
  19155. return !module.is.visible();
  19156. },
  19157. visible: function() {
  19158. return $module.hasClass(className.visible);
  19159. },
  19160. // alias
  19161. open: function() {
  19162. return module.is.visible();
  19163. },
  19164. closed: function() {
  19165. return module.is.hidden();
  19166. },
  19167. vertical: function() {
  19168. return $module.hasClass(className.top);
  19169. },
  19170. animating: function() {
  19171. return $context.hasClass(className.animating);
  19172. },
  19173. rtl: function () {
  19174. if(module.cache.rtl === undefined) {
  19175. module.cache.rtl = $module.attr('dir') === 'rtl' || $module.css('direction') === 'rtl';
  19176. }
  19177. return module.cache.rtl;
  19178. }
  19179. },
  19180. setting: function(name, value) {
  19181. module.debug('Changing setting', name, value);
  19182. if( $.isPlainObject(name) ) {
  19183. $.extend(true, settings, name);
  19184. }
  19185. else if(value !== undefined) {
  19186. if($.isPlainObject(settings[name])) {
  19187. $.extend(true, settings[name], value);
  19188. }
  19189. else {
  19190. settings[name] = value;
  19191. }
  19192. }
  19193. else {
  19194. return settings[name];
  19195. }
  19196. },
  19197. internal: function(name, value) {
  19198. if( $.isPlainObject(name) ) {
  19199. $.extend(true, module, name);
  19200. }
  19201. else if(value !== undefined) {
  19202. module[name] = value;
  19203. }
  19204. else {
  19205. return module[name];
  19206. }
  19207. },
  19208. debug: function() {
  19209. if(!settings.silent && settings.debug) {
  19210. if(settings.performance) {
  19211. module.performance.log(arguments);
  19212. }
  19213. else {
  19214. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19215. module.debug.apply(console, arguments);
  19216. }
  19217. }
  19218. },
  19219. verbose: function() {
  19220. if(!settings.silent && settings.verbose && settings.debug) {
  19221. if(settings.performance) {
  19222. module.performance.log(arguments);
  19223. }
  19224. else {
  19225. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19226. module.verbose.apply(console, arguments);
  19227. }
  19228. }
  19229. },
  19230. error: function() {
  19231. if(!settings.silent) {
  19232. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  19233. module.error.apply(console, arguments);
  19234. }
  19235. },
  19236. performance: {
  19237. log: function(message) {
  19238. var
  19239. currentTime,
  19240. executionTime,
  19241. previousTime
  19242. ;
  19243. if(settings.performance) {
  19244. currentTime = new Date().getTime();
  19245. previousTime = time || currentTime;
  19246. executionTime = currentTime - previousTime;
  19247. time = currentTime;
  19248. performance.push({
  19249. 'Name' : message[0],
  19250. 'Arguments' : [].slice.call(message, 1) || '',
  19251. 'Element' : element,
  19252. 'Execution Time' : executionTime
  19253. });
  19254. }
  19255. clearTimeout(module.performance.timer);
  19256. module.performance.timer = setTimeout(module.performance.display, 500);
  19257. },
  19258. display: function() {
  19259. var
  19260. title = settings.name + ':',
  19261. totalTime = 0
  19262. ;
  19263. time = false;
  19264. clearTimeout(module.performance.timer);
  19265. $.each(performance, function(index, data) {
  19266. totalTime += data['Execution Time'];
  19267. });
  19268. title += ' ' + totalTime + 'ms';
  19269. if(moduleSelector) {
  19270. title += ' \'' + moduleSelector + '\'';
  19271. }
  19272. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  19273. console.groupCollapsed(title);
  19274. if(console.table) {
  19275. console.table(performance);
  19276. }
  19277. else {
  19278. $.each(performance, function(index, data) {
  19279. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  19280. });
  19281. }
  19282. console.groupEnd();
  19283. }
  19284. performance = [];
  19285. }
  19286. },
  19287. invoke: function(query, passedArguments, context) {
  19288. var
  19289. object = instance,
  19290. maxDepth,
  19291. found,
  19292. response
  19293. ;
  19294. passedArguments = passedArguments || queryArguments;
  19295. context = element || context;
  19296. if(typeof query == 'string' && object !== undefined) {
  19297. query = query.split(/[\. ]/);
  19298. maxDepth = query.length - 1;
  19299. $.each(query, function(depth, value) {
  19300. var camelCaseValue = (depth != maxDepth)
  19301. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  19302. : query
  19303. ;
  19304. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  19305. object = object[camelCaseValue];
  19306. }
  19307. else if( object[camelCaseValue] !== undefined ) {
  19308. found = object[camelCaseValue];
  19309. return false;
  19310. }
  19311. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  19312. object = object[value];
  19313. }
  19314. else if( object[value] !== undefined ) {
  19315. found = object[value];
  19316. return false;
  19317. }
  19318. else {
  19319. module.error(error.method, query);
  19320. return false;
  19321. }
  19322. });
  19323. }
  19324. if ( $.isFunction( found ) ) {
  19325. response = found.apply(context, passedArguments);
  19326. }
  19327. else if(found !== undefined) {
  19328. response = found;
  19329. }
  19330. if(Array.isArray(returnedValue)) {
  19331. returnedValue.push(response);
  19332. }
  19333. else if(returnedValue !== undefined) {
  19334. returnedValue = [returnedValue, response];
  19335. }
  19336. else if(response !== undefined) {
  19337. returnedValue = response;
  19338. }
  19339. return found;
  19340. }
  19341. }
  19342. ;
  19343. if(methodInvoked) {
  19344. if(instance === undefined) {
  19345. module.initialize();
  19346. }
  19347. module.invoke(query);
  19348. }
  19349. else {
  19350. if(instance !== undefined) {
  19351. module.invoke('destroy');
  19352. }
  19353. module.initialize();
  19354. }
  19355. });
  19356. return (returnedValue !== undefined)
  19357. ? returnedValue
  19358. : this
  19359. ;
  19360. };
  19361. $.fn.sidebar.settings = {
  19362. name : 'Sidebar',
  19363. namespace : 'sidebar',
  19364. silent : false,
  19365. debug : false,
  19366. verbose : false,
  19367. performance : true,
  19368. transition : 'auto',
  19369. mobileTransition : 'auto',
  19370. defaultTransition : {
  19371. computer: {
  19372. left : 'uncover',
  19373. right : 'uncover',
  19374. top : 'overlay',
  19375. bottom : 'overlay'
  19376. },
  19377. mobile: {
  19378. left : 'uncover',
  19379. right : 'uncover',
  19380. top : 'overlay',
  19381. bottom : 'overlay'
  19382. }
  19383. },
  19384. context : 'body',
  19385. exclusive : false,
  19386. closable : true,
  19387. dimPage : true,
  19388. scrollLock : false,
  19389. returnScroll : false,
  19390. delaySetup : false,
  19391. duration : 500,
  19392. onChange : function(){},
  19393. onShow : function(){},
  19394. onHide : function(){},
  19395. onHidden : function(){},
  19396. onVisible : function(){},
  19397. className : {
  19398. active : 'active',
  19399. animating : 'animating',
  19400. dimmed : 'dimmed',
  19401. ios : 'ios',
  19402. pushable : 'pushable',
  19403. pushed : 'pushed',
  19404. right : 'right',
  19405. top : 'top',
  19406. left : 'left',
  19407. bottom : 'bottom',
  19408. visible : 'visible'
  19409. },
  19410. selector: {
  19411. fixed : '.fixed',
  19412. omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
  19413. pusher : '.pusher',
  19414. sidebar : '.ui.sidebar'
  19415. },
  19416. regExp: {
  19417. ios : /(iPad|iPhone|iPod)/g,
  19418. mobileChrome : /(CriOS)/g,
  19419. 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
  19420. },
  19421. error : {
  19422. method : 'The method you called is not defined.',
  19423. pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
  19424. movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
  19425. overlay : 'The overlay setting is no longer supported, use animation: overlay',
  19426. notFound : 'There were no elements that matched the specified selector'
  19427. }
  19428. };
  19429. })( jQuery, window, document );
  19430. /*!
  19431. * # Fomantic-UI - Sticky
  19432. * http://github.com/fomantic/Fomantic-UI/
  19433. *
  19434. *
  19435. * Released under the MIT license
  19436. * http://opensource.org/licenses/MIT
  19437. *
  19438. */
  19439. ;(function ($, window, document, undefined) {
  19440. 'use strict';
  19441. $.isFunction = $.isFunction || function(obj) {
  19442. return typeof obj === "function" && typeof obj.nodeType !== "number";
  19443. };
  19444. window = (typeof window != 'undefined' && window.Math == Math)
  19445. ? window
  19446. : (typeof self != 'undefined' && self.Math == Math)
  19447. ? self
  19448. : Function('return this')()
  19449. ;
  19450. $.fn.sticky = function(parameters) {
  19451. var
  19452. $allModules = $(this),
  19453. moduleSelector = $allModules.selector || '',
  19454. time = new Date().getTime(),
  19455. performance = [],
  19456. query = arguments[0],
  19457. methodInvoked = (typeof query == 'string'),
  19458. queryArguments = [].slice.call(arguments, 1),
  19459. returnedValue
  19460. ;
  19461. $allModules
  19462. .each(function() {
  19463. var
  19464. settings = ( $.isPlainObject(parameters) )
  19465. ? $.extend(true, {}, $.fn.sticky.settings, parameters)
  19466. : $.extend({}, $.fn.sticky.settings),
  19467. className = settings.className,
  19468. namespace = settings.namespace,
  19469. error = settings.error,
  19470. eventNamespace = '.' + namespace,
  19471. moduleNamespace = 'module-' + namespace,
  19472. $module = $(this),
  19473. $window = $(window),
  19474. $scroll = $(settings.scrollContext),
  19475. $container,
  19476. $context,
  19477. instance = $module.data(moduleNamespace),
  19478. requestAnimationFrame = window.requestAnimationFrame
  19479. || window.mozRequestAnimationFrame
  19480. || window.webkitRequestAnimationFrame
  19481. || window.msRequestAnimationFrame
  19482. || function(callback) { setTimeout(callback, 0); },
  19483. element = this,
  19484. documentObserver,
  19485. observer,
  19486. module
  19487. ;
  19488. module = {
  19489. initialize: function() {
  19490. module.determineContainer();
  19491. module.determineContext();
  19492. module.verbose('Initializing sticky', settings, $container);
  19493. module.save.positions();
  19494. module.checkErrors();
  19495. module.bind.events();
  19496. if(settings.observeChanges) {
  19497. module.observeChanges();
  19498. }
  19499. module.instantiate();
  19500. },
  19501. instantiate: function() {
  19502. module.verbose('Storing instance of module', module);
  19503. instance = module;
  19504. $module
  19505. .data(moduleNamespace, module)
  19506. ;
  19507. },
  19508. destroy: function() {
  19509. module.verbose('Destroying previous instance');
  19510. module.reset();
  19511. if(documentObserver) {
  19512. documentObserver.disconnect();
  19513. }
  19514. if(observer) {
  19515. observer.disconnect();
  19516. }
  19517. $window
  19518. .off('load' + eventNamespace, module.event.load)
  19519. .off('resize' + eventNamespace, module.event.resize)
  19520. ;
  19521. $scroll
  19522. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  19523. ;
  19524. $module.removeData(moduleNamespace);
  19525. },
  19526. observeChanges: function() {
  19527. if('MutationObserver' in window) {
  19528. documentObserver = new MutationObserver(module.event.documentChanged);
  19529. observer = new MutationObserver(module.event.changed);
  19530. documentObserver.observe(document, {
  19531. childList : true,
  19532. subtree : true
  19533. });
  19534. observer.observe(element, {
  19535. childList : true,
  19536. subtree : true
  19537. });
  19538. observer.observe($context[0], {
  19539. childList : true,
  19540. subtree : true
  19541. });
  19542. module.debug('Setting up mutation observer', observer);
  19543. }
  19544. },
  19545. determineContainer: function() {
  19546. if(settings.container) {
  19547. $container = $(settings.container);
  19548. }
  19549. else {
  19550. $container = $module.offsetParent();
  19551. }
  19552. },
  19553. determineContext: function() {
  19554. if(settings.context) {
  19555. $context = $(settings.context);
  19556. }
  19557. else {
  19558. $context = $container;
  19559. }
  19560. if($context.length === 0) {
  19561. module.error(error.invalidContext, settings.context, $module);
  19562. return;
  19563. }
  19564. },
  19565. checkErrors: function() {
  19566. if( module.is.hidden() ) {
  19567. module.error(error.visible, $module);
  19568. }
  19569. if(module.cache.element.height > module.cache.context.height) {
  19570. module.reset();
  19571. module.error(error.elementSize, $module);
  19572. return;
  19573. }
  19574. },
  19575. bind: {
  19576. events: function() {
  19577. $window
  19578. .on('load' + eventNamespace, module.event.load)
  19579. .on('resize' + eventNamespace, module.event.resize)
  19580. ;
  19581. // pub/sub pattern
  19582. $scroll
  19583. .off('scroll' + eventNamespace)
  19584. .on('scroll' + eventNamespace, module.event.scroll)
  19585. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  19586. ;
  19587. }
  19588. },
  19589. event: {
  19590. changed: function(mutations) {
  19591. clearTimeout(module.timer);
  19592. module.timer = setTimeout(function() {
  19593. module.verbose('DOM tree modified, updating sticky menu', mutations);
  19594. module.refresh();
  19595. }, 100);
  19596. },
  19597. documentChanged: function(mutations) {
  19598. [].forEach.call(mutations, function(mutation) {
  19599. if(mutation.removedNodes) {
  19600. [].forEach.call(mutation.removedNodes, function(node) {
  19601. if(node == element || $(node).find(element).length > 0) {
  19602. module.debug('Element removed from DOM, tearing down events');
  19603. module.destroy();
  19604. }
  19605. });
  19606. }
  19607. });
  19608. },
  19609. load: function() {
  19610. module.verbose('Page contents finished loading');
  19611. requestAnimationFrame(module.refresh);
  19612. },
  19613. resize: function() {
  19614. module.verbose('Window resized');
  19615. requestAnimationFrame(module.refresh);
  19616. },
  19617. scroll: function() {
  19618. requestAnimationFrame(function() {
  19619. $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
  19620. });
  19621. },
  19622. scrollchange: function(event, scrollPosition) {
  19623. module.stick(scrollPosition);
  19624. settings.onScroll.call(element);
  19625. }
  19626. },
  19627. refresh: function(hardRefresh) {
  19628. module.reset();
  19629. if(!settings.context) {
  19630. module.determineContext();
  19631. }
  19632. if(hardRefresh) {
  19633. module.determineContainer();
  19634. }
  19635. module.save.positions();
  19636. module.stick();
  19637. settings.onReposition.call(element);
  19638. },
  19639. supports: {
  19640. sticky: function() {
  19641. var
  19642. $element = $('<div/>')
  19643. ;
  19644. $element.addClass(className.supported);
  19645. return($element.css('position').match('sticky'));
  19646. }
  19647. },
  19648. save: {
  19649. lastScroll: function(scroll) {
  19650. module.lastScroll = scroll;
  19651. },
  19652. elementScroll: function(scroll) {
  19653. module.elementScroll = scroll;
  19654. },
  19655. positions: function() {
  19656. var
  19657. scrollContext = {
  19658. height : $scroll.height()
  19659. },
  19660. element = {
  19661. margin: {
  19662. top : parseInt($module.css('margin-top'), 10),
  19663. bottom : parseInt($module.css('margin-bottom'), 10),
  19664. },
  19665. offset : $module.offset(),
  19666. width : $module.outerWidth(),
  19667. height : $module.outerHeight()
  19668. },
  19669. context = {
  19670. offset : $context.offset(),
  19671. height : $context.outerHeight()
  19672. }
  19673. ;
  19674. if( !module.is.standardScroll() ) {
  19675. module.debug('Non-standard scroll. Removing scroll offset from element offset');
  19676. scrollContext.top = $scroll.scrollTop();
  19677. scrollContext.left = $scroll.scrollLeft();
  19678. element.offset.top += scrollContext.top;
  19679. context.offset.top += scrollContext.top;
  19680. element.offset.left += scrollContext.left;
  19681. context.offset.left += scrollContext.left;
  19682. }
  19683. module.cache = {
  19684. fits : ( (element.height + settings.offset) <= scrollContext.height),
  19685. sameHeight : (element.height == context.height),
  19686. scrollContext : {
  19687. height : scrollContext.height
  19688. },
  19689. element: {
  19690. margin : element.margin,
  19691. top : element.offset.top - element.margin.top,
  19692. left : element.offset.left,
  19693. width : element.width,
  19694. height : element.height,
  19695. bottom : element.offset.top + element.height
  19696. },
  19697. context: {
  19698. top : context.offset.top,
  19699. height : context.height,
  19700. bottom : context.offset.top + context.height
  19701. }
  19702. };
  19703. module.set.containerSize();
  19704. module.stick();
  19705. module.debug('Caching element positions', module.cache);
  19706. }
  19707. },
  19708. get: {
  19709. direction: function(scroll) {
  19710. var
  19711. direction = 'down'
  19712. ;
  19713. scroll = scroll || $scroll.scrollTop();
  19714. if(module.lastScroll !== undefined) {
  19715. if(module.lastScroll < scroll) {
  19716. direction = 'down';
  19717. }
  19718. else if(module.lastScroll > scroll) {
  19719. direction = 'up';
  19720. }
  19721. }
  19722. return direction;
  19723. },
  19724. scrollChange: function(scroll) {
  19725. scroll = scroll || $scroll.scrollTop();
  19726. return (module.lastScroll)
  19727. ? (scroll - module.lastScroll)
  19728. : 0
  19729. ;
  19730. },
  19731. currentElementScroll: function() {
  19732. if(module.elementScroll) {
  19733. return module.elementScroll;
  19734. }
  19735. return ( module.is.top() )
  19736. ? Math.abs(parseInt($module.css('top'), 10)) || 0
  19737. : Math.abs(parseInt($module.css('bottom'), 10)) || 0
  19738. ;
  19739. },
  19740. elementScroll: function(scroll) {
  19741. scroll = scroll || $scroll.scrollTop();
  19742. var
  19743. element = module.cache.element,
  19744. scrollContext = module.cache.scrollContext,
  19745. delta = module.get.scrollChange(scroll),
  19746. maxScroll = (element.height - scrollContext.height + settings.offset),
  19747. elementScroll = module.get.currentElementScroll(),
  19748. possibleScroll = (elementScroll + delta)
  19749. ;
  19750. if(module.cache.fits || possibleScroll < 0) {
  19751. elementScroll = 0;
  19752. }
  19753. else if(possibleScroll > maxScroll ) {
  19754. elementScroll = maxScroll;
  19755. }
  19756. else {
  19757. elementScroll = possibleScroll;
  19758. }
  19759. return elementScroll;
  19760. }
  19761. },
  19762. remove: {
  19763. lastScroll: function() {
  19764. delete module.lastScroll;
  19765. },
  19766. elementScroll: function(scroll) {
  19767. delete module.elementScroll;
  19768. },
  19769. minimumSize: function() {
  19770. $container
  19771. .css('min-height', '')
  19772. ;
  19773. },
  19774. offset: function() {
  19775. $module.css('margin-top', '');
  19776. }
  19777. },
  19778. set: {
  19779. offset: function() {
  19780. module.verbose('Setting offset on element', settings.offset);
  19781. $module
  19782. .css('margin-top', settings.offset)
  19783. ;
  19784. },
  19785. containerSize: function() {
  19786. var
  19787. tagName = $container.get(0).tagName
  19788. ;
  19789. if(tagName === 'HTML' || tagName == 'body') {
  19790. // this can trigger for too many reasons
  19791. //module.error(error.container, tagName, $module);
  19792. module.determineContainer();
  19793. }
  19794. else {
  19795. if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
  19796. module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
  19797. $container.css({
  19798. height: module.cache.context.height
  19799. });
  19800. }
  19801. }
  19802. },
  19803. minimumSize: function() {
  19804. var
  19805. element = module.cache.element
  19806. ;
  19807. $container
  19808. .css('min-height', element.height)
  19809. ;
  19810. },
  19811. scroll: function(scroll) {
  19812. module.debug('Setting scroll on element', scroll);
  19813. if(module.elementScroll == scroll) {
  19814. return;
  19815. }
  19816. if( module.is.top() ) {
  19817. $module
  19818. .css('bottom', '')
  19819. .css('top', -scroll)
  19820. ;
  19821. }
  19822. if( module.is.bottom() ) {
  19823. $module
  19824. .css('top', '')
  19825. .css('bottom', scroll)
  19826. ;
  19827. }
  19828. },
  19829. size: function() {
  19830. if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
  19831. element.style.setProperty('width', module.cache.element.width + 'px', 'important');
  19832. element.style.setProperty('height', module.cache.element.height + 'px', 'important');
  19833. }
  19834. }
  19835. },
  19836. is: {
  19837. standardScroll: function() {
  19838. return ($scroll[0] == window);
  19839. },
  19840. top: function() {
  19841. return $module.hasClass(className.top);
  19842. },
  19843. bottom: function() {
  19844. return $module.hasClass(className.bottom);
  19845. },
  19846. initialPosition: function() {
  19847. return (!module.is.fixed() && !module.is.bound());
  19848. },
  19849. hidden: function() {
  19850. return (!$module.is(':visible'));
  19851. },
  19852. bound: function() {
  19853. return $module.hasClass(className.bound);
  19854. },
  19855. fixed: function() {
  19856. return $module.hasClass(className.fixed);
  19857. }
  19858. },
  19859. stick: function(scroll) {
  19860. var
  19861. cachedPosition = scroll || $scroll.scrollTop(),
  19862. cache = module.cache,
  19863. fits = cache.fits,
  19864. sameHeight = cache.sameHeight,
  19865. element = cache.element,
  19866. scrollContext = cache.scrollContext,
  19867. context = cache.context,
  19868. offset = (module.is.bottom() && settings.pushing)
  19869. ? settings.bottomOffset
  19870. : settings.offset,
  19871. scroll = {
  19872. top : cachedPosition + offset,
  19873. bottom : cachedPosition + offset + scrollContext.height
  19874. },
  19875. elementScroll = (fits)
  19876. ? 0
  19877. : module.get.elementScroll(scroll.top),
  19878. // shorthand
  19879. doesntFit = !fits,
  19880. elementVisible = (element.height !== 0)
  19881. ;
  19882. if(elementVisible && !sameHeight) {
  19883. if( module.is.initialPosition() ) {
  19884. if(scroll.top >= context.bottom) {
  19885. module.debug('Initial element position is bottom of container');
  19886. module.bindBottom();
  19887. }
  19888. else if(scroll.top > element.top) {
  19889. if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  19890. module.debug('Initial element position is bottom of container');
  19891. module.bindBottom();
  19892. }
  19893. else {
  19894. module.debug('Initial element position is fixed');
  19895. module.fixTop();
  19896. }
  19897. }
  19898. }
  19899. else if( module.is.fixed() ) {
  19900. // currently fixed top
  19901. if( module.is.top() ) {
  19902. if( scroll.top <= element.top ) {
  19903. module.debug('Fixed element reached top of container');
  19904. module.setInitialPosition();
  19905. }
  19906. else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  19907. module.debug('Fixed element reached bottom of container');
  19908. module.bindBottom();
  19909. }
  19910. // scroll element if larger than screen
  19911. else if(doesntFit) {
  19912. module.set.scroll(elementScroll);
  19913. module.save.lastScroll(scroll.top);
  19914. module.save.elementScroll(elementScroll);
  19915. }
  19916. }
  19917. // currently fixed bottom
  19918. else if(module.is.bottom() ) {
  19919. // top edge
  19920. if( (scroll.bottom - element.height) <= element.top) {
  19921. module.debug('Bottom fixed rail has reached top of container');
  19922. module.setInitialPosition();
  19923. }
  19924. // bottom edge
  19925. else if(scroll.bottom >= context.bottom) {
  19926. module.debug('Bottom fixed rail has reached bottom of container');
  19927. module.bindBottom();
  19928. }
  19929. // scroll element if larger than screen
  19930. else if(doesntFit) {
  19931. module.set.scroll(elementScroll);
  19932. module.save.lastScroll(scroll.top);
  19933. module.save.elementScroll(elementScroll);
  19934. }
  19935. }
  19936. }
  19937. else if( module.is.bottom() ) {
  19938. if( scroll.top <= element.top ) {
  19939. module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
  19940. module.setInitialPosition();
  19941. }
  19942. else {
  19943. if(settings.pushing) {
  19944. if(module.is.bound() && scroll.bottom <= context.bottom ) {
  19945. module.debug('Fixing bottom attached element to bottom of browser.');
  19946. module.fixBottom();
  19947. }
  19948. }
  19949. else {
  19950. if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
  19951. module.debug('Fixing bottom attached element to top of browser.');
  19952. module.fixTop();
  19953. }
  19954. }
  19955. }
  19956. }
  19957. }
  19958. },
  19959. bindTop: function() {
  19960. module.debug('Binding element to top of parent container');
  19961. module.remove.offset();
  19962. $module
  19963. .css({
  19964. left : '',
  19965. top : '',
  19966. marginBottom : ''
  19967. })
  19968. .removeClass(className.fixed)
  19969. .removeClass(className.bottom)
  19970. .addClass(className.bound)
  19971. .addClass(className.top)
  19972. ;
  19973. settings.onTop.call(element);
  19974. settings.onUnstick.call(element);
  19975. },
  19976. bindBottom: function() {
  19977. module.debug('Binding element to bottom of parent container');
  19978. module.remove.offset();
  19979. $module
  19980. .css({
  19981. left : '',
  19982. top : ''
  19983. })
  19984. .removeClass(className.fixed)
  19985. .removeClass(className.top)
  19986. .addClass(className.bound)
  19987. .addClass(className.bottom)
  19988. ;
  19989. settings.onBottom.call(element);
  19990. settings.onUnstick.call(element);
  19991. },
  19992. setInitialPosition: function() {
  19993. module.debug('Returning to initial position');
  19994. module.unfix();
  19995. module.unbind();
  19996. },
  19997. fixTop: function() {
  19998. module.debug('Fixing element to top of page');
  19999. if(settings.setSize) {
  20000. module.set.size();
  20001. }
  20002. module.set.minimumSize();
  20003. module.set.offset();
  20004. $module
  20005. .css({
  20006. left : module.cache.element.left,
  20007. bottom : '',
  20008. marginBottom : ''
  20009. })
  20010. .removeClass(className.bound)
  20011. .removeClass(className.bottom)
  20012. .addClass(className.fixed)
  20013. .addClass(className.top)
  20014. ;
  20015. settings.onStick.call(element);
  20016. },
  20017. fixBottom: function() {
  20018. module.debug('Sticking element to bottom of page');
  20019. if(settings.setSize) {
  20020. module.set.size();
  20021. }
  20022. module.set.minimumSize();
  20023. module.set.offset();
  20024. $module
  20025. .css({
  20026. left : module.cache.element.left,
  20027. bottom : '',
  20028. marginBottom : ''
  20029. })
  20030. .removeClass(className.bound)
  20031. .removeClass(className.top)
  20032. .addClass(className.fixed)
  20033. .addClass(className.bottom)
  20034. ;
  20035. settings.onStick.call(element);
  20036. },
  20037. unbind: function() {
  20038. if( module.is.bound() ) {
  20039. module.debug('Removing container bound position on element');
  20040. module.remove.offset();
  20041. $module
  20042. .removeClass(className.bound)
  20043. .removeClass(className.top)
  20044. .removeClass(className.bottom)
  20045. ;
  20046. }
  20047. },
  20048. unfix: function() {
  20049. if( module.is.fixed() ) {
  20050. module.debug('Removing fixed position on element');
  20051. module.remove.minimumSize();
  20052. module.remove.offset();
  20053. $module
  20054. .removeClass(className.fixed)
  20055. .removeClass(className.top)
  20056. .removeClass(className.bottom)
  20057. ;
  20058. settings.onUnstick.call(element);
  20059. }
  20060. },
  20061. reset: function() {
  20062. module.debug('Resetting elements position');
  20063. module.unbind();
  20064. module.unfix();
  20065. module.resetCSS();
  20066. module.remove.offset();
  20067. module.remove.lastScroll();
  20068. },
  20069. resetCSS: function() {
  20070. $module
  20071. .css({
  20072. width : '',
  20073. height : ''
  20074. })
  20075. ;
  20076. $container
  20077. .css({
  20078. height: ''
  20079. })
  20080. ;
  20081. },
  20082. setting: function(name, value) {
  20083. if( $.isPlainObject(name) ) {
  20084. $.extend(true, settings, name);
  20085. }
  20086. else if(value !== undefined) {
  20087. settings[name] = value;
  20088. }
  20089. else {
  20090. return settings[name];
  20091. }
  20092. },
  20093. internal: function(name, value) {
  20094. if( $.isPlainObject(name) ) {
  20095. $.extend(true, module, name);
  20096. }
  20097. else if(value !== undefined) {
  20098. module[name] = value;
  20099. }
  20100. else {
  20101. return module[name];
  20102. }
  20103. },
  20104. debug: function() {
  20105. if(!settings.silent && settings.debug) {
  20106. if(settings.performance) {
  20107. module.performance.log(arguments);
  20108. }
  20109. else {
  20110. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20111. module.debug.apply(console, arguments);
  20112. }
  20113. }
  20114. },
  20115. verbose: function() {
  20116. if(!settings.silent && settings.verbose && settings.debug) {
  20117. if(settings.performance) {
  20118. module.performance.log(arguments);
  20119. }
  20120. else {
  20121. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20122. module.verbose.apply(console, arguments);
  20123. }
  20124. }
  20125. },
  20126. error: function() {
  20127. if(!settings.silent) {
  20128. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  20129. module.error.apply(console, arguments);
  20130. }
  20131. },
  20132. performance: {
  20133. log: function(message) {
  20134. var
  20135. currentTime,
  20136. executionTime,
  20137. previousTime
  20138. ;
  20139. if(settings.performance) {
  20140. currentTime = new Date().getTime();
  20141. previousTime = time || currentTime;
  20142. executionTime = currentTime - previousTime;
  20143. time = currentTime;
  20144. performance.push({
  20145. 'Name' : message[0],
  20146. 'Arguments' : [].slice.call(message, 1) || '',
  20147. 'Element' : element,
  20148. 'Execution Time' : executionTime
  20149. });
  20150. }
  20151. clearTimeout(module.performance.timer);
  20152. module.performance.timer = setTimeout(module.performance.display, 0);
  20153. },
  20154. display: function() {
  20155. var
  20156. title = settings.name + ':',
  20157. totalTime = 0
  20158. ;
  20159. time = false;
  20160. clearTimeout(module.performance.timer);
  20161. $.each(performance, function(index, data) {
  20162. totalTime += data['Execution Time'];
  20163. });
  20164. title += ' ' + totalTime + 'ms';
  20165. if(moduleSelector) {
  20166. title += ' \'' + moduleSelector + '\'';
  20167. }
  20168. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  20169. console.groupCollapsed(title);
  20170. if(console.table) {
  20171. console.table(performance);
  20172. }
  20173. else {
  20174. $.each(performance, function(index, data) {
  20175. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  20176. });
  20177. }
  20178. console.groupEnd();
  20179. }
  20180. performance = [];
  20181. }
  20182. },
  20183. invoke: function(query, passedArguments, context) {
  20184. var
  20185. object = instance,
  20186. maxDepth,
  20187. found,
  20188. response
  20189. ;
  20190. passedArguments = passedArguments || queryArguments;
  20191. context = element || context;
  20192. if(typeof query == 'string' && object !== undefined) {
  20193. query = query.split(/[\. ]/);
  20194. maxDepth = query.length - 1;
  20195. $.each(query, function(depth, value) {
  20196. var camelCaseValue = (depth != maxDepth)
  20197. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  20198. : query
  20199. ;
  20200. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  20201. object = object[camelCaseValue];
  20202. }
  20203. else if( object[camelCaseValue] !== undefined ) {
  20204. found = object[camelCaseValue];
  20205. return false;
  20206. }
  20207. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  20208. object = object[value];
  20209. }
  20210. else if( object[value] !== undefined ) {
  20211. found = object[value];
  20212. return false;
  20213. }
  20214. else {
  20215. return false;
  20216. }
  20217. });
  20218. }
  20219. if ( $.isFunction( found ) ) {
  20220. response = found.apply(context, passedArguments);
  20221. }
  20222. else if(found !== undefined) {
  20223. response = found;
  20224. }
  20225. if(Array.isArray(returnedValue)) {
  20226. returnedValue.push(response);
  20227. }
  20228. else if(returnedValue !== undefined) {
  20229. returnedValue = [returnedValue, response];
  20230. }
  20231. else if(response !== undefined) {
  20232. returnedValue = response;
  20233. }
  20234. return found;
  20235. }
  20236. };
  20237. if(methodInvoked) {
  20238. if(instance === undefined) {
  20239. module.initialize();
  20240. }
  20241. module.invoke(query);
  20242. }
  20243. else {
  20244. if(instance !== undefined) {
  20245. instance.invoke('destroy');
  20246. }
  20247. module.initialize();
  20248. }
  20249. })
  20250. ;
  20251. return (returnedValue !== undefined)
  20252. ? returnedValue
  20253. : this
  20254. ;
  20255. };
  20256. $.fn.sticky.settings = {
  20257. name : 'Sticky',
  20258. namespace : 'sticky',
  20259. silent : false,
  20260. debug : false,
  20261. verbose : true,
  20262. performance : true,
  20263. // whether to stick in the opposite direction on scroll up
  20264. pushing : false,
  20265. context : false,
  20266. container : false,
  20267. // Context to watch scroll events
  20268. scrollContext : window,
  20269. // Offset to adjust scroll
  20270. offset : 0,
  20271. // Offset to adjust scroll when attached to bottom of screen
  20272. bottomOffset : 0,
  20273. // will only set container height if difference between context and container is larger than this number
  20274. jitter : 5,
  20275. // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
  20276. setSize : true,
  20277. // Whether to automatically observe changes with Mutation Observers
  20278. observeChanges : false,
  20279. // Called when position is recalculated
  20280. onReposition : function(){},
  20281. // Called on each scroll
  20282. onScroll : function(){},
  20283. // Called when element is stuck to viewport
  20284. onStick : function(){},
  20285. // Called when element is unstuck from viewport
  20286. onUnstick : function(){},
  20287. // Called when element reaches top of context
  20288. onTop : function(){},
  20289. // Called when element reaches bottom of context
  20290. onBottom : function(){},
  20291. error : {
  20292. container : 'Sticky element must be inside a relative container',
  20293. visible : 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to surpress this warning in production.',
  20294. method : 'The method you called is not defined.',
  20295. invalidContext : 'Context specified does not exist',
  20296. elementSize : 'Sticky element is larger than its container, cannot create sticky.'
  20297. },
  20298. className : {
  20299. bound : 'bound',
  20300. fixed : 'fixed',
  20301. supported : 'native',
  20302. top : 'top',
  20303. bottom : 'bottom'
  20304. }
  20305. };
  20306. })( jQuery, window, document );
  20307. /*!
  20308. * # Fomantic-UI - Tab
  20309. * http://github.com/fomantic/Fomantic-UI/
  20310. *
  20311. *
  20312. * Released under the MIT license
  20313. * http://opensource.org/licenses/MIT
  20314. *
  20315. */
  20316. ;(function ($, window, document, undefined) {
  20317. 'use strict';
  20318. $.isWindow = $.isWindow || function(obj) {
  20319. return obj != null && obj === obj.window;
  20320. };
  20321. $.isFunction = $.isFunction || function(obj) {
  20322. return typeof obj === "function" && typeof obj.nodeType !== "number";
  20323. };
  20324. window = (typeof window != 'undefined' && window.Math == Math)
  20325. ? window
  20326. : (typeof self != 'undefined' && self.Math == Math)
  20327. ? self
  20328. : Function('return this')()
  20329. ;
  20330. $.fn.tab = function(parameters) {
  20331. var
  20332. // use window context if none specified
  20333. $allModules = $.isFunction(this)
  20334. ? $(window)
  20335. : $(this),
  20336. moduleSelector = $allModules.selector || '',
  20337. time = new Date().getTime(),
  20338. performance = [],
  20339. query = arguments[0],
  20340. methodInvoked = (typeof query == 'string'),
  20341. queryArguments = [].slice.call(arguments, 1),
  20342. initializedHistory = false,
  20343. returnedValue
  20344. ;
  20345. $allModules
  20346. .each(function() {
  20347. var
  20348. settings = ( $.isPlainObject(parameters) )
  20349. ? $.extend(true, {}, $.fn.tab.settings, parameters)
  20350. : $.extend({}, $.fn.tab.settings),
  20351. className = settings.className,
  20352. metadata = settings.metadata,
  20353. selector = settings.selector,
  20354. error = settings.error,
  20355. regExp = settings.regExp,
  20356. eventNamespace = '.' + settings.namespace,
  20357. moduleNamespace = 'module-' + settings.namespace,
  20358. $module = $(this),
  20359. $context,
  20360. $tabs,
  20361. cache = {},
  20362. firstLoad = true,
  20363. recursionDepth = 0,
  20364. element = this,
  20365. instance = $module.data(moduleNamespace),
  20366. activeTabPath,
  20367. parameterArray,
  20368. module,
  20369. historyEvent
  20370. ;
  20371. module = {
  20372. initialize: function() {
  20373. module.debug('Initializing tab menu item', $module);
  20374. module.fix.callbacks();
  20375. module.determineTabs();
  20376. module.debug('Determining tabs', settings.context, $tabs);
  20377. // set up automatic routing
  20378. if(settings.auto) {
  20379. module.set.auto();
  20380. }
  20381. module.bind.events();
  20382. if(settings.history && !initializedHistory) {
  20383. module.initializeHistory();
  20384. initializedHistory = true;
  20385. }
  20386. if(instance === undefined && module.determine.activeTab() == null) {
  20387. module.debug('No active tab detected, setting first tab active', module.get.initialPath());
  20388. module.changeTab(module.get.initialPath());
  20389. };
  20390. module.instantiate();
  20391. },
  20392. instantiate: function () {
  20393. module.verbose('Storing instance of module', module);
  20394. instance = module;
  20395. $module
  20396. .data(moduleNamespace, module)
  20397. ;
  20398. },
  20399. destroy: function() {
  20400. module.debug('Destroying tabs', $module);
  20401. $module
  20402. .removeData(moduleNamespace)
  20403. .off(eventNamespace)
  20404. ;
  20405. },
  20406. bind: {
  20407. events: function() {
  20408. // if using $.tab don't add events
  20409. if( !$.isWindow( element ) ) {
  20410. module.debug('Attaching tab activation events to element', $module);
  20411. $module
  20412. .on('click' + eventNamespace, module.event.click)
  20413. ;
  20414. }
  20415. }
  20416. },
  20417. determineTabs: function() {
  20418. var
  20419. $reference
  20420. ;
  20421. // determine tab context
  20422. if(settings.context === 'parent') {
  20423. if($module.closest(selector.ui).length > 0) {
  20424. $reference = $module.closest(selector.ui);
  20425. module.verbose('Using closest UI element as parent', $reference);
  20426. }
  20427. else {
  20428. $reference = $module;
  20429. }
  20430. $context = $reference.parent();
  20431. module.verbose('Determined parent element for creating context', $context);
  20432. }
  20433. else if(settings.context) {
  20434. $context = $(settings.context);
  20435. module.verbose('Using selector for tab context', settings.context, $context);
  20436. }
  20437. else {
  20438. $context = $('body');
  20439. }
  20440. // find tabs
  20441. if(settings.childrenOnly) {
  20442. $tabs = $context.children(selector.tabs);
  20443. module.debug('Searching tab context children for tabs', $context, $tabs);
  20444. }
  20445. else {
  20446. $tabs = $context.find(selector.tabs);
  20447. module.debug('Searching tab context for tabs', $context, $tabs);
  20448. }
  20449. },
  20450. fix: {
  20451. callbacks: function() {
  20452. if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
  20453. if(parameters.onTabLoad) {
  20454. parameters.onLoad = parameters.onTabLoad;
  20455. delete parameters.onTabLoad;
  20456. module.error(error.legacyLoad, parameters.onLoad);
  20457. }
  20458. if(parameters.onTabInit) {
  20459. parameters.onFirstLoad = parameters.onTabInit;
  20460. delete parameters.onTabInit;
  20461. module.error(error.legacyInit, parameters.onFirstLoad);
  20462. }
  20463. settings = $.extend(true, {}, $.fn.tab.settings, parameters);
  20464. }
  20465. }
  20466. },
  20467. initializeHistory: function() {
  20468. module.debug('Initializing page state');
  20469. if( $.address === undefined ) {
  20470. module.error(error.state);
  20471. return false;
  20472. }
  20473. else {
  20474. if(settings.historyType == 'state') {
  20475. module.debug('Using HTML5 to manage state');
  20476. if(settings.path !== false) {
  20477. $.address
  20478. .history(true)
  20479. .state(settings.path)
  20480. ;
  20481. }
  20482. else {
  20483. module.error(error.path);
  20484. return false;
  20485. }
  20486. }
  20487. $.address
  20488. .bind('change', module.event.history.change)
  20489. ;
  20490. }
  20491. },
  20492. event: {
  20493. click: function(event) {
  20494. var
  20495. tabPath = $(this).data(metadata.tab)
  20496. ;
  20497. if(tabPath !== undefined) {
  20498. if(settings.history) {
  20499. module.verbose('Updating page state', event);
  20500. $.address.value(tabPath);
  20501. }
  20502. else {
  20503. module.verbose('Changing tab', event);
  20504. module.changeTab(tabPath);
  20505. }
  20506. event.preventDefault();
  20507. }
  20508. else {
  20509. module.debug('No tab specified');
  20510. }
  20511. },
  20512. history: {
  20513. change: function(event) {
  20514. var
  20515. tabPath = event.pathNames.join('/') || module.get.initialPath(),
  20516. pageTitle = settings.templates.determineTitle(tabPath) || false
  20517. ;
  20518. module.performance.display();
  20519. module.debug('History change event', tabPath, event);
  20520. historyEvent = event;
  20521. if(tabPath !== undefined) {
  20522. module.changeTab(tabPath);
  20523. }
  20524. if(pageTitle) {
  20525. $.address.title(pageTitle);
  20526. }
  20527. }
  20528. }
  20529. },
  20530. refresh: function() {
  20531. if(activeTabPath) {
  20532. module.debug('Refreshing tab', activeTabPath);
  20533. module.changeTab(activeTabPath);
  20534. }
  20535. },
  20536. cache: {
  20537. read: function(cacheKey) {
  20538. return (cacheKey !== undefined)
  20539. ? cache[cacheKey]
  20540. : false
  20541. ;
  20542. },
  20543. add: function(cacheKey, content) {
  20544. cacheKey = cacheKey || activeTabPath;
  20545. module.debug('Adding cached content for', cacheKey);
  20546. cache[cacheKey] = content;
  20547. },
  20548. remove: function(cacheKey) {
  20549. cacheKey = cacheKey || activeTabPath;
  20550. module.debug('Removing cached content for', cacheKey);
  20551. delete cache[cacheKey];
  20552. }
  20553. },
  20554. escape: {
  20555. string: function(text) {
  20556. text = String(text);
  20557. return text.replace(regExp.escape, '\\$&');
  20558. }
  20559. },
  20560. set: {
  20561. auto: function() {
  20562. var
  20563. url = (typeof settings.path == 'string')
  20564. ? settings.path.replace(/\/$/, '') + '/{$tab}'
  20565. : '/{$tab}'
  20566. ;
  20567. module.verbose('Setting up automatic tab retrieval from server', url);
  20568. if($.isPlainObject(settings.apiSettings)) {
  20569. settings.apiSettings.url = url;
  20570. }
  20571. else {
  20572. settings.apiSettings = {
  20573. url: url
  20574. };
  20575. }
  20576. },
  20577. loading: function(tabPath) {
  20578. var
  20579. $tab = module.get.tabElement(tabPath),
  20580. isLoading = $tab.hasClass(className.loading)
  20581. ;
  20582. if(!isLoading) {
  20583. module.verbose('Setting loading state for', $tab);
  20584. $tab
  20585. .addClass(className.loading)
  20586. .siblings($tabs)
  20587. .removeClass(className.active + ' ' + className.loading)
  20588. ;
  20589. if($tab.length > 0) {
  20590. settings.onRequest.call($tab[0], tabPath);
  20591. }
  20592. }
  20593. },
  20594. state: function(state) {
  20595. $.address.value(state);
  20596. }
  20597. },
  20598. changeTab: function(tabPath) {
  20599. var
  20600. pushStateAvailable = (window.history && window.history.pushState),
  20601. shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
  20602. remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
  20603. // only add default path if not remote content
  20604. pathArray = (remoteContent && !shouldIgnoreLoad)
  20605. ? module.utilities.pathToArray(tabPath)
  20606. : module.get.defaultPathArray(tabPath)
  20607. ;
  20608. tabPath = module.utilities.arrayToPath(pathArray);
  20609. $.each(pathArray, function(index, tab) {
  20610. var
  20611. currentPathArray = pathArray.slice(0, index + 1),
  20612. currentPath = module.utilities.arrayToPath(currentPathArray),
  20613. isTab = module.is.tab(currentPath),
  20614. isLastIndex = (index + 1 == pathArray.length),
  20615. $tab = module.get.tabElement(currentPath),
  20616. $anchor,
  20617. nextPathArray,
  20618. nextPath,
  20619. isLastTab
  20620. ;
  20621. module.verbose('Looking for tab', tab);
  20622. if(isTab) {
  20623. module.verbose('Tab was found', tab);
  20624. // scope up
  20625. activeTabPath = currentPath;
  20626. parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
  20627. if(isLastIndex) {
  20628. isLastTab = true;
  20629. }
  20630. else {
  20631. nextPathArray = pathArray.slice(0, index + 2);
  20632. nextPath = module.utilities.arrayToPath(nextPathArray);
  20633. isLastTab = ( !module.is.tab(nextPath) );
  20634. if(isLastTab) {
  20635. module.verbose('Tab parameters found', nextPathArray);
  20636. }
  20637. }
  20638. if(isLastTab && remoteContent) {
  20639. if(!shouldIgnoreLoad) {
  20640. module.activate.navigation(currentPath);
  20641. module.fetch.content(currentPath, tabPath);
  20642. }
  20643. else {
  20644. module.debug('Ignoring remote content on first tab load', currentPath);
  20645. firstLoad = false;
  20646. module.cache.add(tabPath, $tab.html());
  20647. module.activate.all(currentPath);
  20648. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20649. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20650. }
  20651. return false;
  20652. }
  20653. else {
  20654. module.debug('Opened local tab', currentPath);
  20655. module.activate.all(currentPath);
  20656. if( !module.cache.read(currentPath) ) {
  20657. module.cache.add(currentPath, true);
  20658. module.debug('First time tab loaded calling tab init');
  20659. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20660. }
  20661. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20662. }
  20663. }
  20664. else if(tabPath.search('/') == -1 && tabPath !== '') {
  20665. // look for in page anchor
  20666. tabPath = module.escape.string(tabPath);
  20667. $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
  20668. currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
  20669. $tab = module.get.tabElement(currentPath);
  20670. // if anchor exists use parent tab
  20671. if($anchor && $anchor.length > 0 && currentPath) {
  20672. module.debug('Anchor link used, opening parent tab', $tab, $anchor);
  20673. if( !$tab.hasClass(className.active) ) {
  20674. setTimeout(function() {
  20675. module.scrollTo($anchor);
  20676. }, 0);
  20677. }
  20678. module.activate.all(currentPath);
  20679. if( !module.cache.read(currentPath) ) {
  20680. module.cache.add(currentPath, true);
  20681. module.debug('First time tab loaded calling tab init');
  20682. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20683. }
  20684. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  20685. return false;
  20686. }
  20687. }
  20688. else {
  20689. module.error(error.missingTab, $module, $context, currentPath);
  20690. return false;
  20691. }
  20692. });
  20693. },
  20694. scrollTo: function($element) {
  20695. var
  20696. scrollOffset = ($element && $element.length > 0)
  20697. ? $element.offset().top
  20698. : false
  20699. ;
  20700. if(scrollOffset !== false) {
  20701. module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
  20702. $(document).scrollTop(scrollOffset);
  20703. }
  20704. },
  20705. update: {
  20706. content: function(tabPath, html, evaluateScripts) {
  20707. var
  20708. $tab = module.get.tabElement(tabPath),
  20709. tab = $tab[0]
  20710. ;
  20711. evaluateScripts = (evaluateScripts !== undefined)
  20712. ? evaluateScripts
  20713. : settings.evaluateScripts
  20714. ;
  20715. if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') {
  20716. $tab
  20717. .empty()
  20718. .append($(html).clone(true))
  20719. ;
  20720. }
  20721. else {
  20722. if(evaluateScripts) {
  20723. module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
  20724. $tab.html(html);
  20725. }
  20726. else {
  20727. module.debug('Updating HTML', tabPath, html);
  20728. tab.innerHTML = html;
  20729. }
  20730. }
  20731. }
  20732. },
  20733. fetch: {
  20734. content: function(tabPath, fullTabPath) {
  20735. var
  20736. $tab = module.get.tabElement(tabPath),
  20737. apiSettings = {
  20738. dataType : 'html',
  20739. encodeParameters : false,
  20740. on : 'now',
  20741. cache : settings.alwaysRefresh,
  20742. headers : {
  20743. 'X-Remote': true
  20744. },
  20745. onSuccess : function(response) {
  20746. if(settings.cacheType == 'response') {
  20747. module.cache.add(fullTabPath, response);
  20748. }
  20749. module.update.content(tabPath, response);
  20750. if(tabPath == activeTabPath) {
  20751. module.debug('Content loaded', tabPath);
  20752. module.activate.tab(tabPath);
  20753. }
  20754. else {
  20755. module.debug('Content loaded in background', tabPath);
  20756. }
  20757. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  20758. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  20759. if(settings.loadOnce) {
  20760. module.cache.add(fullTabPath, true);
  20761. }
  20762. else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) {
  20763. setTimeout(function() {
  20764. var
  20765. $clone = $tab.children().clone(true)
  20766. ;
  20767. $clone = $clone.not('script');
  20768. module.cache.add(fullTabPath, $clone);
  20769. }, 0);
  20770. }
  20771. else {
  20772. module.cache.add(fullTabPath, $tab.html());
  20773. }
  20774. },
  20775. urlData: {
  20776. tab: fullTabPath
  20777. }
  20778. },
  20779. request = $tab.api('get request') || false,
  20780. existingRequest = ( request && request.state() === 'pending' ),
  20781. requestSettings,
  20782. cachedContent
  20783. ;
  20784. fullTabPath = fullTabPath || tabPath;
  20785. cachedContent = module.cache.read(fullTabPath);
  20786. if(settings.cache && cachedContent) {
  20787. module.activate.tab(tabPath);
  20788. module.debug('Adding cached content', fullTabPath);
  20789. if(!settings.loadOnce) {
  20790. if(settings.evaluateScripts == 'once') {
  20791. module.update.content(tabPath, cachedContent, false);
  20792. }
  20793. else {
  20794. module.update.content(tabPath, cachedContent);
  20795. }
  20796. }
  20797. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  20798. }
  20799. else if(existingRequest) {
  20800. module.set.loading(tabPath);
  20801. module.debug('Content is already loading', fullTabPath);
  20802. }
  20803. else if($.api !== undefined) {
  20804. requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
  20805. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  20806. module.set.loading(tabPath);
  20807. $tab.api(requestSettings);
  20808. }
  20809. else {
  20810. module.error(error.api);
  20811. }
  20812. }
  20813. },
  20814. activate: {
  20815. all: function(tabPath) {
  20816. module.activate.tab(tabPath);
  20817. module.activate.navigation(tabPath);
  20818. },
  20819. tab: function(tabPath) {
  20820. var
  20821. $tab = module.get.tabElement(tabPath),
  20822. $deactiveTabs = (settings.deactivate == 'siblings')
  20823. ? $tab.siblings($tabs)
  20824. : $tabs.not($tab),
  20825. isActive = $tab.hasClass(className.active)
  20826. ;
  20827. module.verbose('Showing tab content for', $tab);
  20828. if(!isActive) {
  20829. $tab
  20830. .addClass(className.active)
  20831. ;
  20832. $deactiveTabs
  20833. .removeClass(className.active + ' ' + className.loading)
  20834. ;
  20835. if($tab.length > 0) {
  20836. settings.onVisible.call($tab[0], tabPath);
  20837. }
  20838. }
  20839. },
  20840. navigation: function(tabPath) {
  20841. var
  20842. $navigation = module.get.navElement(tabPath),
  20843. $deactiveNavigation = (settings.deactivate == 'siblings')
  20844. ? $navigation.siblings($allModules)
  20845. : $allModules.not($navigation),
  20846. isActive = $navigation.hasClass(className.active)
  20847. ;
  20848. module.verbose('Activating tab navigation for', $navigation, tabPath);
  20849. if(!isActive) {
  20850. $navigation
  20851. .addClass(className.active)
  20852. ;
  20853. $deactiveNavigation
  20854. .removeClass(className.active + ' ' + className.loading)
  20855. ;
  20856. }
  20857. }
  20858. },
  20859. deactivate: {
  20860. all: function() {
  20861. module.deactivate.navigation();
  20862. module.deactivate.tabs();
  20863. },
  20864. navigation: function() {
  20865. $allModules
  20866. .removeClass(className.active)
  20867. ;
  20868. },
  20869. tabs: function() {
  20870. $tabs
  20871. .removeClass(className.active + ' ' + className.loading)
  20872. ;
  20873. }
  20874. },
  20875. is: {
  20876. tab: function(tabName) {
  20877. return (tabName !== undefined)
  20878. ? ( module.get.tabElement(tabName).length > 0 )
  20879. : false
  20880. ;
  20881. }
  20882. },
  20883. get: {
  20884. initialPath: function() {
  20885. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  20886. },
  20887. path: function() {
  20888. return $.address.value();
  20889. },
  20890. // adds default tabs to tab path
  20891. defaultPathArray: function(tabPath) {
  20892. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  20893. },
  20894. defaultPath: function(tabPath) {
  20895. var
  20896. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + module.escape.string(tabPath) + '/"]').eq(0),
  20897. defaultTab = $defaultNav.data(metadata.tab) || false
  20898. ;
  20899. if( defaultTab ) {
  20900. module.debug('Found default tab', defaultTab);
  20901. if(recursionDepth < settings.maxDepth) {
  20902. recursionDepth++;
  20903. return module.get.defaultPath(defaultTab);
  20904. }
  20905. module.error(error.recursion);
  20906. }
  20907. else {
  20908. module.debug('No default tabs found for', tabPath, $tabs);
  20909. }
  20910. recursionDepth = 0;
  20911. return tabPath;
  20912. },
  20913. navElement: function(tabPath) {
  20914. tabPath = tabPath || activeTabPath;
  20915. return $allModules.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]');
  20916. },
  20917. tabElement: function(tabPath) {
  20918. var
  20919. $fullPathTab,
  20920. $simplePathTab,
  20921. tabPathArray,
  20922. lastTab
  20923. ;
  20924. tabPath = tabPath || activeTabPath;
  20925. tabPathArray = module.utilities.pathToArray(tabPath);
  20926. lastTab = module.utilities.last(tabPathArray);
  20927. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]');
  20928. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + module.escape.string(lastTab) + '"]');
  20929. return ($fullPathTab.length > 0)
  20930. ? $fullPathTab
  20931. : $simplePathTab
  20932. ;
  20933. },
  20934. tab: function() {
  20935. return activeTabPath;
  20936. }
  20937. },
  20938. determine: {
  20939. activeTab: function() {
  20940. var activeTab = null;
  20941. $tabs.each(function(_index, tab) {
  20942. var $tab = $(tab);
  20943. if( $tab.hasClass(className.active) ) {
  20944. var
  20945. tabPath = $(this).data(metadata.tab),
  20946. $anchor = $allModules.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]')
  20947. ;
  20948. if( $anchor.hasClass(className.active) ) {
  20949. activeTab = tabPath;
  20950. }
  20951. }
  20952. });
  20953. return activeTab;
  20954. }
  20955. },
  20956. utilities: {
  20957. filterArray: function(keepArray, removeArray) {
  20958. return $.grep(keepArray, function(keepValue) {
  20959. return ( $.inArray(keepValue, removeArray) == -1);
  20960. });
  20961. },
  20962. last: function(array) {
  20963. return Array.isArray(array)
  20964. ? array[ array.length - 1]
  20965. : false
  20966. ;
  20967. },
  20968. pathToArray: function(pathName) {
  20969. if(pathName === undefined) {
  20970. pathName = activeTabPath;
  20971. }
  20972. return typeof pathName == 'string'
  20973. ? pathName.split('/')
  20974. : [pathName]
  20975. ;
  20976. },
  20977. arrayToPath: function(pathArray) {
  20978. return Array.isArray(pathArray)
  20979. ? pathArray.join('/')
  20980. : false
  20981. ;
  20982. }
  20983. },
  20984. setting: function(name, value) {
  20985. module.debug('Changing setting', name, value);
  20986. if( $.isPlainObject(name) ) {
  20987. $.extend(true, settings, name);
  20988. }
  20989. else if(value !== undefined) {
  20990. if($.isPlainObject(settings[name])) {
  20991. $.extend(true, settings[name], value);
  20992. }
  20993. else {
  20994. settings[name] = value;
  20995. }
  20996. }
  20997. else {
  20998. return settings[name];
  20999. }
  21000. },
  21001. internal: function(name, value) {
  21002. if( $.isPlainObject(name) ) {
  21003. $.extend(true, module, name);
  21004. }
  21005. else if(value !== undefined) {
  21006. module[name] = value;
  21007. }
  21008. else {
  21009. return module[name];
  21010. }
  21011. },
  21012. debug: function() {
  21013. if(!settings.silent && settings.debug) {
  21014. if(settings.performance) {
  21015. module.performance.log(arguments);
  21016. }
  21017. else {
  21018. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21019. module.debug.apply(console, arguments);
  21020. }
  21021. }
  21022. },
  21023. verbose: function() {
  21024. if(!settings.silent && settings.verbose && settings.debug) {
  21025. if(settings.performance) {
  21026. module.performance.log(arguments);
  21027. }
  21028. else {
  21029. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21030. module.verbose.apply(console, arguments);
  21031. }
  21032. }
  21033. },
  21034. error: function() {
  21035. if(!settings.silent) {
  21036. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  21037. module.error.apply(console, arguments);
  21038. }
  21039. },
  21040. performance: {
  21041. log: function(message) {
  21042. var
  21043. currentTime,
  21044. executionTime,
  21045. previousTime
  21046. ;
  21047. if(settings.performance) {
  21048. currentTime = new Date().getTime();
  21049. previousTime = time || currentTime;
  21050. executionTime = currentTime - previousTime;
  21051. time = currentTime;
  21052. performance.push({
  21053. 'Name' : message[0],
  21054. 'Arguments' : [].slice.call(message, 1) || '',
  21055. 'Element' : element,
  21056. 'Execution Time' : executionTime
  21057. });
  21058. }
  21059. clearTimeout(module.performance.timer);
  21060. module.performance.timer = setTimeout(module.performance.display, 500);
  21061. },
  21062. display: function() {
  21063. var
  21064. title = settings.name + ':',
  21065. totalTime = 0
  21066. ;
  21067. time = false;
  21068. clearTimeout(module.performance.timer);
  21069. $.each(performance, function(index, data) {
  21070. totalTime += data['Execution Time'];
  21071. });
  21072. title += ' ' + totalTime + 'ms';
  21073. if(moduleSelector) {
  21074. title += ' \'' + moduleSelector + '\'';
  21075. }
  21076. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  21077. console.groupCollapsed(title);
  21078. if(console.table) {
  21079. console.table(performance);
  21080. }
  21081. else {
  21082. $.each(performance, function(index, data) {
  21083. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  21084. });
  21085. }
  21086. console.groupEnd();
  21087. }
  21088. performance = [];
  21089. }
  21090. },
  21091. invoke: function(query, passedArguments, context) {
  21092. var
  21093. object = instance,
  21094. maxDepth,
  21095. found,
  21096. response
  21097. ;
  21098. passedArguments = passedArguments || queryArguments;
  21099. context = element || context;
  21100. if(typeof query == 'string' && object !== undefined) {
  21101. query = query.split(/[\. ]/);
  21102. maxDepth = query.length - 1;
  21103. $.each(query, function(depth, value) {
  21104. var camelCaseValue = (depth != maxDepth)
  21105. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  21106. : query
  21107. ;
  21108. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  21109. object = object[camelCaseValue];
  21110. }
  21111. else if( object[camelCaseValue] !== undefined ) {
  21112. found = object[camelCaseValue];
  21113. return false;
  21114. }
  21115. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  21116. object = object[value];
  21117. }
  21118. else if( object[value] !== undefined ) {
  21119. found = object[value];
  21120. return false;
  21121. }
  21122. else {
  21123. module.error(error.method, query);
  21124. return false;
  21125. }
  21126. });
  21127. }
  21128. if ( $.isFunction( found ) ) {
  21129. response = found.apply(context, passedArguments);
  21130. }
  21131. else if(found !== undefined) {
  21132. response = found;
  21133. }
  21134. if(Array.isArray(returnedValue)) {
  21135. returnedValue.push(response);
  21136. }
  21137. else if(returnedValue !== undefined) {
  21138. returnedValue = [returnedValue, response];
  21139. }
  21140. else if(response !== undefined) {
  21141. returnedValue = response;
  21142. }
  21143. return found;
  21144. }
  21145. };
  21146. if(methodInvoked) {
  21147. if(instance === undefined) {
  21148. module.initialize();
  21149. }
  21150. module.invoke(query);
  21151. }
  21152. else {
  21153. if(instance !== undefined) {
  21154. instance.invoke('destroy');
  21155. }
  21156. module.initialize();
  21157. }
  21158. })
  21159. ;
  21160. return (returnedValue !== undefined)
  21161. ? returnedValue
  21162. : this
  21163. ;
  21164. };
  21165. // shortcut for tabbed content with no defined navigation
  21166. $.tab = function() {
  21167. $(window).tab.apply(this, arguments);
  21168. };
  21169. $.fn.tab.settings = {
  21170. name : 'Tab',
  21171. namespace : 'tab',
  21172. silent : false,
  21173. debug : false,
  21174. verbose : false,
  21175. performance : true,
  21176. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  21177. history : false, // use browser history
  21178. historyType : 'hash', // #/ or html5 state
  21179. path : false, // base path of url
  21180. context : false, // specify a context that tabs must appear inside
  21181. childrenOnly : false, // use only tabs that are children of context
  21182. maxDepth : 25, // max depth a tab can be nested
  21183. deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together
  21184. alwaysRefresh : false, // load tab content new every tab click
  21185. cache : true, // cache the content requests to pull locally
  21186. loadOnce : false, // Whether tab data should only be loaded once when using remote content
  21187. cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute
  21188. ignoreFirstLoad : false, // don't load remote content on first load
  21189. apiSettings : false, // settings for api call
  21190. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  21191. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  21192. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  21193. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  21194. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  21195. templates : {
  21196. determineTitle: function(tabArray) {} // returns page title for path
  21197. },
  21198. error: {
  21199. api : 'You attempted to load content without API module',
  21200. method : 'The method you called is not defined',
  21201. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  21202. noContent : 'The tab you specified is missing a content url.',
  21203. path : 'History enabled, but no path was specified',
  21204. recursion : 'Max recursive depth reached',
  21205. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  21206. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  21207. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  21208. },
  21209. regExp : {
  21210. escape : /[-[\]{}()*+?.,\\^$|#\s:=@]/g
  21211. },
  21212. metadata : {
  21213. tab : 'tab',
  21214. loaded : 'loaded',
  21215. promise: 'promise'
  21216. },
  21217. className : {
  21218. loading : 'loading',
  21219. active : 'active'
  21220. },
  21221. selector : {
  21222. tabs : '.ui.tab',
  21223. ui : '.ui'
  21224. }
  21225. };
  21226. })( jQuery, window, document );
  21227. /*!
  21228. * # Fomantic-UI - Toast
  21229. * http://github.com/fomantic/Fomantic-UI/
  21230. *
  21231. *
  21232. * Released under the MIT license
  21233. * http://opensource.org/licenses/MIT
  21234. *
  21235. */
  21236. ;(function ($, window, document, undefined) {
  21237. 'use strict';
  21238. $.isFunction = $.isFunction || function(obj) {
  21239. return typeof obj === "function" && typeof obj.nodeType !== "number";
  21240. };
  21241. window = (typeof window != 'undefined' && window.Math == Math)
  21242. ? window
  21243. : (typeof self != 'undefined' && self.Math == Math)
  21244. ? self
  21245. : Function('return this')()
  21246. ;
  21247. $.fn.toast = function(parameters) {
  21248. var
  21249. $allModules = $(this),
  21250. moduleSelector = $allModules.selector || '',
  21251. time = new Date().getTime(),
  21252. performance = [],
  21253. query = arguments[0],
  21254. methodInvoked = (typeof query == 'string'),
  21255. queryArguments = [].slice.call(arguments, 1),
  21256. returnedValue
  21257. ;
  21258. $allModules
  21259. .each(function() {
  21260. var
  21261. settings = ( $.isPlainObject(parameters) )
  21262. ? $.extend(true, {}, $.fn.toast.settings, parameters)
  21263. : $.extend({}, $.fn.toast.settings),
  21264. className = settings.className,
  21265. selector = settings.selector,
  21266. error = settings.error,
  21267. namespace = settings.namespace,
  21268. fields = settings.fields,
  21269. eventNamespace = '.' + namespace,
  21270. moduleNamespace = namespace + '-module',
  21271. $module = $(this),
  21272. $toastBox,
  21273. $toast,
  21274. $actions,
  21275. $progress,
  21276. $progressBar,
  21277. $animationObject,
  21278. $close,
  21279. $context = (settings.context)
  21280. ? $(settings.context)
  21281. : $('body'),
  21282. isToastComponent = $module.hasClass('toast') || $module.hasClass('message') || $module.hasClass('card'),
  21283. element = this,
  21284. instance = isToastComponent ? $module.data(moduleNamespace) : undefined,
  21285. module
  21286. ;
  21287. module = {
  21288. initialize: function() {
  21289. module.verbose('Initializing element');
  21290. if (!module.has.container()) {
  21291. module.create.container();
  21292. }
  21293. if(isToastComponent || settings.message !== '' || settings.title !== '' || module.get.iconClass() !== '' || settings.showImage || module.has.configActions()) {
  21294. if(typeof settings.showProgress !== 'string' || [className.top,className.bottom].indexOf(settings.showProgress) === -1 ) {
  21295. settings.showProgress = false;
  21296. }
  21297. module.create.toast();
  21298. if(settings.closeOnClick && (settings.closeIcon || $($toast).find(selector.input).length > 0 || module.has.configActions())){
  21299. settings.closeOnClick = false;
  21300. }
  21301. if(!settings.closeOnClick) {
  21302. $toastBox.addClass(className.unclickable);
  21303. }
  21304. module.bind.events();
  21305. }
  21306. module.instantiate();
  21307. if($toastBox) {
  21308. module.show();
  21309. }
  21310. },
  21311. instantiate: function() {
  21312. module.verbose('Storing instance of toast');
  21313. instance = module;
  21314. $module
  21315. .data(moduleNamespace, instance)
  21316. ;
  21317. },
  21318. destroy: function() {
  21319. if($toastBox) {
  21320. module.debug('Removing toast', $toastBox);
  21321. module.unbind.events();
  21322. $toastBox.remove();
  21323. $toastBox = undefined;
  21324. $toast = undefined;
  21325. $animationObject = undefined;
  21326. settings.onRemove.call($toastBox, element);
  21327. $progress = undefined;
  21328. $progressBar = undefined;
  21329. $close = undefined;
  21330. }
  21331. $module
  21332. .removeData(moduleNamespace)
  21333. ;
  21334. },
  21335. show: function(callback) {
  21336. callback = callback || function(){};
  21337. module.debug('Showing toast');
  21338. if(settings.onShow.call($toastBox, element) === false) {
  21339. module.debug('onShow callback returned false, cancelling toast animation');
  21340. return;
  21341. }
  21342. module.animate.show(callback);
  21343. },
  21344. close: function(callback) {
  21345. callback = callback || function(){};
  21346. module.remove.visible();
  21347. module.unbind.events();
  21348. module.animate.close(callback);
  21349. },
  21350. create: {
  21351. container: function() {
  21352. module.verbose('Creating container');
  21353. $context.append($('<div/>',{class: settings.position + ' ' + className.container}));
  21354. },
  21355. toast: function() {
  21356. $toastBox = $('<div/>', {class: className.box});
  21357. if (!isToastComponent) {
  21358. module.verbose('Creating toast');
  21359. $toast = $('<div/>');
  21360. var $content = $('<div/>', {class: className.content});
  21361. var iconClass = module.get.iconClass();
  21362. if (iconClass !== '') {
  21363. $toast.append($('<i/>', {class: iconClass + ' ' + className.icon}));
  21364. }
  21365. if (settings.showImage) {
  21366. $toast.append($('<img>', {
  21367. class: className.image + ' ' + settings.classImage,
  21368. src: settings.showImage
  21369. }));
  21370. }
  21371. if (settings.title !== '') {
  21372. $content.append($('<div/>', {
  21373. class: className.title,
  21374. text: settings.title
  21375. }));
  21376. }
  21377. $content.append($('<div/>', {html: module.helpers.escape(settings.message, settings.preserveHTML)}));
  21378. $toast
  21379. .addClass(settings.class + ' ' + className.toast)
  21380. .append($content)
  21381. ;
  21382. $toast.css('opacity', settings.opacity);
  21383. if (settings.closeIcon) {
  21384. $close = $('<i/>', {class: className.close + ' ' + (typeof settings.closeIcon === 'string' ? settings.closeIcon : '')});
  21385. if($close.hasClass(className.left)) {
  21386. $toast.prepend($close);
  21387. } else {
  21388. $toast.append($close);
  21389. }
  21390. }
  21391. } else {
  21392. $toast = settings.cloneModule ? $module.clone().removeAttr('id') : $module;
  21393. $close = $toast.find('> i'+module.helpers.toClass(className.close));
  21394. settings.closeIcon = ($close.length > 0);
  21395. }
  21396. if ($toast.hasClass(className.compact)) {
  21397. settings.compact = true;
  21398. }
  21399. if ($toast.hasClass('card')) {
  21400. settings.compact = false;
  21401. }
  21402. $actions = $toast.find('.actions');
  21403. if (module.has.configActions()) {
  21404. if ($actions.length === 0) {
  21405. $actions = $('<div/>', {class: className.actions + ' ' + (settings.classActions || '')}).appendTo($toast);
  21406. }
  21407. if($toast.hasClass('card') && !$actions.hasClass(className.attached)) {
  21408. $actions.addClass(className.extraContent);
  21409. if($actions.hasClass(className.vertical)) {
  21410. $actions.removeClass(className.vertical);
  21411. module.error(error.verticalCard);
  21412. }
  21413. }
  21414. settings.actions.forEach(function (el) {
  21415. var icon = el[fields.icon] ? '<i class="' + module.helpers.deQuote(el[fields.icon]) + ' icon"></i>' : '',
  21416. text = module.helpers.escape(el[fields.text] || '', settings.preserveHTML),
  21417. cls = module.helpers.deQuote(el[fields.class] || ''),
  21418. click = el[fields.click] && $.isFunction(el[fields.click]) ? el[fields.click] : function () {};
  21419. $actions.append($('<button/>', {
  21420. html: icon + text,
  21421. class: className.button + ' ' + cls,
  21422. click: function () {
  21423. if (click.call(element, $module) === false) {
  21424. return;
  21425. }
  21426. module.close();
  21427. }
  21428. }));
  21429. });
  21430. }
  21431. if ($actions && $actions.hasClass(className.vertical)) {
  21432. $toast.addClass(className.vertical);
  21433. }
  21434. if($actions.length > 0 && !$actions.hasClass(className.attached)) {
  21435. if ($actions && (!$actions.hasClass(className.basic) || $actions.hasClass(className.left))) {
  21436. $toast.addClass(className.actions);
  21437. }
  21438. }
  21439. if(settings.displayTime === 'auto'){
  21440. settings.displayTime = Math.max(settings.minDisplayTime, $toast.text().split(" ").length / settings.wordsPerMinute * 60000);
  21441. }
  21442. $toastBox.append($toast);
  21443. if($actions.length > 0 && $actions.hasClass(className.attached)) {
  21444. $actions.addClass(className.buttons);
  21445. $actions.detach();
  21446. $toast.addClass(className.attached);
  21447. if (!$actions.hasClass(className.vertical)) {
  21448. if ($actions.hasClass(className.top)) {
  21449. $toastBox.prepend($actions);
  21450. $toast.addClass(className.bottom);
  21451. } else {
  21452. $toastBox.append($actions);
  21453. $toast.addClass(className.top);
  21454. }
  21455. } else {
  21456. $toast.wrap(
  21457. $('<div/>',{
  21458. class:className.vertical + ' ' +
  21459. className.attached + ' ' +
  21460. (settings.compact ? className.compact : '')
  21461. })
  21462. );
  21463. if($actions.hasClass(className.left)) {
  21464. $toast.addClass(className.left).parent().addClass(className.left).prepend($actions);
  21465. } else {
  21466. $toast.parent().append($actions);
  21467. }
  21468. }
  21469. }
  21470. if($module !== $toast) {
  21471. $module = $toast;
  21472. element = $toast[0];
  21473. }
  21474. if(settings.displayTime > 0) {
  21475. var progressingClass = className.progressing+' '+(settings.pauseOnHover ? className.pausable:'');
  21476. if (!!settings.showProgress) {
  21477. $progress = $('<div/>', {
  21478. class: className.progress + ' ' + (settings.classProgress || settings.class),
  21479. 'data-percent': ''
  21480. });
  21481. if(!settings.classProgress) {
  21482. if ($toast.hasClass('toast') && !$toast.hasClass(className.inverted)) {
  21483. $progress.addClass(className.inverted);
  21484. } else {
  21485. $progress.removeClass(className.inverted);
  21486. }
  21487. }
  21488. $progressBar = $('<div/>', {class: 'bar '+(settings.progressUp ? 'up ' : 'down ')+progressingClass});
  21489. $progress
  21490. .addClass(settings.showProgress)
  21491. .append($progressBar);
  21492. if ($progress.hasClass(className.top)) {
  21493. $toastBox.prepend($progress);
  21494. } else {
  21495. $toastBox.append($progress);
  21496. }
  21497. $progressBar.css('animation-duration', settings.displayTime / 1000 + 's');
  21498. }
  21499. $animationObject = $('<span/>',{class:'wait '+progressingClass});
  21500. $animationObject.css('animation-duration', settings.displayTime / 1000 + 's');
  21501. $animationObject.appendTo($toast);
  21502. }
  21503. if (settings.compact) {
  21504. $toastBox.addClass(className.compact);
  21505. $toast.addClass(className.compact);
  21506. if($progress) {
  21507. $progress.addClass(className.compact);
  21508. }
  21509. }
  21510. if (settings.newestOnTop) {
  21511. $toastBox.prependTo(module.get.container());
  21512. }
  21513. else {
  21514. $toastBox.appendTo(module.get.container());
  21515. }
  21516. }
  21517. },
  21518. bind: {
  21519. events: function() {
  21520. module.debug('Binding events to toast');
  21521. if(settings.closeOnClick || settings.closeIcon) {
  21522. (settings.closeIcon ? $close : $toast)
  21523. .on('click' + eventNamespace, module.event.click)
  21524. ;
  21525. }
  21526. if($animationObject) {
  21527. $animationObject.on('animationend' + eventNamespace, module.close);
  21528. }
  21529. $toastBox
  21530. .on('click' + eventNamespace, selector.approve, module.event.approve)
  21531. .on('click' + eventNamespace, selector.deny, module.event.deny)
  21532. ;
  21533. }
  21534. },
  21535. unbind: {
  21536. events: function() {
  21537. module.debug('Unbinding events to toast');
  21538. if(settings.closeOnClick || settings.closeIcon) {
  21539. (settings.closeIcon ? $close : $toast)
  21540. .off('click' + eventNamespace)
  21541. ;
  21542. }
  21543. if($animationObject) {
  21544. $animationObject.off('animationend' + eventNamespace);
  21545. }
  21546. $toastBox
  21547. .off('click' + eventNamespace)
  21548. ;
  21549. }
  21550. },
  21551. animate: {
  21552. show: function(callback) {
  21553. callback = $.isFunction(callback) ? callback : function(){};
  21554. if(settings.transition && module.can.useElement('transition') && $module.transition('is supported')) {
  21555. module.set.visible();
  21556. $toastBox
  21557. .transition({
  21558. animation : settings.transition.showMethod + ' in',
  21559. queue : false,
  21560. debug : settings.debug,
  21561. verbose : settings.verbose,
  21562. duration : settings.transition.showDuration,
  21563. onComplete : function() {
  21564. callback.call($toastBox, element);
  21565. settings.onVisible.call($toastBox, element);
  21566. }
  21567. })
  21568. ;
  21569. }
  21570. },
  21571. close: function(callback) {
  21572. callback = $.isFunction(callback) ? callback : function(){};
  21573. module.debug('Closing toast');
  21574. if(settings.onHide.call($toastBox, element) === false) {
  21575. module.debug('onHide callback returned false, cancelling toast animation');
  21576. return;
  21577. }
  21578. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  21579. $toastBox
  21580. .transition({
  21581. animation : settings.transition.hideMethod + ' out',
  21582. queue : false,
  21583. duration : settings.transition.hideDuration,
  21584. debug : settings.debug,
  21585. verbose : settings.verbose,
  21586. interval : 50,
  21587. onBeforeHide: function(callback){
  21588. callback = $.isFunction(callback)?callback : function(){};
  21589. if(settings.transition.closeEasing !== ''){
  21590. $toastBox.css('opacity',0);
  21591. $toastBox.wrap('<div/>').parent().slideUp(500,settings.transition.closeEasing,function(){
  21592. if($toastBox){
  21593. $toastBox.parent().remove();
  21594. callback.call($toastBox);
  21595. }
  21596. });
  21597. } else {
  21598. callback.call($toastBox);
  21599. }
  21600. },
  21601. onComplete : function() {
  21602. callback.call($toastBox, element);
  21603. settings.onHidden.call($toastBox, element);
  21604. module.destroy();
  21605. }
  21606. })
  21607. ;
  21608. }
  21609. else {
  21610. module.error(error.noTransition);
  21611. }
  21612. },
  21613. pause: function() {
  21614. $animationObject.css('animationPlayState','paused');
  21615. if($progressBar) {
  21616. $progressBar.css('animationPlayState', 'paused');
  21617. }
  21618. },
  21619. continue: function() {
  21620. $animationObject.css('animationPlayState','running');
  21621. if($progressBar) {
  21622. $progressBar.css('animationPlayState', 'running');
  21623. }
  21624. }
  21625. },
  21626. has: {
  21627. container: function() {
  21628. module.verbose('Determining if there is already a container');
  21629. return ($context.find(module.helpers.toClass(settings.position) + selector.container).length > 0);
  21630. },
  21631. toast: function(){
  21632. return !!module.get.toast();
  21633. },
  21634. toasts: function(){
  21635. return module.get.toasts().length > 0;
  21636. },
  21637. configActions: function () {
  21638. return Array.isArray(settings.actions) && settings.actions.length > 0;
  21639. }
  21640. },
  21641. get: {
  21642. container: function() {
  21643. return ($context.find(module.helpers.toClass(settings.position) + selector.container)[0]);
  21644. },
  21645. toastBox: function() {
  21646. return $toastBox || null;
  21647. },
  21648. toast: function() {
  21649. return $toast || null;
  21650. },
  21651. toasts: function() {
  21652. return $(module.get.container()).find(selector.box);
  21653. },
  21654. iconClass: function() {
  21655. return typeof settings.showIcon === 'string' ? settings.showIcon : settings.showIcon && settings.icons[settings.class] ? settings.icons[settings.class] : '';
  21656. },
  21657. remainingTime: function() {
  21658. return $animationObject ? $animationObject.css('opacity') * settings.displayTime : 0;
  21659. }
  21660. },
  21661. set: {
  21662. visible: function() {
  21663. $toast.addClass(className.visible);
  21664. }
  21665. },
  21666. remove: {
  21667. visible: function() {
  21668. $toast.removeClass(className.visible);
  21669. }
  21670. },
  21671. event: {
  21672. click: function(event) {
  21673. if($(event.target).closest('a').length === 0) {
  21674. settings.onClick.call($toastBox, element);
  21675. module.close();
  21676. }
  21677. },
  21678. approve: function() {
  21679. if(settings.onApprove.call(element, $module) === false) {
  21680. module.verbose('Approve callback returned false cancelling close');
  21681. return;
  21682. }
  21683. module.close();
  21684. },
  21685. deny: function() {
  21686. if(settings.onDeny.call(element, $module) === false) {
  21687. module.verbose('Deny callback returned false cancelling close');
  21688. return;
  21689. }
  21690. module.close();
  21691. }
  21692. },
  21693. helpers: {
  21694. toClass: function(selector) {
  21695. var
  21696. classes = selector.split(' '),
  21697. result = ''
  21698. ;
  21699. classes.forEach(function (element) {
  21700. result += '.' + element;
  21701. });
  21702. return result;
  21703. },
  21704. deQuote: function(string) {
  21705. return String(string).replace(/"/g,"");
  21706. },
  21707. escape: function(string, preserveHTML) {
  21708. if (preserveHTML){
  21709. return string;
  21710. }
  21711. var
  21712. badChars = /[&<>"'`]/g,
  21713. shouldEscape = /[&<>"'`]/,
  21714. escape = {
  21715. "&": "&amp;",
  21716. "<": "&lt;",
  21717. ">": "&gt;",
  21718. '"': "&quot;",
  21719. "'": "&#x27;",
  21720. "`": "&#x60;"
  21721. },
  21722. escapedChar = function(chr) {
  21723. return escape[chr];
  21724. }
  21725. ;
  21726. if(shouldEscape.test(string)) {
  21727. return string.replace(badChars, escapedChar);
  21728. }
  21729. return string;
  21730. }
  21731. },
  21732. can: {
  21733. useElement: function(element){
  21734. if ($.fn[element] !== undefined) {
  21735. return true;
  21736. }
  21737. module.error(error.noElement.replace('{element}',element));
  21738. return false;
  21739. }
  21740. },
  21741. setting: function(name, value) {
  21742. module.debug('Changing setting', name, value);
  21743. if( $.isPlainObject(name) ) {
  21744. $.extend(true, settings, name);
  21745. }
  21746. else if(value !== undefined) {
  21747. if($.isPlainObject(settings[name])) {
  21748. $.extend(true, settings[name], value);
  21749. }
  21750. else {
  21751. settings[name] = value;
  21752. }
  21753. }
  21754. else {
  21755. return settings[name];
  21756. }
  21757. },
  21758. internal: function(name, value) {
  21759. if( $.isPlainObject(name) ) {
  21760. $.extend(true, module, name);
  21761. }
  21762. else if(value !== undefined) {
  21763. module[name] = value;
  21764. }
  21765. else {
  21766. return module[name];
  21767. }
  21768. },
  21769. debug: function() {
  21770. if(!settings.silent && settings.debug) {
  21771. if(settings.performance) {
  21772. module.performance.log(arguments);
  21773. }
  21774. else {
  21775. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21776. module.debug.apply(console, arguments);
  21777. }
  21778. }
  21779. },
  21780. verbose: function() {
  21781. if(!settings.silent && settings.verbose && settings.debug) {
  21782. if(settings.performance) {
  21783. module.performance.log(arguments);
  21784. }
  21785. else {
  21786. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  21787. module.verbose.apply(console, arguments);
  21788. }
  21789. }
  21790. },
  21791. error: function() {
  21792. if(!settings.silent) {
  21793. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  21794. module.error.apply(console, arguments);
  21795. }
  21796. },
  21797. performance: {
  21798. log: function(message) {
  21799. var
  21800. currentTime,
  21801. executionTime,
  21802. previousTime
  21803. ;
  21804. if(settings.performance) {
  21805. currentTime = new Date().getTime();
  21806. previousTime = time || currentTime;
  21807. executionTime = currentTime - previousTime;
  21808. time = currentTime;
  21809. performance.push({
  21810. 'Name' : message[0],
  21811. 'Arguments' : [].slice.call(message, 1) || '',
  21812. 'Element' : element,
  21813. 'Execution Time' : executionTime
  21814. });
  21815. }
  21816. clearTimeout(module.performance.timer);
  21817. module.performance.timer = setTimeout(module.performance.display, 500);
  21818. },
  21819. display: function() {
  21820. var
  21821. title = settings.name + ':',
  21822. totalTime = 0
  21823. ;
  21824. time = false;
  21825. clearTimeout(module.performance.timer);
  21826. $.each(performance, function(index, data) {
  21827. totalTime += data['Execution Time'];
  21828. });
  21829. title += ' ' + totalTime + 'ms';
  21830. if(moduleSelector) {
  21831. title += ' \'' + moduleSelector + '\'';
  21832. }
  21833. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  21834. console.groupCollapsed(title);
  21835. if(console.table) {
  21836. console.table(performance);
  21837. }
  21838. else {
  21839. $.each(performance, function(index, data) {
  21840. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  21841. });
  21842. }
  21843. console.groupEnd();
  21844. }
  21845. performance = [];
  21846. }
  21847. },
  21848. invoke: function(query, passedArguments, context) {
  21849. var
  21850. object = instance,
  21851. maxDepth,
  21852. found,
  21853. response
  21854. ;
  21855. passedArguments = passedArguments || queryArguments;
  21856. context = element || context;
  21857. if(typeof query == 'string' && object !== undefined) {
  21858. query = query.split(/[\. ]/);
  21859. maxDepth = query.length - 1;
  21860. $.each(query, function(depth, value) {
  21861. var camelCaseValue = (depth != maxDepth)
  21862. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  21863. : query
  21864. ;
  21865. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  21866. object = object[camelCaseValue];
  21867. }
  21868. else if( object[camelCaseValue] !== undefined ) {
  21869. found = object[camelCaseValue];
  21870. return false;
  21871. }
  21872. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  21873. object = object[value];
  21874. }
  21875. else if( object[value] !== undefined ) {
  21876. found = object[value];
  21877. return false;
  21878. }
  21879. else {
  21880. module.error(error.method, query);
  21881. return false;
  21882. }
  21883. });
  21884. }
  21885. if ( $.isFunction( found ) ) {
  21886. response = found.apply(context, passedArguments);
  21887. }
  21888. else if(found !== undefined) {
  21889. response = found;
  21890. }
  21891. if(Array.isArray(returnedValue)) {
  21892. returnedValue.push(response);
  21893. }
  21894. else if(returnedValue !== undefined) {
  21895. returnedValue = [returnedValue, response];
  21896. }
  21897. else if(response !== undefined) {
  21898. returnedValue = response;
  21899. }
  21900. return found;
  21901. }
  21902. };
  21903. if(methodInvoked) {
  21904. if(instance === undefined) {
  21905. module.initialize();
  21906. }
  21907. module.invoke(query);
  21908. }
  21909. else {
  21910. if(instance !== undefined) {
  21911. instance.invoke('destroy');
  21912. }
  21913. module.initialize();
  21914. returnedValue = $module;
  21915. }
  21916. })
  21917. ;
  21918. return (returnedValue !== undefined)
  21919. ? returnedValue
  21920. : this
  21921. ;
  21922. };
  21923. $.fn.toast.settings = {
  21924. name : 'Toast',
  21925. namespace : 'toast',
  21926. silent : false,
  21927. debug : false,
  21928. verbose : false,
  21929. performance : true,
  21930. context : 'body',
  21931. position : 'top right',
  21932. class : 'neutral',
  21933. classProgress : false,
  21934. classActions : false,
  21935. classImage : 'mini',
  21936. title : '',
  21937. message : '',
  21938. displayTime : 3000, // set to zero to require manually dismissal, otherwise hides on its own
  21939. minDisplayTime : 1000, // minimum displaytime in case displayTime is set to 'auto'
  21940. wordsPerMinute : 120,
  21941. showIcon : false,
  21942. newestOnTop : false,
  21943. showProgress : false,
  21944. pauseOnHover : true,
  21945. progressUp : false, //if true, the bar will start at 0% and increase to 100%
  21946. opacity : 1,
  21947. compact : true,
  21948. closeIcon : false,
  21949. closeOnClick : true,
  21950. cloneModule : true,
  21951. actions : false,
  21952. preserveHTML : true,
  21953. showImage : false,
  21954. // transition settings
  21955. transition : {
  21956. showMethod : 'scale',
  21957. showDuration : 500,
  21958. hideMethod : 'scale',
  21959. hideDuration : 500,
  21960. closeEasing : 'easeOutCubic' //Set to empty string to stack the closed toast area immediately (old behaviour)
  21961. },
  21962. error: {
  21963. method : 'The method you called is not defined.',
  21964. noElement : 'This module requires ui {element}',
  21965. verticalCard : 'Vertical but not attached actions are not supported for card layout'
  21966. },
  21967. className : {
  21968. container : 'ui toast-container',
  21969. box : 'floating toast-box',
  21970. progress : 'ui attached active progress',
  21971. toast : 'ui toast',
  21972. icon : 'centered icon',
  21973. visible : 'visible',
  21974. content : 'content',
  21975. title : 'ui header',
  21976. actions : 'actions',
  21977. extraContent : 'extra content',
  21978. button : 'ui button',
  21979. buttons : 'ui buttons',
  21980. close : 'close icon',
  21981. image : 'ui image',
  21982. vertical : 'vertical',
  21983. attached : 'attached',
  21984. inverted : 'inverted',
  21985. compact : 'compact',
  21986. pausable : 'pausable',
  21987. progressing : 'progressing',
  21988. top : 'top',
  21989. bottom : 'bottom',
  21990. left : 'left',
  21991. basic : 'basic',
  21992. unclickable : 'unclickable'
  21993. },
  21994. icons : {
  21995. info : 'info',
  21996. success : 'checkmark',
  21997. warning : 'warning',
  21998. error : 'times'
  21999. },
  22000. selector : {
  22001. container : '.ui.toast-container',
  22002. box : '.toast-box',
  22003. toast : '.ui.toast',
  22004. input : 'input:not([type="hidden"]), textarea, select, button, .ui.button, ui.dropdown',
  22005. approve : '.actions .positive, .actions .approve, .actions .ok',
  22006. deny : '.actions .negative, .actions .deny, .actions .cancel'
  22007. },
  22008. fields : {
  22009. class : 'class',
  22010. text : 'text',
  22011. icon : 'icon',
  22012. click : 'click'
  22013. },
  22014. // callbacks
  22015. onShow : function(){},
  22016. onVisible : function(){},
  22017. onClick : function(){},
  22018. onHide : function(){},
  22019. onHidden : function(){},
  22020. onRemove : function(){},
  22021. onApprove : function(){},
  22022. onDeny : function(){}
  22023. };
  22024. $.extend( $.easing, {
  22025. easeOutBounce: function (x, t, b, c, d) {
  22026. if ((t/=d) < (1/2.75)) {
  22027. return c*(7.5625*t*t) + b;
  22028. } else if (t < (2/2.75)) {
  22029. return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
  22030. } else if (t < (2.5/2.75)) {
  22031. return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
  22032. } else {
  22033. return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
  22034. }
  22035. },
  22036. easeOutCubic: function (t) {
  22037. return (--t)*t*t+1;
  22038. }
  22039. });
  22040. })( jQuery, window, document );
  22041. /*!
  22042. * # Fomantic-UI - Transition
  22043. * http://github.com/fomantic/Fomantic-UI/
  22044. *
  22045. *
  22046. * Released under the MIT license
  22047. * http://opensource.org/licenses/MIT
  22048. *
  22049. */
  22050. ;(function ($, window, document, undefined) {
  22051. 'use strict';
  22052. $.isFunction = $.isFunction || function(obj) {
  22053. return typeof obj === "function" && typeof obj.nodeType !== "number";
  22054. };
  22055. window = (typeof window != 'undefined' && window.Math == Math)
  22056. ? window
  22057. : (typeof self != 'undefined' && self.Math == Math)
  22058. ? self
  22059. : Function('return this')()
  22060. ;
  22061. $.fn.transition = function() {
  22062. var
  22063. $allModules = $(this),
  22064. moduleSelector = $allModules.selector || '',
  22065. time = new Date().getTime(),
  22066. performance = [],
  22067. moduleArguments = arguments,
  22068. query = moduleArguments[0],
  22069. queryArguments = [].slice.call(arguments, 1),
  22070. methodInvoked = (typeof query === 'string'),
  22071. returnedValue
  22072. ;
  22073. $allModules
  22074. .each(function(index) {
  22075. var
  22076. $module = $(this),
  22077. element = this,
  22078. // set at run time
  22079. settings,
  22080. instance,
  22081. error,
  22082. className,
  22083. metadata,
  22084. animationEnd,
  22085. moduleNamespace,
  22086. eventNamespace,
  22087. module
  22088. ;
  22089. module = {
  22090. initialize: function() {
  22091. // get full settings
  22092. settings = module.get.settings.apply(element, moduleArguments);
  22093. // shorthand
  22094. className = settings.className;
  22095. error = settings.error;
  22096. metadata = settings.metadata;
  22097. // define namespace
  22098. eventNamespace = '.' + settings.namespace;
  22099. moduleNamespace = 'module-' + settings.namespace;
  22100. instance = $module.data(moduleNamespace) || module;
  22101. // get vendor specific events
  22102. animationEnd = module.get.animationEndEvent();
  22103. if(methodInvoked) {
  22104. methodInvoked = module.invoke(query);
  22105. }
  22106. // method not invoked, lets run an animation
  22107. if(methodInvoked === false) {
  22108. module.verbose('Converted arguments into settings object', settings);
  22109. if(settings.interval) {
  22110. module.delay(settings.animate);
  22111. }
  22112. else {
  22113. module.animate();
  22114. }
  22115. module.instantiate();
  22116. }
  22117. },
  22118. instantiate: function() {
  22119. module.verbose('Storing instance of module', module);
  22120. instance = module;
  22121. $module
  22122. .data(moduleNamespace, instance)
  22123. ;
  22124. },
  22125. destroy: function() {
  22126. module.verbose('Destroying previous module for', element);
  22127. $module
  22128. .removeData(moduleNamespace)
  22129. ;
  22130. },
  22131. refresh: function() {
  22132. module.verbose('Refreshing display type on next animation');
  22133. delete module.displayType;
  22134. },
  22135. forceRepaint: function() {
  22136. module.verbose('Forcing element repaint');
  22137. var
  22138. $parentElement = $module.parent(),
  22139. $nextElement = $module.next()
  22140. ;
  22141. if($nextElement.length === 0) {
  22142. $module.detach().appendTo($parentElement);
  22143. }
  22144. else {
  22145. $module.detach().insertBefore($nextElement);
  22146. }
  22147. },
  22148. repaint: function() {
  22149. module.verbose('Repainting element');
  22150. var
  22151. fakeAssignment = element.offsetWidth
  22152. ;
  22153. },
  22154. delay: function(interval) {
  22155. var
  22156. direction = module.get.animationDirection(),
  22157. shouldReverse,
  22158. delay
  22159. ;
  22160. if(!direction) {
  22161. direction = module.can.transition()
  22162. ? module.get.direction()
  22163. : 'static'
  22164. ;
  22165. }
  22166. interval = (interval !== undefined)
  22167. ? interval
  22168. : settings.interval
  22169. ;
  22170. shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
  22171. delay = (shouldReverse || settings.reverse == true)
  22172. ? ($allModules.length - index) * settings.interval
  22173. : index * settings.interval
  22174. ;
  22175. module.debug('Delaying animation by', delay);
  22176. setTimeout(module.animate, delay);
  22177. },
  22178. animate: function(overrideSettings) {
  22179. settings = overrideSettings || settings;
  22180. if(!module.is.supported()) {
  22181. module.error(error.support);
  22182. return false;
  22183. }
  22184. module.debug('Preparing animation', settings.animation);
  22185. if(module.is.animating()) {
  22186. if(settings.queue) {
  22187. if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
  22188. module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
  22189. }
  22190. else {
  22191. module.queue(settings.animation);
  22192. }
  22193. return false;
  22194. }
  22195. else if(!settings.allowRepeats && module.is.occurring()) {
  22196. module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
  22197. return false;
  22198. }
  22199. else {
  22200. module.debug('New animation started, completing previous early', settings.animation);
  22201. instance.complete();
  22202. }
  22203. }
  22204. if( module.can.animate() ) {
  22205. module.set.animating(settings.animation);
  22206. }
  22207. else {
  22208. module.error(error.noAnimation, settings.animation, element);
  22209. }
  22210. },
  22211. reset: function() {
  22212. module.debug('Resetting animation to beginning conditions');
  22213. module.remove.animationCallbacks();
  22214. module.restore.conditions();
  22215. module.remove.animating();
  22216. },
  22217. queue: function(animation) {
  22218. module.debug('Queueing animation of', animation);
  22219. module.queuing = true;
  22220. $module
  22221. .one(animationEnd + '.queue' + eventNamespace, function() {
  22222. module.queuing = false;
  22223. module.repaint();
  22224. module.animate.apply(this, settings);
  22225. })
  22226. ;
  22227. },
  22228. complete: function (event) {
  22229. if(event && event.target === element) {
  22230. event.stopPropagation();
  22231. }
  22232. module.debug('Animation complete', settings.animation);
  22233. module.remove.completeCallback();
  22234. module.remove.failSafe();
  22235. if(!module.is.looping()) {
  22236. if( module.is.outward() ) {
  22237. module.verbose('Animation is outward, hiding element');
  22238. module.restore.conditions();
  22239. module.hide();
  22240. }
  22241. else if( module.is.inward() ) {
  22242. module.verbose('Animation is outward, showing element');
  22243. module.restore.conditions();
  22244. module.show();
  22245. }
  22246. else {
  22247. module.verbose('Static animation completed');
  22248. module.restore.conditions();
  22249. settings.onComplete.call(element);
  22250. }
  22251. }
  22252. },
  22253. force: {
  22254. visible: function() {
  22255. var
  22256. style = $module.attr('style'),
  22257. userStyle = module.get.userStyle(style),
  22258. displayType = module.get.displayType(),
  22259. overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
  22260. inlineDisplay = $module[0].style.display,
  22261. mustStayHidden = !displayType || (inlineDisplay === 'none' && settings.skipInlineHidden) || $module[0].tagName.match(/(script|link|style)/i)
  22262. ;
  22263. if (mustStayHidden){
  22264. module.remove.transition();
  22265. return false;
  22266. }
  22267. module.verbose('Overriding default display to show element', displayType);
  22268. $module
  22269. .attr('style', overrideStyle)
  22270. ;
  22271. return true;
  22272. },
  22273. hidden: function() {
  22274. var
  22275. style = $module.attr('style'),
  22276. currentDisplay = $module.css('display'),
  22277. emptyStyle = (style === undefined || style === '')
  22278. ;
  22279. if(currentDisplay !== 'none' && !module.is.hidden()) {
  22280. module.verbose('Overriding default display to hide element');
  22281. $module
  22282. .css('display', 'none')
  22283. ;
  22284. }
  22285. else if(emptyStyle) {
  22286. $module
  22287. .removeAttr('style')
  22288. ;
  22289. }
  22290. }
  22291. },
  22292. has: {
  22293. direction: function(animation) {
  22294. var
  22295. hasDirection = false
  22296. ;
  22297. animation = animation || settings.animation;
  22298. if(typeof animation === 'string') {
  22299. animation = animation.split(' ');
  22300. $.each(animation, function(index, word){
  22301. if(word === className.inward || word === className.outward) {
  22302. hasDirection = true;
  22303. }
  22304. });
  22305. }
  22306. return hasDirection;
  22307. },
  22308. inlineDisplay: function() {
  22309. var
  22310. style = $module.attr('style') || ''
  22311. ;
  22312. return Array.isArray(style.match(/display.*?;/, ''));
  22313. }
  22314. },
  22315. set: {
  22316. animating: function(animation) {
  22317. // remove previous callbacks
  22318. module.remove.completeCallback();
  22319. // determine exact animation
  22320. animation = animation || settings.animation;
  22321. var animationClass = module.get.animationClass(animation);
  22322. // save animation class in cache to restore class names
  22323. module.save.animation(animationClass);
  22324. if(module.force.visible()) {
  22325. module.remove.hidden();
  22326. module.remove.direction();
  22327. module.start.animation(animationClass);
  22328. }
  22329. },
  22330. duration: function(animationName, duration) {
  22331. duration = duration || settings.duration;
  22332. duration = (typeof duration == 'number')
  22333. ? duration + 'ms'
  22334. : duration
  22335. ;
  22336. if(duration || duration === 0) {
  22337. module.verbose('Setting animation duration', duration);
  22338. $module
  22339. .css({
  22340. 'animation-duration': duration
  22341. })
  22342. ;
  22343. }
  22344. },
  22345. direction: function(direction) {
  22346. direction = direction || module.get.direction();
  22347. if(direction == className.inward) {
  22348. module.set.inward();
  22349. }
  22350. else {
  22351. module.set.outward();
  22352. }
  22353. },
  22354. looping: function() {
  22355. module.debug('Transition set to loop');
  22356. $module
  22357. .addClass(className.looping)
  22358. ;
  22359. },
  22360. hidden: function() {
  22361. $module
  22362. .addClass(className.transition)
  22363. .addClass(className.hidden)
  22364. ;
  22365. },
  22366. inward: function() {
  22367. module.debug('Setting direction to inward');
  22368. $module
  22369. .removeClass(className.outward)
  22370. .addClass(className.inward)
  22371. ;
  22372. },
  22373. outward: function() {
  22374. module.debug('Setting direction to outward');
  22375. $module
  22376. .removeClass(className.inward)
  22377. .addClass(className.outward)
  22378. ;
  22379. },
  22380. visible: function() {
  22381. $module
  22382. .addClass(className.transition)
  22383. .addClass(className.visible)
  22384. ;
  22385. }
  22386. },
  22387. start: {
  22388. animation: function(animationClass) {
  22389. animationClass = animationClass || module.get.animationClass();
  22390. module.debug('Starting tween', animationClass);
  22391. $module
  22392. .addClass(animationClass)
  22393. .one(animationEnd + '.complete' + eventNamespace, module.complete)
  22394. ;
  22395. if(settings.useFailSafe) {
  22396. module.add.failSafe();
  22397. }
  22398. module.set.duration(settings.duration);
  22399. settings.onStart.call(element);
  22400. }
  22401. },
  22402. save: {
  22403. animation: function(animation) {
  22404. if(!module.cache) {
  22405. module.cache = {};
  22406. }
  22407. module.cache.animation = animation;
  22408. },
  22409. displayType: function(displayType) {
  22410. if(displayType !== 'none') {
  22411. $module.data(metadata.displayType, displayType);
  22412. }
  22413. },
  22414. transitionExists: function(animation, exists) {
  22415. $.fn.transition.exists[animation] = exists;
  22416. module.verbose('Saving existence of transition', animation, exists);
  22417. }
  22418. },
  22419. restore: {
  22420. conditions: function() {
  22421. var
  22422. animation = module.get.currentAnimation()
  22423. ;
  22424. if(animation) {
  22425. $module
  22426. .removeClass(animation)
  22427. ;
  22428. module.verbose('Removing animation class', module.cache);
  22429. }
  22430. module.remove.duration();
  22431. }
  22432. },
  22433. add: {
  22434. failSafe: function() {
  22435. var
  22436. duration = module.get.duration()
  22437. ;
  22438. module.timer = setTimeout(function() {
  22439. $module.triggerHandler(animationEnd);
  22440. }, duration + settings.failSafeDelay);
  22441. module.verbose('Adding fail safe timer', module.timer);
  22442. }
  22443. },
  22444. remove: {
  22445. animating: function() {
  22446. $module.removeClass(className.animating);
  22447. },
  22448. animationCallbacks: function() {
  22449. module.remove.queueCallback();
  22450. module.remove.completeCallback();
  22451. },
  22452. queueCallback: function() {
  22453. $module.off('.queue' + eventNamespace);
  22454. },
  22455. completeCallback: function() {
  22456. $module.off('.complete' + eventNamespace);
  22457. },
  22458. display: function() {
  22459. $module.css('display', '');
  22460. },
  22461. direction: function() {
  22462. $module
  22463. .removeClass(className.inward)
  22464. .removeClass(className.outward)
  22465. ;
  22466. },
  22467. duration: function() {
  22468. $module
  22469. .css('animation-duration', '')
  22470. ;
  22471. },
  22472. failSafe: function() {
  22473. module.verbose('Removing fail safe timer', module.timer);
  22474. if(module.timer) {
  22475. clearTimeout(module.timer);
  22476. }
  22477. },
  22478. hidden: function() {
  22479. $module.removeClass(className.hidden);
  22480. },
  22481. visible: function() {
  22482. $module.removeClass(className.visible);
  22483. },
  22484. looping: function() {
  22485. module.debug('Transitions are no longer looping');
  22486. if( module.is.looping() ) {
  22487. module.reset();
  22488. $module
  22489. .removeClass(className.looping)
  22490. ;
  22491. }
  22492. },
  22493. transition: function() {
  22494. $module
  22495. .removeClass(className.transition)
  22496. .removeClass(className.visible)
  22497. .removeClass(className.hidden)
  22498. ;
  22499. }
  22500. },
  22501. get: {
  22502. settings: function(animation, duration, onComplete) {
  22503. // single settings object
  22504. if(typeof animation == 'object') {
  22505. return $.extend(true, {}, $.fn.transition.settings, animation);
  22506. }
  22507. // all arguments provided
  22508. else if(typeof onComplete == 'function') {
  22509. return $.extend({}, $.fn.transition.settings, {
  22510. animation : animation,
  22511. onComplete : onComplete,
  22512. duration : duration
  22513. });
  22514. }
  22515. // only duration provided
  22516. else if(typeof duration == 'string' || typeof duration == 'number') {
  22517. return $.extend({}, $.fn.transition.settings, {
  22518. animation : animation,
  22519. duration : duration
  22520. });
  22521. }
  22522. // duration is actually settings object
  22523. else if(typeof duration == 'object') {
  22524. return $.extend({}, $.fn.transition.settings, duration, {
  22525. animation : animation
  22526. });
  22527. }
  22528. // duration is actually callback
  22529. else if(typeof duration == 'function') {
  22530. return $.extend({}, $.fn.transition.settings, {
  22531. animation : animation,
  22532. onComplete : duration
  22533. });
  22534. }
  22535. // only animation provided
  22536. else {
  22537. return $.extend({}, $.fn.transition.settings, {
  22538. animation : animation
  22539. });
  22540. }
  22541. },
  22542. animationClass: function(animation) {
  22543. var
  22544. animationClass = animation || settings.animation,
  22545. directionClass = (module.can.transition() && !module.has.direction())
  22546. ? module.get.direction() + ' '
  22547. : ''
  22548. ;
  22549. return className.animating + ' '
  22550. + className.transition + ' '
  22551. + directionClass
  22552. + animationClass
  22553. ;
  22554. },
  22555. currentAnimation: function() {
  22556. return (module.cache && module.cache.animation !== undefined)
  22557. ? module.cache.animation
  22558. : false
  22559. ;
  22560. },
  22561. currentDirection: function() {
  22562. return module.is.inward()
  22563. ? className.inward
  22564. : className.outward
  22565. ;
  22566. },
  22567. direction: function() {
  22568. return module.is.hidden() || !module.is.visible()
  22569. ? className.inward
  22570. : className.outward
  22571. ;
  22572. },
  22573. animationDirection: function(animation) {
  22574. var
  22575. direction
  22576. ;
  22577. animation = animation || settings.animation;
  22578. if(typeof animation === 'string') {
  22579. animation = animation.split(' ');
  22580. // search animation name for out/in class
  22581. $.each(animation, function(index, word){
  22582. if(word === className.inward) {
  22583. direction = className.inward;
  22584. }
  22585. else if(word === className.outward) {
  22586. direction = className.outward;
  22587. }
  22588. });
  22589. }
  22590. // return found direction
  22591. if(direction) {
  22592. return direction;
  22593. }
  22594. return false;
  22595. },
  22596. duration: function(duration) {
  22597. duration = duration || settings.duration;
  22598. if(duration === false) {
  22599. duration = $module.css('animation-duration') || 0;
  22600. }
  22601. return (typeof duration === 'string')
  22602. ? (duration.indexOf('ms') > -1)
  22603. ? parseFloat(duration)
  22604. : parseFloat(duration) * 1000
  22605. : duration
  22606. ;
  22607. },
  22608. displayType: function(shouldDetermine) {
  22609. shouldDetermine = (shouldDetermine !== undefined)
  22610. ? shouldDetermine
  22611. : true
  22612. ;
  22613. if(settings.displayType) {
  22614. return settings.displayType;
  22615. }
  22616. if(shouldDetermine && $module.data(metadata.displayType) === undefined) {
  22617. var currentDisplay = $module.css('display');
  22618. if(currentDisplay === '' || currentDisplay === 'none'){
  22619. // create fake element to determine display state
  22620. module.can.transition(true);
  22621. } else {
  22622. module.save.displayType(currentDisplay);
  22623. }
  22624. }
  22625. return $module.data(metadata.displayType);
  22626. },
  22627. userStyle: function(style) {
  22628. style = style || $module.attr('style') || '';
  22629. return style.replace(/display.*?;/, '');
  22630. },
  22631. transitionExists: function(animation) {
  22632. return $.fn.transition.exists[animation];
  22633. },
  22634. animationStartEvent: function() {
  22635. var
  22636. element = document.createElement('div'),
  22637. animations = {
  22638. 'animation' :'animationstart',
  22639. 'OAnimation' :'oAnimationStart',
  22640. 'MozAnimation' :'mozAnimationStart',
  22641. 'WebkitAnimation' :'webkitAnimationStart'
  22642. },
  22643. animation
  22644. ;
  22645. for(animation in animations){
  22646. if( element.style[animation] !== undefined ){
  22647. return animations[animation];
  22648. }
  22649. }
  22650. return false;
  22651. },
  22652. animationEndEvent: function() {
  22653. var
  22654. element = document.createElement('div'),
  22655. animations = {
  22656. 'animation' :'animationend',
  22657. 'OAnimation' :'oAnimationEnd',
  22658. 'MozAnimation' :'mozAnimationEnd',
  22659. 'WebkitAnimation' :'webkitAnimationEnd'
  22660. },
  22661. animation
  22662. ;
  22663. for(animation in animations){
  22664. if( element.style[animation] !== undefined ){
  22665. return animations[animation];
  22666. }
  22667. }
  22668. return false;
  22669. }
  22670. },
  22671. can: {
  22672. transition: function(forced) {
  22673. var
  22674. animation = settings.animation,
  22675. transitionExists = module.get.transitionExists(animation),
  22676. displayType = module.get.displayType(false),
  22677. elementClass,
  22678. tagName,
  22679. $clone,
  22680. currentAnimation,
  22681. inAnimation,
  22682. directionExists
  22683. ;
  22684. if( transitionExists === undefined || forced) {
  22685. module.verbose('Determining whether animation exists');
  22686. elementClass = $module.attr('class');
  22687. tagName = $module.prop('tagName');
  22688. $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
  22689. currentAnimation = $clone
  22690. .addClass(animation)
  22691. .removeClass(className.inward)
  22692. .removeClass(className.outward)
  22693. .addClass(className.animating)
  22694. .addClass(className.transition)
  22695. .css('animationName')
  22696. ;
  22697. inAnimation = $clone
  22698. .addClass(className.inward)
  22699. .css('animationName')
  22700. ;
  22701. if(!displayType) {
  22702. displayType = $clone
  22703. .attr('class', elementClass)
  22704. .removeAttr('style')
  22705. .removeClass(className.hidden)
  22706. .removeClass(className.visible)
  22707. .show()
  22708. .css('display')
  22709. ;
  22710. module.verbose('Determining final display state', displayType);
  22711. module.save.displayType(displayType);
  22712. }
  22713. $clone.remove();
  22714. if(currentAnimation != inAnimation) {
  22715. module.debug('Direction exists for animation', animation);
  22716. directionExists = true;
  22717. }
  22718. else if(currentAnimation == 'none' || !currentAnimation) {
  22719. module.debug('No animation defined in css', animation);
  22720. return;
  22721. }
  22722. else {
  22723. module.debug('Static animation found', animation, displayType);
  22724. directionExists = false;
  22725. }
  22726. module.save.transitionExists(animation, directionExists);
  22727. }
  22728. return (transitionExists !== undefined)
  22729. ? transitionExists
  22730. : directionExists
  22731. ;
  22732. },
  22733. animate: function() {
  22734. // can transition does not return a value if animation does not exist
  22735. return (module.can.transition() !== undefined);
  22736. }
  22737. },
  22738. is: {
  22739. animating: function() {
  22740. return $module.hasClass(className.animating);
  22741. },
  22742. inward: function() {
  22743. return $module.hasClass(className.inward);
  22744. },
  22745. outward: function() {
  22746. return $module.hasClass(className.outward);
  22747. },
  22748. looping: function() {
  22749. return $module.hasClass(className.looping);
  22750. },
  22751. occurring: function(animation) {
  22752. animation = animation || settings.animation;
  22753. animation = '.' + animation.replace(' ', '.');
  22754. return ( $module.filter(animation).length > 0 );
  22755. },
  22756. visible: function() {
  22757. return $module.is(':visible');
  22758. },
  22759. hidden: function() {
  22760. return $module.css('visibility') === 'hidden';
  22761. },
  22762. supported: function() {
  22763. return(animationEnd !== false);
  22764. }
  22765. },
  22766. hide: function() {
  22767. module.verbose('Hiding element');
  22768. if( module.is.animating() ) {
  22769. module.reset();
  22770. }
  22771. element.blur(); // IE will trigger focus change if element is not blurred before hiding
  22772. module.remove.display();
  22773. module.remove.visible();
  22774. if($.isFunction(settings.onBeforeHide)){
  22775. settings.onBeforeHide.call(element,function(){
  22776. module.hideNow();
  22777. });
  22778. } else {
  22779. module.hideNow();
  22780. }
  22781. },
  22782. hideNow: function() {
  22783. module.set.hidden();
  22784. module.force.hidden();
  22785. settings.onHide.call(element);
  22786. settings.onComplete.call(element);
  22787. // module.repaint();
  22788. },
  22789. show: function(display) {
  22790. module.verbose('Showing element', display);
  22791. if(module.force.visible()) {
  22792. module.remove.hidden();
  22793. module.set.visible();
  22794. settings.onShow.call(element);
  22795. settings.onComplete.call(element);
  22796. // module.repaint();
  22797. }
  22798. },
  22799. toggle: function() {
  22800. if( module.is.visible() ) {
  22801. module.hide();
  22802. }
  22803. else {
  22804. module.show();
  22805. }
  22806. },
  22807. stop: function() {
  22808. module.debug('Stopping current animation');
  22809. $module.triggerHandler(animationEnd);
  22810. },
  22811. stopAll: function() {
  22812. module.debug('Stopping all animation');
  22813. module.remove.queueCallback();
  22814. $module.triggerHandler(animationEnd);
  22815. },
  22816. clear: {
  22817. queue: function() {
  22818. module.debug('Clearing animation queue');
  22819. module.remove.queueCallback();
  22820. }
  22821. },
  22822. enable: function() {
  22823. module.verbose('Starting animation');
  22824. $module.removeClass(className.disabled);
  22825. },
  22826. disable: function() {
  22827. module.debug('Stopping animation');
  22828. $module.addClass(className.disabled);
  22829. },
  22830. setting: function(name, value) {
  22831. module.debug('Changing setting', name, value);
  22832. if( $.isPlainObject(name) ) {
  22833. $.extend(true, settings, name);
  22834. }
  22835. else if(value !== undefined) {
  22836. if($.isPlainObject(settings[name])) {
  22837. $.extend(true, settings[name], value);
  22838. }
  22839. else {
  22840. settings[name] = value;
  22841. }
  22842. }
  22843. else {
  22844. return settings[name];
  22845. }
  22846. },
  22847. internal: function(name, value) {
  22848. if( $.isPlainObject(name) ) {
  22849. $.extend(true, module, name);
  22850. }
  22851. else if(value !== undefined) {
  22852. module[name] = value;
  22853. }
  22854. else {
  22855. return module[name];
  22856. }
  22857. },
  22858. debug: function() {
  22859. if(!settings.silent && settings.debug) {
  22860. if(settings.performance) {
  22861. module.performance.log(arguments);
  22862. }
  22863. else {
  22864. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  22865. module.debug.apply(console, arguments);
  22866. }
  22867. }
  22868. },
  22869. verbose: function() {
  22870. if(!settings.silent && settings.verbose && settings.debug) {
  22871. if(settings.performance) {
  22872. module.performance.log(arguments);
  22873. }
  22874. else {
  22875. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  22876. module.verbose.apply(console, arguments);
  22877. }
  22878. }
  22879. },
  22880. error: function() {
  22881. if(!settings.silent) {
  22882. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  22883. module.error.apply(console, arguments);
  22884. }
  22885. },
  22886. performance: {
  22887. log: function(message) {
  22888. var
  22889. currentTime,
  22890. executionTime,
  22891. previousTime
  22892. ;
  22893. if(settings.performance) {
  22894. currentTime = new Date().getTime();
  22895. previousTime = time || currentTime;
  22896. executionTime = currentTime - previousTime;
  22897. time = currentTime;
  22898. performance.push({
  22899. 'Name' : message[0],
  22900. 'Arguments' : [].slice.call(message, 1) || '',
  22901. 'Element' : element,
  22902. 'Execution Time' : executionTime
  22903. });
  22904. }
  22905. clearTimeout(module.performance.timer);
  22906. module.performance.timer = setTimeout(module.performance.display, 500);
  22907. },
  22908. display: function() {
  22909. var
  22910. title = settings.name + ':',
  22911. totalTime = 0
  22912. ;
  22913. time = false;
  22914. clearTimeout(module.performance.timer);
  22915. $.each(performance, function(index, data) {
  22916. totalTime += data['Execution Time'];
  22917. });
  22918. title += ' ' + totalTime + 'ms';
  22919. if(moduleSelector) {
  22920. title += ' \'' + moduleSelector + '\'';
  22921. }
  22922. if($allModules.length > 1) {
  22923. title += ' ' + '(' + $allModules.length + ')';
  22924. }
  22925. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  22926. console.groupCollapsed(title);
  22927. if(console.table) {
  22928. console.table(performance);
  22929. }
  22930. else {
  22931. $.each(performance, function(index, data) {
  22932. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  22933. });
  22934. }
  22935. console.groupEnd();
  22936. }
  22937. performance = [];
  22938. }
  22939. },
  22940. // modified for transition to return invoke success
  22941. invoke: function(query, passedArguments, context) {
  22942. var
  22943. object = instance,
  22944. maxDepth,
  22945. found,
  22946. response
  22947. ;
  22948. passedArguments = passedArguments || queryArguments;
  22949. context = element || context;
  22950. if(typeof query == 'string' && object !== undefined) {
  22951. query = query.split(/[\. ]/);
  22952. maxDepth = query.length - 1;
  22953. $.each(query, function(depth, value) {
  22954. var camelCaseValue = (depth != maxDepth)
  22955. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  22956. : query
  22957. ;
  22958. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  22959. object = object[camelCaseValue];
  22960. }
  22961. else if( object[camelCaseValue] !== undefined ) {
  22962. found = object[camelCaseValue];
  22963. return false;
  22964. }
  22965. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  22966. object = object[value];
  22967. }
  22968. else if( object[value] !== undefined ) {
  22969. found = object[value];
  22970. return false;
  22971. }
  22972. else {
  22973. return false;
  22974. }
  22975. });
  22976. }
  22977. if ( $.isFunction( found ) ) {
  22978. response = found.apply(context, passedArguments);
  22979. }
  22980. else if(found !== undefined) {
  22981. response = found;
  22982. }
  22983. if(Array.isArray(returnedValue)) {
  22984. returnedValue.push(response);
  22985. }
  22986. else if(returnedValue !== undefined) {
  22987. returnedValue = [returnedValue, response];
  22988. }
  22989. else if(response !== undefined) {
  22990. returnedValue = response;
  22991. }
  22992. return (found !== undefined)
  22993. ? found
  22994. : false
  22995. ;
  22996. }
  22997. };
  22998. module.initialize();
  22999. })
  23000. ;
  23001. return (returnedValue !== undefined)
  23002. ? returnedValue
  23003. : this
  23004. ;
  23005. };
  23006. // Records if CSS transition is available
  23007. $.fn.transition.exists = {};
  23008. $.fn.transition.settings = {
  23009. // module info
  23010. name : 'Transition',
  23011. // hide all output from this component regardless of other settings
  23012. silent : false,
  23013. // debug content outputted to console
  23014. debug : false,
  23015. // verbose debug output
  23016. verbose : false,
  23017. // performance data output
  23018. performance : true,
  23019. // event namespace
  23020. namespace : 'transition',
  23021. // delay between animations in group
  23022. interval : 0,
  23023. // whether group animations should be reversed
  23024. reverse : 'auto',
  23025. // animation callback event
  23026. onStart : function() {},
  23027. onComplete : function() {},
  23028. onShow : function() {},
  23029. onHide : function() {},
  23030. // whether timeout should be used to ensure callback fires in cases animationend does not
  23031. useFailSafe : true,
  23032. // delay in ms for fail safe
  23033. failSafeDelay : 100,
  23034. // whether EXACT animation can occur twice in a row
  23035. allowRepeats : false,
  23036. // Override final display type on visible
  23037. displayType : false,
  23038. // animation duration
  23039. animation : 'fade',
  23040. duration : false,
  23041. // new animations will occur after previous ones
  23042. queue : true,
  23043. // whether initially inline hidden objects should be skipped for transition
  23044. skipInlineHidden: false,
  23045. metadata : {
  23046. displayType: 'display'
  23047. },
  23048. className : {
  23049. animating : 'animating',
  23050. disabled : 'disabled',
  23051. hidden : 'hidden',
  23052. inward : 'in',
  23053. loading : 'loading',
  23054. looping : 'looping',
  23055. outward : 'out',
  23056. transition : 'transition',
  23057. visible : 'visible'
  23058. },
  23059. // possible errors
  23060. error: {
  23061. noAnimation : 'Element is no longer attached to DOM. Unable to animate. Use silent setting to surpress this warning in production.',
  23062. repeated : 'That animation is already occurring, cancelling repeated animation',
  23063. method : 'The method you called is not defined',
  23064. support : 'This browser does not support CSS animations'
  23065. }
  23066. };
  23067. })( jQuery, window, document );
  23068. /*!
  23069. * # Fomantic-UI - API
  23070. * http://github.com/fomantic/Fomantic-UI/
  23071. *
  23072. *
  23073. * Released under the MIT license
  23074. * http://opensource.org/licenses/MIT
  23075. *
  23076. */
  23077. ;(function ($, window, document, undefined) {
  23078. 'use strict';
  23079. $.isWindow = $.isWindow || function(obj) {
  23080. return obj != null && obj === obj.window;
  23081. };
  23082. window = (typeof window != 'undefined' && window.Math == Math)
  23083. ? window
  23084. : (typeof self != 'undefined' && self.Math == Math)
  23085. ? self
  23086. : Function('return this')()
  23087. ;
  23088. $.api = $.fn.api = function(parameters) {
  23089. var
  23090. // use window context if none specified
  23091. $allModules = $.isFunction(this)
  23092. ? $(window)
  23093. : $(this),
  23094. moduleSelector = $allModules.selector || '',
  23095. time = new Date().getTime(),
  23096. performance = [],
  23097. query = arguments[0],
  23098. methodInvoked = (typeof query == 'string'),
  23099. queryArguments = [].slice.call(arguments, 1),
  23100. returnedValue
  23101. ;
  23102. $allModules
  23103. .each(function() {
  23104. var
  23105. settings = ( $.isPlainObject(parameters) )
  23106. ? $.extend(true, {}, $.fn.api.settings, parameters)
  23107. : $.extend({}, $.fn.api.settings),
  23108. // internal aliases
  23109. namespace = settings.namespace,
  23110. metadata = settings.metadata,
  23111. selector = settings.selector,
  23112. error = settings.error,
  23113. className = settings.className,
  23114. // define namespaces for modules
  23115. eventNamespace = '.' + namespace,
  23116. moduleNamespace = 'module-' + namespace,
  23117. // element that creates request
  23118. $module = $(this),
  23119. $form = $module.closest(selector.form),
  23120. // context used for state
  23121. $context = (settings.stateContext)
  23122. ? $(settings.stateContext)
  23123. : $module,
  23124. // request details
  23125. ajaxSettings,
  23126. requestSettings,
  23127. url,
  23128. data,
  23129. requestStartTime,
  23130. // standard module
  23131. element = this,
  23132. context = $context[0],
  23133. instance = $module.data(moduleNamespace),
  23134. module
  23135. ;
  23136. module = {
  23137. initialize: function() {
  23138. if(!methodInvoked) {
  23139. module.bind.events();
  23140. }
  23141. module.instantiate();
  23142. },
  23143. instantiate: function() {
  23144. module.verbose('Storing instance of module', module);
  23145. instance = module;
  23146. $module
  23147. .data(moduleNamespace, instance)
  23148. ;
  23149. },
  23150. destroy: function() {
  23151. module.verbose('Destroying previous module for', element);
  23152. $module
  23153. .removeData(moduleNamespace)
  23154. .off(eventNamespace)
  23155. ;
  23156. },
  23157. bind: {
  23158. events: function() {
  23159. var
  23160. triggerEvent = module.get.event()
  23161. ;
  23162. if( triggerEvent ) {
  23163. module.verbose('Attaching API events to element', triggerEvent);
  23164. $module
  23165. .on(triggerEvent + eventNamespace, module.event.trigger)
  23166. ;
  23167. }
  23168. else if(settings.on == 'now') {
  23169. module.debug('Querying API endpoint immediately');
  23170. module.query();
  23171. }
  23172. }
  23173. },
  23174. decode: {
  23175. json: function(response) {
  23176. if(response !== undefined && typeof response == 'string') {
  23177. try {
  23178. response = JSON.parse(response);
  23179. }
  23180. catch(e) {
  23181. // isnt json string
  23182. }
  23183. }
  23184. return response;
  23185. }
  23186. },
  23187. read: {
  23188. cachedResponse: function(url) {
  23189. var
  23190. response
  23191. ;
  23192. if(window.Storage === undefined) {
  23193. module.error(error.noStorage);
  23194. return;
  23195. }
  23196. response = sessionStorage.getItem(url);
  23197. module.debug('Using cached response', url, response);
  23198. response = module.decode.json(response);
  23199. return response;
  23200. }
  23201. },
  23202. write: {
  23203. cachedResponse: function(url, response) {
  23204. if(response && response === '') {
  23205. module.debug('Response empty, not caching', response);
  23206. return;
  23207. }
  23208. if(window.Storage === undefined) {
  23209. module.error(error.noStorage);
  23210. return;
  23211. }
  23212. if( $.isPlainObject(response) ) {
  23213. response = JSON.stringify(response);
  23214. }
  23215. sessionStorage.setItem(url, response);
  23216. module.verbose('Storing cached response for url', url, response);
  23217. }
  23218. },
  23219. query: function() {
  23220. if(module.is.disabled()) {
  23221. module.debug('Element is disabled API request aborted');
  23222. return;
  23223. }
  23224. if(module.is.loading()) {
  23225. if(settings.interruptRequests) {
  23226. module.debug('Interrupting previous request');
  23227. module.abort();
  23228. }
  23229. else {
  23230. module.debug('Cancelling request, previous request is still pending');
  23231. return;
  23232. }
  23233. }
  23234. // pass element metadata to url (value, text)
  23235. if(settings.defaultData) {
  23236. $.extend(true, settings.urlData, module.get.defaultData());
  23237. }
  23238. // Add form content
  23239. if(settings.serializeForm) {
  23240. settings.data = module.add.formData(settings.data);
  23241. }
  23242. // call beforesend and get any settings changes
  23243. requestSettings = module.get.settings();
  23244. // check if before send cancelled request
  23245. if(requestSettings === false) {
  23246. module.cancelled = true;
  23247. module.error(error.beforeSend);
  23248. return;
  23249. }
  23250. else {
  23251. module.cancelled = false;
  23252. }
  23253. // get url
  23254. url = module.get.templatedURL();
  23255. if(!url && !module.is.mocked()) {
  23256. module.error(error.missingURL);
  23257. return;
  23258. }
  23259. // replace variables
  23260. url = module.add.urlData( url );
  23261. // missing url parameters
  23262. if( !url && !module.is.mocked()) {
  23263. return;
  23264. }
  23265. requestSettings.url = settings.base + url;
  23266. // look for jQuery ajax parameters in settings
  23267. ajaxSettings = $.extend(true, {}, settings, {
  23268. type : settings.method || settings.type,
  23269. data : data,
  23270. url : settings.base + url,
  23271. beforeSend : settings.beforeXHR,
  23272. success : function() {},
  23273. failure : function() {},
  23274. complete : function() {}
  23275. });
  23276. module.debug('Querying URL', ajaxSettings.url);
  23277. module.verbose('Using AJAX settings', ajaxSettings);
  23278. if(settings.cache === 'local' && module.read.cachedResponse(url)) {
  23279. module.debug('Response returned from local cache');
  23280. module.request = module.create.request();
  23281. module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
  23282. return;
  23283. }
  23284. if( !settings.throttle ) {
  23285. module.debug('Sending request', data, ajaxSettings.method);
  23286. module.send.request();
  23287. }
  23288. else {
  23289. if(!settings.throttleFirstRequest && !module.timer) {
  23290. module.debug('Sending request', data, ajaxSettings.method);
  23291. module.send.request();
  23292. module.timer = setTimeout(function(){}, settings.throttle);
  23293. }
  23294. else {
  23295. module.debug('Throttling request', settings.throttle);
  23296. clearTimeout(module.timer);
  23297. module.timer = setTimeout(function() {
  23298. if(module.timer) {
  23299. delete module.timer;
  23300. }
  23301. module.debug('Sending throttled request', data, ajaxSettings.method);
  23302. module.send.request();
  23303. }, settings.throttle);
  23304. }
  23305. }
  23306. },
  23307. should: {
  23308. removeError: function() {
  23309. return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
  23310. }
  23311. },
  23312. is: {
  23313. disabled: function() {
  23314. return ($module.filter(selector.disabled).length > 0);
  23315. },
  23316. expectingJSON: function() {
  23317. return settings.dataType === 'json' || settings.dataType === 'jsonp';
  23318. },
  23319. form: function() {
  23320. return $module.is('form') || $context.is('form');
  23321. },
  23322. mocked: function() {
  23323. return (settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync);
  23324. },
  23325. input: function() {
  23326. return $module.is('input');
  23327. },
  23328. loading: function() {
  23329. return (module.request)
  23330. ? (module.request.state() == 'pending')
  23331. : false
  23332. ;
  23333. },
  23334. abortedRequest: function(xhr) {
  23335. if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
  23336. module.verbose('XHR request determined to be aborted');
  23337. return true;
  23338. }
  23339. else {
  23340. module.verbose('XHR request was not aborted');
  23341. return false;
  23342. }
  23343. },
  23344. validResponse: function(response) {
  23345. if( (!module.is.expectingJSON()) || !$.isFunction(settings.successTest) ) {
  23346. module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
  23347. return true;
  23348. }
  23349. module.debug('Checking JSON returned success', settings.successTest, response);
  23350. if( settings.successTest(response) ) {
  23351. module.debug('Response passed success test', response);
  23352. return true;
  23353. }
  23354. else {
  23355. module.debug('Response failed success test', response);
  23356. return false;
  23357. }
  23358. }
  23359. },
  23360. was: {
  23361. cancelled: function() {
  23362. return (module.cancelled || false);
  23363. },
  23364. succesful: function() {
  23365. module.verbose('This behavior will be deleted due to typo. Use "was successful" instead.');
  23366. return module.was.successful();
  23367. },
  23368. successful: function() {
  23369. return (module.request && module.request.state() == 'resolved');
  23370. },
  23371. failure: function() {
  23372. return (module.request && module.request.state() == 'rejected');
  23373. },
  23374. complete: function() {
  23375. return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
  23376. }
  23377. },
  23378. add: {
  23379. urlData: function(url, urlData) {
  23380. var
  23381. requiredVariables,
  23382. optionalVariables
  23383. ;
  23384. if(url) {
  23385. requiredVariables = url.match(settings.regExp.required);
  23386. optionalVariables = url.match(settings.regExp.optional);
  23387. urlData = urlData || settings.urlData;
  23388. if(requiredVariables) {
  23389. module.debug('Looking for required URL variables', requiredVariables);
  23390. $.each(requiredVariables, function(index, templatedString) {
  23391. var
  23392. // allow legacy {$var} style
  23393. variable = (templatedString.indexOf('$') !== -1)
  23394. ? templatedString.substr(2, templatedString.length - 3)
  23395. : templatedString.substr(1, templatedString.length - 2),
  23396. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  23397. ? urlData[variable]
  23398. : ($module.data(variable) !== undefined)
  23399. ? $module.data(variable)
  23400. : ($context.data(variable) !== undefined)
  23401. ? $context.data(variable)
  23402. : urlData[variable]
  23403. ;
  23404. // remove value
  23405. if(value === undefined) {
  23406. module.error(error.requiredParameter, variable, url);
  23407. url = false;
  23408. return false;
  23409. }
  23410. else {
  23411. module.verbose('Found required variable', variable, value);
  23412. value = (settings.encodeParameters)
  23413. ? module.get.urlEncodedValue(value)
  23414. : value
  23415. ;
  23416. url = url.replace(templatedString, value);
  23417. }
  23418. });
  23419. }
  23420. if(optionalVariables) {
  23421. module.debug('Looking for optional URL variables', requiredVariables);
  23422. $.each(optionalVariables, function(index, templatedString) {
  23423. var
  23424. // allow legacy {/$var} style
  23425. variable = (templatedString.indexOf('$') !== -1)
  23426. ? templatedString.substr(3, templatedString.length - 4)
  23427. : templatedString.substr(2, templatedString.length - 3),
  23428. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  23429. ? urlData[variable]
  23430. : ($module.data(variable) !== undefined)
  23431. ? $module.data(variable)
  23432. : ($context.data(variable) !== undefined)
  23433. ? $context.data(variable)
  23434. : urlData[variable]
  23435. ;
  23436. // optional replacement
  23437. if(value !== undefined) {
  23438. module.verbose('Optional variable Found', variable, value);
  23439. url = url.replace(templatedString, value);
  23440. }
  23441. else {
  23442. module.verbose('Optional variable not found', variable);
  23443. // remove preceding slash if set
  23444. if(url.indexOf('/' + templatedString) !== -1) {
  23445. url = url.replace('/' + templatedString, '');
  23446. }
  23447. else {
  23448. url = url.replace(templatedString, '');
  23449. }
  23450. }
  23451. });
  23452. }
  23453. }
  23454. return url;
  23455. },
  23456. formData: function(data) {
  23457. var
  23458. canSerialize = ($.fn.serializeObject !== undefined),
  23459. formData = (canSerialize)
  23460. ? $form.serializeObject()
  23461. : $form.serialize(),
  23462. hasOtherData
  23463. ;
  23464. data = data || settings.data;
  23465. hasOtherData = $.isPlainObject(data);
  23466. if(hasOtherData) {
  23467. if(canSerialize) {
  23468. module.debug('Extending existing data with form data', data, formData);
  23469. data = $.extend(true, {}, data, formData);
  23470. }
  23471. else {
  23472. module.error(error.missingSerialize);
  23473. module.debug('Cant extend data. Replacing data with form data', data, formData);
  23474. data = formData;
  23475. }
  23476. }
  23477. else {
  23478. module.debug('Adding form data', formData);
  23479. data = formData;
  23480. }
  23481. return data;
  23482. }
  23483. },
  23484. send: {
  23485. request: function() {
  23486. module.set.loading();
  23487. module.request = module.create.request();
  23488. if( module.is.mocked() ) {
  23489. module.mockedXHR = module.create.mockedXHR();
  23490. }
  23491. else {
  23492. module.xhr = module.create.xhr();
  23493. }
  23494. settings.onRequest.call(context, module.request, module.xhr);
  23495. }
  23496. },
  23497. event: {
  23498. trigger: function(event) {
  23499. module.query();
  23500. if(event.type == 'submit' || event.type == 'click') {
  23501. event.preventDefault();
  23502. }
  23503. },
  23504. xhr: {
  23505. always: function() {
  23506. // nothing special
  23507. },
  23508. done: function(response, textStatus, xhr) {
  23509. var
  23510. context = this,
  23511. elapsedTime = (new Date().getTime() - requestStartTime),
  23512. timeLeft = (settings.loadingDuration - elapsedTime),
  23513. translatedResponse = ( $.isFunction(settings.onResponse) )
  23514. ? module.is.expectingJSON() && !settings.rawResponse
  23515. ? settings.onResponse.call(context, $.extend(true, {}, response))
  23516. : settings.onResponse.call(context, response)
  23517. : false
  23518. ;
  23519. timeLeft = (timeLeft > 0)
  23520. ? timeLeft
  23521. : 0
  23522. ;
  23523. if(translatedResponse) {
  23524. module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
  23525. response = translatedResponse;
  23526. }
  23527. if(timeLeft > 0) {
  23528. module.debug('Response completed early delaying state change by', timeLeft);
  23529. }
  23530. setTimeout(function() {
  23531. if( module.is.validResponse(response) ) {
  23532. module.request.resolveWith(context, [response, xhr]);
  23533. }
  23534. else {
  23535. module.request.rejectWith(context, [xhr, 'invalid']);
  23536. }
  23537. }, timeLeft);
  23538. },
  23539. fail: function(xhr, status, httpMessage) {
  23540. var
  23541. context = this,
  23542. elapsedTime = (new Date().getTime() - requestStartTime),
  23543. timeLeft = (settings.loadingDuration - elapsedTime)
  23544. ;
  23545. timeLeft = (timeLeft > 0)
  23546. ? timeLeft
  23547. : 0
  23548. ;
  23549. if(timeLeft > 0) {
  23550. module.debug('Response completed early delaying state change by', timeLeft);
  23551. }
  23552. setTimeout(function() {
  23553. if( module.is.abortedRequest(xhr) ) {
  23554. module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
  23555. }
  23556. else {
  23557. module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
  23558. }
  23559. }, timeLeft);
  23560. }
  23561. },
  23562. request: {
  23563. done: function(response, xhr) {
  23564. module.debug('Successful API Response', response);
  23565. if(settings.cache === 'local' && url) {
  23566. module.write.cachedResponse(url, response);
  23567. module.debug('Saving server response locally', module.cache);
  23568. }
  23569. settings.onSuccess.call(context, response, $module, xhr);
  23570. },
  23571. complete: function(firstParameter, secondParameter) {
  23572. var
  23573. xhr,
  23574. response
  23575. ;
  23576. // have to guess callback parameters based on request success
  23577. if( module.was.successful() ) {
  23578. response = firstParameter;
  23579. xhr = secondParameter;
  23580. }
  23581. else {
  23582. xhr = firstParameter;
  23583. response = module.get.responseFromXHR(xhr);
  23584. }
  23585. module.remove.loading();
  23586. settings.onComplete.call(context, response, $module, xhr);
  23587. },
  23588. fail: function(xhr, status, httpMessage) {
  23589. var
  23590. // pull response from xhr if available
  23591. response = module.get.responseFromXHR(xhr),
  23592. errorMessage = module.get.errorFromRequest(response, status, httpMessage)
  23593. ;
  23594. if(status == 'aborted') {
  23595. module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
  23596. settings.onAbort.call(context, status, $module, xhr);
  23597. return true;
  23598. }
  23599. else if(status == 'invalid') {
  23600. module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
  23601. }
  23602. else if(status == 'error') {
  23603. if(xhr !== undefined) {
  23604. module.debug('XHR produced a server error', status, httpMessage);
  23605. // make sure we have an error to display to console
  23606. if( (xhr.status < 200 || xhr.status >= 300) && httpMessage !== undefined && httpMessage !== '') {
  23607. module.error(error.statusMessage + httpMessage, ajaxSettings.url);
  23608. }
  23609. settings.onError.call(context, errorMessage, $module, xhr);
  23610. }
  23611. }
  23612. if(settings.errorDuration && status !== 'aborted') {
  23613. module.debug('Adding error state');
  23614. module.set.error();
  23615. if( module.should.removeError() ) {
  23616. setTimeout(module.remove.error, settings.errorDuration);
  23617. }
  23618. }
  23619. module.debug('API Request failed', errorMessage, xhr);
  23620. settings.onFailure.call(context, response, $module, xhr);
  23621. }
  23622. }
  23623. },
  23624. create: {
  23625. request: function() {
  23626. // api request promise
  23627. return $.Deferred()
  23628. .always(module.event.request.complete)
  23629. .done(module.event.request.done)
  23630. .fail(module.event.request.fail)
  23631. ;
  23632. },
  23633. mockedXHR: function () {
  23634. var
  23635. // xhr does not simulate these properties of xhr but must return them
  23636. textStatus = false,
  23637. status = false,
  23638. httpMessage = false,
  23639. responder = settings.mockResponse || settings.response,
  23640. asyncResponder = settings.mockResponseAsync || settings.responseAsync,
  23641. asyncCallback,
  23642. response,
  23643. mockedXHR
  23644. ;
  23645. mockedXHR = $.Deferred()
  23646. .always(module.event.xhr.complete)
  23647. .done(module.event.xhr.done)
  23648. .fail(module.event.xhr.fail)
  23649. ;
  23650. if(responder) {
  23651. if( $.isFunction(responder) ) {
  23652. module.debug('Using specified synchronous callback', responder);
  23653. response = responder.call(context, requestSettings);
  23654. }
  23655. else {
  23656. module.debug('Using settings specified response', responder);
  23657. response = responder;
  23658. }
  23659. // simulating response
  23660. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  23661. }
  23662. else if( $.isFunction(asyncResponder) ) {
  23663. asyncCallback = function(response) {
  23664. module.debug('Async callback returned response', response);
  23665. if(response) {
  23666. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  23667. }
  23668. else {
  23669. mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
  23670. }
  23671. };
  23672. module.debug('Using specified async response callback', asyncResponder);
  23673. asyncResponder.call(context, requestSettings, asyncCallback);
  23674. }
  23675. return mockedXHR;
  23676. },
  23677. xhr: function() {
  23678. var
  23679. xhr
  23680. ;
  23681. // ajax request promise
  23682. xhr = $.ajax(ajaxSettings)
  23683. .always(module.event.xhr.always)
  23684. .done(module.event.xhr.done)
  23685. .fail(module.event.xhr.fail)
  23686. ;
  23687. module.verbose('Created server request', xhr, ajaxSettings);
  23688. return xhr;
  23689. }
  23690. },
  23691. set: {
  23692. error: function() {
  23693. module.verbose('Adding error state to element', $context);
  23694. $context.addClass(className.error);
  23695. },
  23696. loading: function() {
  23697. module.verbose('Adding loading state to element', $context);
  23698. $context.addClass(className.loading);
  23699. requestStartTime = new Date().getTime();
  23700. }
  23701. },
  23702. remove: {
  23703. error: function() {
  23704. module.verbose('Removing error state from element', $context);
  23705. $context.removeClass(className.error);
  23706. },
  23707. loading: function() {
  23708. module.verbose('Removing loading state from element', $context);
  23709. $context.removeClass(className.loading);
  23710. }
  23711. },
  23712. get: {
  23713. responseFromXHR: function(xhr) {
  23714. return $.isPlainObject(xhr)
  23715. ? (module.is.expectingJSON())
  23716. ? module.decode.json(xhr.responseText)
  23717. : xhr.responseText
  23718. : false
  23719. ;
  23720. },
  23721. errorFromRequest: function(response, status, httpMessage) {
  23722. return ($.isPlainObject(response) && response.error !== undefined)
  23723. ? response.error // use json error message
  23724. : (settings.error[status] !== undefined) // use server error message
  23725. ? settings.error[status]
  23726. : httpMessage
  23727. ;
  23728. },
  23729. request: function() {
  23730. return module.request || false;
  23731. },
  23732. xhr: function() {
  23733. return module.xhr || false;
  23734. },
  23735. settings: function() {
  23736. var
  23737. runSettings
  23738. ;
  23739. runSettings = settings.beforeSend.call($module, settings);
  23740. if(runSettings) {
  23741. if(runSettings.success !== undefined) {
  23742. module.debug('Legacy success callback detected', runSettings);
  23743. module.error(error.legacyParameters, runSettings.success);
  23744. runSettings.onSuccess = runSettings.success;
  23745. }
  23746. if(runSettings.failure !== undefined) {
  23747. module.debug('Legacy failure callback detected', runSettings);
  23748. module.error(error.legacyParameters, runSettings.failure);
  23749. runSettings.onFailure = runSettings.failure;
  23750. }
  23751. if(runSettings.complete !== undefined) {
  23752. module.debug('Legacy complete callback detected', runSettings);
  23753. module.error(error.legacyParameters, runSettings.complete);
  23754. runSettings.onComplete = runSettings.complete;
  23755. }
  23756. }
  23757. if(runSettings === undefined) {
  23758. module.error(error.noReturnedValue);
  23759. }
  23760. if(runSettings === false) {
  23761. return runSettings;
  23762. }
  23763. return (runSettings !== undefined)
  23764. ? $.extend(true, {}, runSettings)
  23765. : $.extend(true, {}, settings)
  23766. ;
  23767. },
  23768. urlEncodedValue: function(value) {
  23769. var
  23770. decodedValue = window.decodeURIComponent(value),
  23771. encodedValue = window.encodeURIComponent(value),
  23772. alreadyEncoded = (decodedValue !== value)
  23773. ;
  23774. if(alreadyEncoded) {
  23775. module.debug('URL value is already encoded, avoiding double encoding', value);
  23776. return value;
  23777. }
  23778. module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
  23779. return encodedValue;
  23780. },
  23781. defaultData: function() {
  23782. var
  23783. data = {}
  23784. ;
  23785. if( !$.isWindow(element) ) {
  23786. if( module.is.input() ) {
  23787. data.value = $module.val();
  23788. }
  23789. else if( module.is.form() ) {
  23790. }
  23791. else {
  23792. data.text = $module.text();
  23793. }
  23794. }
  23795. return data;
  23796. },
  23797. event: function() {
  23798. if( $.isWindow(element) || settings.on == 'now' ) {
  23799. module.debug('API called without element, no events attached');
  23800. return false;
  23801. }
  23802. else if(settings.on == 'auto') {
  23803. if( $module.is('input') ) {
  23804. return (element.oninput !== undefined)
  23805. ? 'input'
  23806. : (element.onpropertychange !== undefined)
  23807. ? 'propertychange'
  23808. : 'keyup'
  23809. ;
  23810. }
  23811. else if( $module.is('form') ) {
  23812. return 'submit';
  23813. }
  23814. else {
  23815. return 'click';
  23816. }
  23817. }
  23818. else {
  23819. return settings.on;
  23820. }
  23821. },
  23822. templatedURL: function(action) {
  23823. action = action || $module.data(metadata.action) || settings.action || false;
  23824. url = $module.data(metadata.url) || settings.url || false;
  23825. if(url) {
  23826. module.debug('Using specified url', url);
  23827. return url;
  23828. }
  23829. if(action) {
  23830. module.debug('Looking up url for action', action, settings.api);
  23831. if(settings.api[action] === undefined && !module.is.mocked()) {
  23832. module.error(error.missingAction, settings.action, settings.api);
  23833. return;
  23834. }
  23835. url = settings.api[action];
  23836. }
  23837. else if( module.is.form() ) {
  23838. url = $module.attr('action') || $context.attr('action') || false;
  23839. module.debug('No url or action specified, defaulting to form action', url);
  23840. }
  23841. return url;
  23842. }
  23843. },
  23844. abort: function() {
  23845. var
  23846. xhr = module.get.xhr()
  23847. ;
  23848. if( xhr && xhr.state() !== 'resolved') {
  23849. module.debug('Cancelling API request');
  23850. xhr.abort();
  23851. }
  23852. },
  23853. // reset state
  23854. reset: function() {
  23855. module.remove.error();
  23856. module.remove.loading();
  23857. },
  23858. setting: function(name, value) {
  23859. module.debug('Changing setting', name, value);
  23860. if( $.isPlainObject(name) ) {
  23861. $.extend(true, settings, name);
  23862. }
  23863. else if(value !== undefined) {
  23864. if($.isPlainObject(settings[name])) {
  23865. $.extend(true, settings[name], value);
  23866. }
  23867. else {
  23868. settings[name] = value;
  23869. }
  23870. }
  23871. else {
  23872. return settings[name];
  23873. }
  23874. },
  23875. internal: function(name, value) {
  23876. if( $.isPlainObject(name) ) {
  23877. $.extend(true, module, name);
  23878. }
  23879. else if(value !== undefined) {
  23880. module[name] = value;
  23881. }
  23882. else {
  23883. return module[name];
  23884. }
  23885. },
  23886. debug: function() {
  23887. if(!settings.silent && settings.debug) {
  23888. if(settings.performance) {
  23889. module.performance.log(arguments);
  23890. }
  23891. else {
  23892. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  23893. module.debug.apply(console, arguments);
  23894. }
  23895. }
  23896. },
  23897. verbose: function() {
  23898. if(!settings.silent && settings.verbose && settings.debug) {
  23899. if(settings.performance) {
  23900. module.performance.log(arguments);
  23901. }
  23902. else {
  23903. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  23904. module.verbose.apply(console, arguments);
  23905. }
  23906. }
  23907. },
  23908. error: function() {
  23909. if(!settings.silent) {
  23910. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  23911. module.error.apply(console, arguments);
  23912. }
  23913. },
  23914. performance: {
  23915. log: function(message) {
  23916. var
  23917. currentTime,
  23918. executionTime,
  23919. previousTime
  23920. ;
  23921. if(settings.performance) {
  23922. currentTime = new Date().getTime();
  23923. previousTime = time || currentTime;
  23924. executionTime = currentTime - previousTime;
  23925. time = currentTime;
  23926. performance.push({
  23927. 'Name' : message[0],
  23928. 'Arguments' : [].slice.call(message, 1) || '',
  23929. //'Element' : element,
  23930. 'Execution Time' : executionTime
  23931. });
  23932. }
  23933. clearTimeout(module.performance.timer);
  23934. module.performance.timer = setTimeout(module.performance.display, 500);
  23935. },
  23936. display: function() {
  23937. var
  23938. title = settings.name + ':',
  23939. totalTime = 0
  23940. ;
  23941. time = false;
  23942. clearTimeout(module.performance.timer);
  23943. $.each(performance, function(index, data) {
  23944. totalTime += data['Execution Time'];
  23945. });
  23946. title += ' ' + totalTime + 'ms';
  23947. if(moduleSelector) {
  23948. title += ' \'' + moduleSelector + '\'';
  23949. }
  23950. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  23951. console.groupCollapsed(title);
  23952. if(console.table) {
  23953. console.table(performance);
  23954. }
  23955. else {
  23956. $.each(performance, function(index, data) {
  23957. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  23958. });
  23959. }
  23960. console.groupEnd();
  23961. }
  23962. performance = [];
  23963. }
  23964. },
  23965. invoke: function(query, passedArguments, context) {
  23966. var
  23967. object = instance,
  23968. maxDepth,
  23969. found,
  23970. response
  23971. ;
  23972. passedArguments = passedArguments || queryArguments;
  23973. context = element || context;
  23974. if(typeof query == 'string' && object !== undefined) {
  23975. query = query.split(/[\. ]/);
  23976. maxDepth = query.length - 1;
  23977. $.each(query, function(depth, value) {
  23978. var camelCaseValue = (depth != maxDepth)
  23979. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  23980. : query
  23981. ;
  23982. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  23983. object = object[camelCaseValue];
  23984. }
  23985. else if( object[camelCaseValue] !== undefined ) {
  23986. found = object[camelCaseValue];
  23987. return false;
  23988. }
  23989. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  23990. object = object[value];
  23991. }
  23992. else if( object[value] !== undefined ) {
  23993. found = object[value];
  23994. return false;
  23995. }
  23996. else {
  23997. module.error(error.method, query);
  23998. return false;
  23999. }
  24000. });
  24001. }
  24002. if ( $.isFunction( found ) ) {
  24003. response = found.apply(context, passedArguments);
  24004. }
  24005. else if(found !== undefined) {
  24006. response = found;
  24007. }
  24008. if(Array.isArray(returnedValue)) {
  24009. returnedValue.push(response);
  24010. }
  24011. else if(returnedValue !== undefined) {
  24012. returnedValue = [returnedValue, response];
  24013. }
  24014. else if(response !== undefined) {
  24015. returnedValue = response;
  24016. }
  24017. return found;
  24018. }
  24019. };
  24020. if(methodInvoked) {
  24021. if(instance === undefined) {
  24022. module.initialize();
  24023. }
  24024. module.invoke(query);
  24025. }
  24026. else {
  24027. if(instance !== undefined) {
  24028. instance.invoke('destroy');
  24029. }
  24030. module.initialize();
  24031. }
  24032. })
  24033. ;
  24034. return (returnedValue !== undefined)
  24035. ? returnedValue
  24036. : this
  24037. ;
  24038. };
  24039. $.api.settings = {
  24040. name : 'API',
  24041. namespace : 'api',
  24042. debug : false,
  24043. verbose : false,
  24044. performance : true,
  24045. // object containing all templates endpoints
  24046. api : {},
  24047. // whether to cache responses
  24048. cache : true,
  24049. // whether new requests should abort previous requests
  24050. interruptRequests : true,
  24051. // event binding
  24052. on : 'auto',
  24053. // context for applying state classes
  24054. stateContext : false,
  24055. // duration for loading state
  24056. loadingDuration : 0,
  24057. // whether to hide errors after a period of time
  24058. hideError : 'auto',
  24059. // duration for error state
  24060. errorDuration : 2000,
  24061. // whether parameters should be encoded with encodeURIComponent
  24062. encodeParameters : true,
  24063. // API action to use
  24064. action : false,
  24065. // templated URL to use
  24066. url : false,
  24067. // base URL to apply to all endpoints
  24068. base : '',
  24069. // data that will
  24070. urlData : {},
  24071. // whether to add default data to url data
  24072. defaultData : true,
  24073. // whether to serialize closest form
  24074. serializeForm : false,
  24075. // how long to wait before request should occur
  24076. throttle : 0,
  24077. // whether to throttle first request or only repeated
  24078. throttleFirstRequest : true,
  24079. // standard ajax settings
  24080. method : 'get',
  24081. data : {},
  24082. dataType : 'json',
  24083. // mock response
  24084. mockResponse : false,
  24085. mockResponseAsync : false,
  24086. // aliases for mock
  24087. response : false,
  24088. responseAsync : false,
  24089. // whether onResponse should work with response value without force converting into an object
  24090. rawResponse : false,
  24091. // callbacks before request
  24092. beforeSend : function(settings) { return settings; },
  24093. beforeXHR : function(xhr) {},
  24094. onRequest : function(promise, xhr) {},
  24095. // after request
  24096. onResponse : false, // function(response) { },
  24097. // response was successful, if JSON passed validation
  24098. onSuccess : function(response, $module) {},
  24099. // request finished without aborting
  24100. onComplete : function(response, $module) {},
  24101. // failed JSON success test
  24102. onFailure : function(response, $module) {},
  24103. // server error
  24104. onError : function(errorMessage, $module) {},
  24105. // request aborted
  24106. onAbort : function(errorMessage, $module) {},
  24107. successTest : false,
  24108. // errors
  24109. error : {
  24110. beforeSend : 'The before send function has aborted the request',
  24111. error : 'There was an error with your request',
  24112. exitConditions : 'API Request Aborted. Exit conditions met',
  24113. JSONParse : 'JSON could not be parsed during error handling',
  24114. legacyParameters : 'You are using legacy API success callback names',
  24115. method : 'The method you called is not defined',
  24116. missingAction : 'API action used but no url was defined',
  24117. missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
  24118. missingURL : 'No URL specified for api event',
  24119. noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
  24120. noStorage : 'Caching responses locally requires session storage',
  24121. parseError : 'There was an error parsing your request',
  24122. requiredParameter : 'Missing a required URL parameter: ',
  24123. statusMessage : 'Server gave an error: ',
  24124. timeout : 'Your request timed out'
  24125. },
  24126. regExp : {
  24127. required : /\{\$*[A-z0-9]+\}/g,
  24128. optional : /\{\/\$*[A-z0-9]+\}/g,
  24129. },
  24130. className: {
  24131. loading : 'loading',
  24132. error : 'error'
  24133. },
  24134. selector: {
  24135. disabled : '.disabled',
  24136. form : 'form'
  24137. },
  24138. metadata: {
  24139. action : 'action',
  24140. url : 'url'
  24141. }
  24142. };
  24143. })( jQuery, window, document );
  24144. /*!
  24145. * # Fomantic-UI - State
  24146. * http://github.com/fomantic/Fomantic-UI/
  24147. *
  24148. *
  24149. * Released under the MIT license
  24150. * http://opensource.org/licenses/MIT
  24151. *
  24152. */
  24153. ;(function ($, window, document, undefined) {
  24154. "use strict";
  24155. $.isFunction = $.isFunction || function(obj) {
  24156. return typeof obj === "function" && typeof obj.nodeType !== "number";
  24157. };
  24158. window = (typeof window != 'undefined' && window.Math == Math)
  24159. ? window
  24160. : (typeof self != 'undefined' && self.Math == Math)
  24161. ? self
  24162. : Function('return this')()
  24163. ;
  24164. $.fn.state = function(parameters) {
  24165. var
  24166. $allModules = $(this),
  24167. moduleSelector = $allModules.selector || '',
  24168. time = new Date().getTime(),
  24169. performance = [],
  24170. query = arguments[0],
  24171. methodInvoked = (typeof query == 'string'),
  24172. queryArguments = [].slice.call(arguments, 1),
  24173. returnedValue
  24174. ;
  24175. $allModules
  24176. .each(function() {
  24177. var
  24178. settings = ( $.isPlainObject(parameters) )
  24179. ? $.extend(true, {}, $.fn.state.settings, parameters)
  24180. : $.extend({}, $.fn.state.settings),
  24181. error = settings.error,
  24182. metadata = settings.metadata,
  24183. className = settings.className,
  24184. namespace = settings.namespace,
  24185. states = settings.states,
  24186. text = settings.text,
  24187. eventNamespace = '.' + namespace,
  24188. moduleNamespace = namespace + '-module',
  24189. $module = $(this),
  24190. element = this,
  24191. instance = $module.data(moduleNamespace),
  24192. module
  24193. ;
  24194. module = {
  24195. initialize: function() {
  24196. module.verbose('Initializing module');
  24197. // allow module to guess desired state based on element
  24198. if(settings.automatic) {
  24199. module.add.defaults();
  24200. }
  24201. // bind events with delegated events
  24202. if(settings.context && moduleSelector !== '') {
  24203. $(settings.context)
  24204. .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text)
  24205. .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text)
  24206. .on(moduleSelector, 'click' + eventNamespace, module.toggle.state)
  24207. ;
  24208. }
  24209. else {
  24210. $module
  24211. .on('mouseenter' + eventNamespace, module.change.text)
  24212. .on('mouseleave' + eventNamespace, module.reset.text)
  24213. .on('click' + eventNamespace, module.toggle.state)
  24214. ;
  24215. }
  24216. module.instantiate();
  24217. },
  24218. instantiate: function() {
  24219. module.verbose('Storing instance of module', module);
  24220. instance = module;
  24221. $module
  24222. .data(moduleNamespace, module)
  24223. ;
  24224. },
  24225. destroy: function() {
  24226. module.verbose('Destroying previous module', instance);
  24227. $module
  24228. .off(eventNamespace)
  24229. .removeData(moduleNamespace)
  24230. ;
  24231. },
  24232. refresh: function() {
  24233. module.verbose('Refreshing selector cache');
  24234. $module = $(element);
  24235. },
  24236. add: {
  24237. defaults: function() {
  24238. var
  24239. userStates = parameters && $.isPlainObject(parameters.states)
  24240. ? parameters.states
  24241. : {}
  24242. ;
  24243. $.each(settings.defaults, function(type, typeStates) {
  24244. if( module.is[type] !== undefined && module.is[type]() ) {
  24245. module.verbose('Adding default states', type, element);
  24246. $.extend(settings.states, typeStates, userStates);
  24247. }
  24248. });
  24249. }
  24250. },
  24251. is: {
  24252. active: function() {
  24253. return $module.hasClass(className.active);
  24254. },
  24255. loading: function() {
  24256. return $module.hasClass(className.loading);
  24257. },
  24258. inactive: function() {
  24259. return !( $module.hasClass(className.active) );
  24260. },
  24261. state: function(state) {
  24262. if(className[state] === undefined) {
  24263. return false;
  24264. }
  24265. return $module.hasClass( className[state] );
  24266. },
  24267. enabled: function() {
  24268. return !( $module.is(settings.filter.active) );
  24269. },
  24270. disabled: function() {
  24271. return ( $module.is(settings.filter.active) );
  24272. },
  24273. textEnabled: function() {
  24274. return !( $module.is(settings.filter.text) );
  24275. },
  24276. // definitions for automatic type detection
  24277. button: function() {
  24278. return $module.is('.button:not(a, .submit)');
  24279. },
  24280. input: function() {
  24281. return $module.is('input');
  24282. },
  24283. progress: function() {
  24284. return $module.is('.ui.progress');
  24285. }
  24286. },
  24287. allow: function(state) {
  24288. module.debug('Now allowing state', state);
  24289. states[state] = true;
  24290. },
  24291. disallow: function(state) {
  24292. module.debug('No longer allowing', state);
  24293. states[state] = false;
  24294. },
  24295. allows: function(state) {
  24296. return states[state] || false;
  24297. },
  24298. enable: function() {
  24299. $module.removeClass(className.disabled);
  24300. },
  24301. disable: function() {
  24302. $module.addClass(className.disabled);
  24303. },
  24304. setState: function(state) {
  24305. if(module.allows(state)) {
  24306. $module.addClass( className[state] );
  24307. }
  24308. },
  24309. removeState: function(state) {
  24310. if(module.allows(state)) {
  24311. $module.removeClass( className[state] );
  24312. }
  24313. },
  24314. toggle: {
  24315. state: function() {
  24316. var
  24317. apiRequest,
  24318. requestCancelled
  24319. ;
  24320. if( module.allows('active') && module.is.enabled() ) {
  24321. module.refresh();
  24322. if($.fn.api !== undefined) {
  24323. apiRequest = $module.api('get request');
  24324. requestCancelled = $module.api('was cancelled');
  24325. if( requestCancelled ) {
  24326. module.debug('API Request cancelled by beforesend');
  24327. settings.activateTest = function(){ return false; };
  24328. settings.deactivateTest = function(){ return false; };
  24329. }
  24330. else if(apiRequest) {
  24331. module.listenTo(apiRequest);
  24332. return;
  24333. }
  24334. }
  24335. module.change.state();
  24336. }
  24337. }
  24338. },
  24339. listenTo: function(apiRequest) {
  24340. module.debug('API request detected, waiting for state signal', apiRequest);
  24341. if(apiRequest) {
  24342. if(text.loading) {
  24343. module.update.text(text.loading);
  24344. }
  24345. $.when(apiRequest)
  24346. .then(function() {
  24347. if(apiRequest.state() == 'resolved') {
  24348. module.debug('API request succeeded');
  24349. settings.activateTest = function(){ return true; };
  24350. settings.deactivateTest = function(){ return true; };
  24351. }
  24352. else {
  24353. module.debug('API request failed');
  24354. settings.activateTest = function(){ return false; };
  24355. settings.deactivateTest = function(){ return false; };
  24356. }
  24357. module.change.state();
  24358. })
  24359. ;
  24360. }
  24361. },
  24362. // checks whether active/inactive state can be given
  24363. change: {
  24364. state: function() {
  24365. module.debug('Determining state change direction');
  24366. // inactive to active change
  24367. if( module.is.inactive() ) {
  24368. module.activate();
  24369. }
  24370. else {
  24371. module.deactivate();
  24372. }
  24373. if(settings.sync) {
  24374. module.sync();
  24375. }
  24376. settings.onChange.call(element);
  24377. },
  24378. text: function() {
  24379. if( module.is.textEnabled() ) {
  24380. if(module.is.disabled() ) {
  24381. module.verbose('Changing text to disabled text', text.hover);
  24382. module.update.text(text.disabled);
  24383. }
  24384. else if( module.is.active() ) {
  24385. if(text.hover) {
  24386. module.verbose('Changing text to hover text', text.hover);
  24387. module.update.text(text.hover);
  24388. }
  24389. else if(text.deactivate) {
  24390. module.verbose('Changing text to deactivating text', text.deactivate);
  24391. module.update.text(text.deactivate);
  24392. }
  24393. }
  24394. else {
  24395. if(text.hover) {
  24396. module.verbose('Changing text to hover text', text.hover);
  24397. module.update.text(text.hover);
  24398. }
  24399. else if(text.activate){
  24400. module.verbose('Changing text to activating text', text.activate);
  24401. module.update.text(text.activate);
  24402. }
  24403. }
  24404. }
  24405. }
  24406. },
  24407. activate: function() {
  24408. if( settings.activateTest.call(element) ) {
  24409. module.debug('Setting state to active');
  24410. $module
  24411. .addClass(className.active)
  24412. ;
  24413. module.update.text(text.active);
  24414. settings.onActivate.call(element);
  24415. }
  24416. },
  24417. deactivate: function() {
  24418. if( settings.deactivateTest.call(element) ) {
  24419. module.debug('Setting state to inactive');
  24420. $module
  24421. .removeClass(className.active)
  24422. ;
  24423. module.update.text(text.inactive);
  24424. settings.onDeactivate.call(element);
  24425. }
  24426. },
  24427. sync: function() {
  24428. module.verbose('Syncing other buttons to current state');
  24429. if( module.is.active() ) {
  24430. $allModules
  24431. .not($module)
  24432. .state('activate');
  24433. }
  24434. else {
  24435. $allModules
  24436. .not($module)
  24437. .state('deactivate')
  24438. ;
  24439. }
  24440. },
  24441. get: {
  24442. text: function() {
  24443. return (settings.selector.text)
  24444. ? $module.find(settings.selector.text).text()
  24445. : $module.html()
  24446. ;
  24447. },
  24448. textFor: function(state) {
  24449. return text[state] || false;
  24450. }
  24451. },
  24452. flash: {
  24453. text: function(text, duration, callback) {
  24454. var
  24455. previousText = module.get.text()
  24456. ;
  24457. module.debug('Flashing text message', text, duration);
  24458. text = text || settings.text.flash;
  24459. duration = duration || settings.flashDuration;
  24460. callback = callback || function() {};
  24461. module.update.text(text);
  24462. setTimeout(function(){
  24463. module.update.text(previousText);
  24464. callback.call(element);
  24465. }, duration);
  24466. }
  24467. },
  24468. reset: {
  24469. // on mouseout sets text to previous value
  24470. text: function() {
  24471. var
  24472. activeText = text.active || $module.data(metadata.storedText),
  24473. inactiveText = text.inactive || $module.data(metadata.storedText)
  24474. ;
  24475. if( module.is.textEnabled() ) {
  24476. if( module.is.active() && activeText) {
  24477. module.verbose('Resetting active text', activeText);
  24478. module.update.text(activeText);
  24479. }
  24480. else if(inactiveText) {
  24481. module.verbose('Resetting inactive text', activeText);
  24482. module.update.text(inactiveText);
  24483. }
  24484. }
  24485. }
  24486. },
  24487. update: {
  24488. text: function(text) {
  24489. var
  24490. currentText = module.get.text()
  24491. ;
  24492. if(text && text !== currentText) {
  24493. module.debug('Updating text', text);
  24494. if(settings.selector.text) {
  24495. $module
  24496. .data(metadata.storedText, text)
  24497. .find(settings.selector.text)
  24498. .text(text)
  24499. ;
  24500. }
  24501. else {
  24502. $module
  24503. .data(metadata.storedText, text)
  24504. .html(text)
  24505. ;
  24506. }
  24507. }
  24508. else {
  24509. module.debug('Text is already set, ignoring update', text);
  24510. }
  24511. }
  24512. },
  24513. setting: function(name, value) {
  24514. module.debug('Changing setting', name, value);
  24515. if( $.isPlainObject(name) ) {
  24516. $.extend(true, settings, name);
  24517. }
  24518. else if(value !== undefined) {
  24519. if($.isPlainObject(settings[name])) {
  24520. $.extend(true, settings[name], value);
  24521. }
  24522. else {
  24523. settings[name] = value;
  24524. }
  24525. }
  24526. else {
  24527. return settings[name];
  24528. }
  24529. },
  24530. internal: function(name, value) {
  24531. if( $.isPlainObject(name) ) {
  24532. $.extend(true, module, name);
  24533. }
  24534. else if(value !== undefined) {
  24535. module[name] = value;
  24536. }
  24537. else {
  24538. return module[name];
  24539. }
  24540. },
  24541. debug: function() {
  24542. if(!settings.silent && settings.debug) {
  24543. if(settings.performance) {
  24544. module.performance.log(arguments);
  24545. }
  24546. else {
  24547. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  24548. module.debug.apply(console, arguments);
  24549. }
  24550. }
  24551. },
  24552. verbose: function() {
  24553. if(!settings.silent && settings.verbose && settings.debug) {
  24554. if(settings.performance) {
  24555. module.performance.log(arguments);
  24556. }
  24557. else {
  24558. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  24559. module.verbose.apply(console, arguments);
  24560. }
  24561. }
  24562. },
  24563. error: function() {
  24564. if(!settings.silent) {
  24565. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  24566. module.error.apply(console, arguments);
  24567. }
  24568. },
  24569. performance: {
  24570. log: function(message) {
  24571. var
  24572. currentTime,
  24573. executionTime,
  24574. previousTime
  24575. ;
  24576. if(settings.performance) {
  24577. currentTime = new Date().getTime();
  24578. previousTime = time || currentTime;
  24579. executionTime = currentTime - previousTime;
  24580. time = currentTime;
  24581. performance.push({
  24582. 'Name' : message[0],
  24583. 'Arguments' : [].slice.call(message, 1) || '',
  24584. 'Element' : element,
  24585. 'Execution Time' : executionTime
  24586. });
  24587. }
  24588. clearTimeout(module.performance.timer);
  24589. module.performance.timer = setTimeout(module.performance.display, 500);
  24590. },
  24591. display: function() {
  24592. var
  24593. title = settings.name + ':',
  24594. totalTime = 0
  24595. ;
  24596. time = false;
  24597. clearTimeout(module.performance.timer);
  24598. $.each(performance, function(index, data) {
  24599. totalTime += data['Execution Time'];
  24600. });
  24601. title += ' ' + totalTime + 'ms';
  24602. if(moduleSelector) {
  24603. title += ' \'' + moduleSelector + '\'';
  24604. }
  24605. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  24606. console.groupCollapsed(title);
  24607. if(console.table) {
  24608. console.table(performance);
  24609. }
  24610. else {
  24611. $.each(performance, function(index, data) {
  24612. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  24613. });
  24614. }
  24615. console.groupEnd();
  24616. }
  24617. performance = [];
  24618. }
  24619. },
  24620. invoke: function(query, passedArguments, context) {
  24621. var
  24622. object = instance,
  24623. maxDepth,
  24624. found,
  24625. response
  24626. ;
  24627. passedArguments = passedArguments || queryArguments;
  24628. context = element || context;
  24629. if(typeof query == 'string' && object !== undefined) {
  24630. query = query.split(/[\. ]/);
  24631. maxDepth = query.length - 1;
  24632. $.each(query, function(depth, value) {
  24633. var camelCaseValue = (depth != maxDepth)
  24634. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  24635. : query
  24636. ;
  24637. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  24638. object = object[camelCaseValue];
  24639. }
  24640. else if( object[camelCaseValue] !== undefined ) {
  24641. found = object[camelCaseValue];
  24642. return false;
  24643. }
  24644. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  24645. object = object[value];
  24646. }
  24647. else if( object[value] !== undefined ) {
  24648. found = object[value];
  24649. return false;
  24650. }
  24651. else {
  24652. module.error(error.method, query);
  24653. return false;
  24654. }
  24655. });
  24656. }
  24657. if ( $.isFunction( found ) ) {
  24658. response = found.apply(context, passedArguments);
  24659. }
  24660. else if(found !== undefined) {
  24661. response = found;
  24662. }
  24663. if(Array.isArray(returnedValue)) {
  24664. returnedValue.push(response);
  24665. }
  24666. else if(returnedValue !== undefined) {
  24667. returnedValue = [returnedValue, response];
  24668. }
  24669. else if(response !== undefined) {
  24670. returnedValue = response;
  24671. }
  24672. return found;
  24673. }
  24674. };
  24675. if(methodInvoked) {
  24676. if(instance === undefined) {
  24677. module.initialize();
  24678. }
  24679. module.invoke(query);
  24680. }
  24681. else {
  24682. if(instance !== undefined) {
  24683. instance.invoke('destroy');
  24684. }
  24685. module.initialize();
  24686. }
  24687. })
  24688. ;
  24689. return (returnedValue !== undefined)
  24690. ? returnedValue
  24691. : this
  24692. ;
  24693. };
  24694. $.fn.state.settings = {
  24695. // module info
  24696. name : 'State',
  24697. // debug output
  24698. debug : false,
  24699. // verbose debug output
  24700. verbose : false,
  24701. // namespace for events
  24702. namespace : 'state',
  24703. // debug data includes performance
  24704. performance : true,
  24705. // callback occurs on state change
  24706. onActivate : function() {},
  24707. onDeactivate : function() {},
  24708. onChange : function() {},
  24709. // state test functions
  24710. activateTest : function() { return true; },
  24711. deactivateTest : function() { return true; },
  24712. // whether to automatically map default states
  24713. automatic : true,
  24714. // activate / deactivate changes all elements instantiated at same time
  24715. sync : false,
  24716. // default flash text duration, used for temporarily changing text of an element
  24717. flashDuration : 1000,
  24718. // selector filter
  24719. filter : {
  24720. text : '.loading, .disabled',
  24721. active : '.disabled'
  24722. },
  24723. context : false,
  24724. // error
  24725. error: {
  24726. beforeSend : 'The before send function has cancelled state change',
  24727. method : 'The method you called is not defined.'
  24728. },
  24729. // metadata
  24730. metadata: {
  24731. promise : 'promise',
  24732. storedText : 'stored-text'
  24733. },
  24734. // change class on state
  24735. className: {
  24736. active : 'active',
  24737. disabled : 'disabled',
  24738. error : 'error',
  24739. loading : 'loading',
  24740. success : 'success',
  24741. warning : 'warning'
  24742. },
  24743. selector: {
  24744. // selector for text node
  24745. text: false
  24746. },
  24747. defaults : {
  24748. input: {
  24749. disabled : true,
  24750. loading : true,
  24751. active : true
  24752. },
  24753. button: {
  24754. disabled : true,
  24755. loading : true,
  24756. active : true,
  24757. },
  24758. progress: {
  24759. active : true,
  24760. success : true,
  24761. warning : true,
  24762. error : true
  24763. }
  24764. },
  24765. states : {
  24766. active : true,
  24767. disabled : true,
  24768. error : true,
  24769. loading : true,
  24770. success : true,
  24771. warning : true
  24772. },
  24773. text : {
  24774. disabled : false,
  24775. flash : false,
  24776. hover : false,
  24777. active : false,
  24778. inactive : false,
  24779. activate : false,
  24780. deactivate : false
  24781. }
  24782. };
  24783. })( jQuery, window, document );
  24784. /*!
  24785. * # Fomantic-UI - Visibility
  24786. * http://github.com/fomantic/Fomantic-UI/
  24787. *
  24788. *
  24789. * Released under the MIT license
  24790. * http://opensource.org/licenses/MIT
  24791. *
  24792. */
  24793. ;(function ($, window, document, undefined) {
  24794. 'use strict';
  24795. $.isFunction = $.isFunction || function(obj) {
  24796. return typeof obj === "function" && typeof obj.nodeType !== "number";
  24797. };
  24798. window = (typeof window != 'undefined' && window.Math == Math)
  24799. ? window
  24800. : (typeof self != 'undefined' && self.Math == Math)
  24801. ? self
  24802. : Function('return this')()
  24803. ;
  24804. $.fn.visibility = function(parameters) {
  24805. var
  24806. $allModules = $(this),
  24807. moduleSelector = $allModules.selector || '',
  24808. time = new Date().getTime(),
  24809. performance = [],
  24810. query = arguments[0],
  24811. methodInvoked = (typeof query == 'string'),
  24812. queryArguments = [].slice.call(arguments, 1),
  24813. returnedValue,
  24814. moduleCount = $allModules.length,
  24815. loadedCount = 0
  24816. ;
  24817. $allModules
  24818. .each(function() {
  24819. var
  24820. settings = ( $.isPlainObject(parameters) )
  24821. ? $.extend(true, {}, $.fn.visibility.settings, parameters)
  24822. : $.extend({}, $.fn.visibility.settings),
  24823. className = settings.className,
  24824. namespace = settings.namespace,
  24825. error = settings.error,
  24826. metadata = settings.metadata,
  24827. eventNamespace = '.' + namespace,
  24828. moduleNamespace = 'module-' + namespace,
  24829. $window = $(window),
  24830. $module = $(this),
  24831. $context = $(settings.context),
  24832. $placeholder,
  24833. instance = $module.data(moduleNamespace),
  24834. requestAnimationFrame = window.requestAnimationFrame
  24835. || window.mozRequestAnimationFrame
  24836. || window.webkitRequestAnimationFrame
  24837. || window.msRequestAnimationFrame
  24838. || function(callback) { setTimeout(callback, 0); },
  24839. element = this,
  24840. disabled = false,
  24841. contextObserver,
  24842. observer,
  24843. module
  24844. ;
  24845. module = {
  24846. initialize: function() {
  24847. module.debug('Initializing', settings);
  24848. module.setup.cache();
  24849. if( module.should.trackChanges() ) {
  24850. if(settings.type == 'image') {
  24851. module.setup.image();
  24852. }
  24853. if(settings.type == 'fixed') {
  24854. module.setup.fixed();
  24855. }
  24856. if(settings.observeChanges) {
  24857. module.observeChanges();
  24858. }
  24859. module.bind.events();
  24860. }
  24861. module.save.position();
  24862. if( !module.is.visible() ) {
  24863. module.error(error.visible, $module);
  24864. }
  24865. if(settings.initialCheck) {
  24866. module.checkVisibility();
  24867. }
  24868. module.instantiate();
  24869. },
  24870. instantiate: function() {
  24871. module.debug('Storing instance', module);
  24872. $module
  24873. .data(moduleNamespace, module)
  24874. ;
  24875. instance = module;
  24876. },
  24877. destroy: function() {
  24878. module.verbose('Destroying previous module');
  24879. if(observer) {
  24880. observer.disconnect();
  24881. }
  24882. if(contextObserver) {
  24883. contextObserver.disconnect();
  24884. }
  24885. $window
  24886. .off('load' + eventNamespace, module.event.load)
  24887. .off('resize' + eventNamespace, module.event.resize)
  24888. ;
  24889. $context
  24890. .off('scroll' + eventNamespace, module.event.scroll)
  24891. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  24892. ;
  24893. if(settings.type == 'fixed') {
  24894. module.resetFixed();
  24895. module.remove.placeholder();
  24896. }
  24897. $module
  24898. .off(eventNamespace)
  24899. .removeData(moduleNamespace)
  24900. ;
  24901. },
  24902. observeChanges: function() {
  24903. if('MutationObserver' in window) {
  24904. contextObserver = new MutationObserver(module.event.contextChanged);
  24905. observer = new MutationObserver(module.event.changed);
  24906. contextObserver.observe(document, {
  24907. childList : true,
  24908. subtree : true
  24909. });
  24910. observer.observe(element, {
  24911. childList : true,
  24912. subtree : true
  24913. });
  24914. module.debug('Setting up mutation observer', observer);
  24915. }
  24916. },
  24917. bind: {
  24918. events: function() {
  24919. module.verbose('Binding visibility events to scroll and resize');
  24920. if(settings.refreshOnLoad) {
  24921. $window
  24922. .on('load' + eventNamespace, module.event.load)
  24923. ;
  24924. }
  24925. $window
  24926. .on('resize' + eventNamespace, module.event.resize)
  24927. ;
  24928. // pub/sub pattern
  24929. $context
  24930. .off('scroll' + eventNamespace)
  24931. .on('scroll' + eventNamespace, module.event.scroll)
  24932. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  24933. ;
  24934. }
  24935. },
  24936. event: {
  24937. changed: function(mutations) {
  24938. module.verbose('DOM tree modified, updating visibility calculations');
  24939. module.timer = setTimeout(function() {
  24940. module.verbose('DOM tree modified, updating sticky menu');
  24941. module.refresh();
  24942. }, 100);
  24943. },
  24944. contextChanged: function(mutations) {
  24945. [].forEach.call(mutations, function(mutation) {
  24946. if(mutation.removedNodes) {
  24947. [].forEach.call(mutation.removedNodes, function(node) {
  24948. if(node == element || $(node).find(element).length > 0) {
  24949. module.debug('Element removed from DOM, tearing down events');
  24950. module.destroy();
  24951. }
  24952. });
  24953. }
  24954. });
  24955. },
  24956. resize: function() {
  24957. module.debug('Window resized');
  24958. if(settings.refreshOnResize) {
  24959. requestAnimationFrame(module.refresh);
  24960. }
  24961. },
  24962. load: function() {
  24963. module.debug('Page finished loading');
  24964. requestAnimationFrame(module.refresh);
  24965. },
  24966. // publishes scrollchange event on one scroll
  24967. scroll: function() {
  24968. if(settings.throttle) {
  24969. clearTimeout(module.timer);
  24970. module.timer = setTimeout(function() {
  24971. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  24972. }, settings.throttle);
  24973. }
  24974. else {
  24975. requestAnimationFrame(function() {
  24976. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  24977. });
  24978. }
  24979. },
  24980. // subscribes to scrollchange
  24981. scrollchange: function(event, scrollPosition) {
  24982. module.checkVisibility(scrollPosition);
  24983. },
  24984. },
  24985. precache: function(images, callback) {
  24986. if (!(images instanceof Array)) {
  24987. images = [images];
  24988. }
  24989. var
  24990. imagesLength = images.length,
  24991. loadedCounter = 0,
  24992. cache = [],
  24993. cacheImage = document.createElement('img'),
  24994. handleLoad = function() {
  24995. loadedCounter++;
  24996. if (loadedCounter >= images.length) {
  24997. if ($.isFunction(callback)) {
  24998. callback();
  24999. }
  25000. }
  25001. }
  25002. ;
  25003. while (imagesLength--) {
  25004. cacheImage = document.createElement('img');
  25005. cacheImage.onload = handleLoad;
  25006. cacheImage.onerror = handleLoad;
  25007. cacheImage.src = images[imagesLength];
  25008. cache.push(cacheImage);
  25009. }
  25010. },
  25011. enableCallbacks: function() {
  25012. module.debug('Allowing callbacks to occur');
  25013. disabled = false;
  25014. },
  25015. disableCallbacks: function() {
  25016. module.debug('Disabling all callbacks temporarily');
  25017. disabled = true;
  25018. },
  25019. should: {
  25020. trackChanges: function() {
  25021. if(methodInvoked) {
  25022. module.debug('One time query, no need to bind events');
  25023. return false;
  25024. }
  25025. module.debug('Callbacks being attached');
  25026. return true;
  25027. }
  25028. },
  25029. setup: {
  25030. cache: function() {
  25031. module.cache = {
  25032. occurred : {},
  25033. screen : {},
  25034. element : {},
  25035. };
  25036. },
  25037. image: function() {
  25038. var
  25039. src = $module.data(metadata.src)
  25040. ;
  25041. if(src) {
  25042. module.verbose('Lazy loading image', src);
  25043. settings.once = true;
  25044. settings.observeChanges = false;
  25045. // show when top visible
  25046. settings.onOnScreen = function() {
  25047. module.debug('Image on screen', element);
  25048. module.precache(src, function() {
  25049. module.set.image(src, function() {
  25050. loadedCount++;
  25051. if(loadedCount == moduleCount) {
  25052. settings.onAllLoaded.call(this);
  25053. }
  25054. settings.onLoad.call(this);
  25055. });
  25056. });
  25057. };
  25058. }
  25059. },
  25060. fixed: function() {
  25061. module.debug('Setting up fixed');
  25062. settings.once = false;
  25063. settings.observeChanges = false;
  25064. settings.initialCheck = true;
  25065. settings.refreshOnLoad = true;
  25066. if(!parameters.transition) {
  25067. settings.transition = false;
  25068. }
  25069. module.create.placeholder();
  25070. module.debug('Added placeholder', $placeholder);
  25071. settings.onTopPassed = function() {
  25072. module.debug('Element passed, adding fixed position', $module);
  25073. module.show.placeholder();
  25074. module.set.fixed();
  25075. if(settings.transition) {
  25076. if($.fn.transition !== undefined) {
  25077. $module.transition(settings.transition, settings.duration);
  25078. }
  25079. }
  25080. };
  25081. settings.onTopPassedReverse = function() {
  25082. module.debug('Element returned to position, removing fixed', $module);
  25083. module.hide.placeholder();
  25084. module.remove.fixed();
  25085. };
  25086. }
  25087. },
  25088. create: {
  25089. placeholder: function() {
  25090. module.verbose('Creating fixed position placeholder');
  25091. $placeholder = $module
  25092. .clone(false)
  25093. .css('display', 'none')
  25094. .addClass(className.placeholder)
  25095. .insertAfter($module)
  25096. ;
  25097. }
  25098. },
  25099. show: {
  25100. placeholder: function() {
  25101. module.verbose('Showing placeholder');
  25102. $placeholder
  25103. .css('display', 'block')
  25104. .css('visibility', 'hidden')
  25105. ;
  25106. }
  25107. },
  25108. hide: {
  25109. placeholder: function() {
  25110. module.verbose('Hiding placeholder');
  25111. $placeholder
  25112. .css('display', 'none')
  25113. .css('visibility', '')
  25114. ;
  25115. }
  25116. },
  25117. set: {
  25118. fixed: function() {
  25119. module.verbose('Setting element to fixed position');
  25120. $module
  25121. .addClass(className.fixed)
  25122. .css({
  25123. position : 'fixed',
  25124. top : settings.offset + 'px',
  25125. left : 'auto',
  25126. zIndex : settings.zIndex
  25127. })
  25128. ;
  25129. settings.onFixed.call(element);
  25130. },
  25131. image: function(src, callback) {
  25132. $module
  25133. .attr('src', src)
  25134. ;
  25135. if(settings.transition) {
  25136. if( $.fn.transition !== undefined) {
  25137. if($module.hasClass(className.visible)) {
  25138. module.debug('Transition already occurred on this image, skipping animation');
  25139. return;
  25140. }
  25141. $module.transition(settings.transition, settings.duration, callback);
  25142. }
  25143. else {
  25144. $module.fadeIn(settings.duration, callback);
  25145. }
  25146. }
  25147. else {
  25148. $module.show();
  25149. }
  25150. }
  25151. },
  25152. is: {
  25153. onScreen: function() {
  25154. var
  25155. calculations = module.get.elementCalculations()
  25156. ;
  25157. return calculations.onScreen;
  25158. },
  25159. offScreen: function() {
  25160. var
  25161. calculations = module.get.elementCalculations()
  25162. ;
  25163. return calculations.offScreen;
  25164. },
  25165. visible: function() {
  25166. if(module.cache && module.cache.element) {
  25167. return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
  25168. }
  25169. return false;
  25170. },
  25171. verticallyScrollableContext: function() {
  25172. var
  25173. overflowY = ($context.get(0) !== window)
  25174. ? $context.css('overflow-y')
  25175. : false
  25176. ;
  25177. return (overflowY == 'auto' || overflowY == 'scroll');
  25178. },
  25179. horizontallyScrollableContext: function() {
  25180. var
  25181. overflowX = ($context.get(0) !== window)
  25182. ? $context.css('overflow-x')
  25183. : false
  25184. ;
  25185. return (overflowX == 'auto' || overflowX == 'scroll');
  25186. }
  25187. },
  25188. refresh: function() {
  25189. module.debug('Refreshing constants (width/height)');
  25190. if(settings.type == 'fixed') {
  25191. module.resetFixed();
  25192. }
  25193. module.reset();
  25194. module.save.position();
  25195. if(settings.checkOnRefresh) {
  25196. module.checkVisibility();
  25197. }
  25198. settings.onRefresh.call(element);
  25199. },
  25200. resetFixed: function () {
  25201. module.remove.fixed();
  25202. module.remove.occurred();
  25203. },
  25204. reset: function() {
  25205. module.verbose('Resetting all cached values');
  25206. if( $.isPlainObject(module.cache) ) {
  25207. module.cache.screen = {};
  25208. module.cache.element = {};
  25209. }
  25210. },
  25211. checkVisibility: function(scroll) {
  25212. module.verbose('Checking visibility of element', module.cache.element);
  25213. if( !disabled && module.is.visible() ) {
  25214. // save scroll position
  25215. module.save.scroll(scroll);
  25216. // update calculations derived from scroll
  25217. module.save.calculations();
  25218. // percentage
  25219. module.passed();
  25220. // reverse (must be first)
  25221. module.passingReverse();
  25222. module.topVisibleReverse();
  25223. module.bottomVisibleReverse();
  25224. module.topPassedReverse();
  25225. module.bottomPassedReverse();
  25226. // one time
  25227. module.onScreen();
  25228. module.offScreen();
  25229. module.passing();
  25230. module.topVisible();
  25231. module.bottomVisible();
  25232. module.topPassed();
  25233. module.bottomPassed();
  25234. // on update callback
  25235. if(settings.onUpdate) {
  25236. settings.onUpdate.call(element, module.get.elementCalculations());
  25237. }
  25238. }
  25239. },
  25240. passed: function(amount, newCallback) {
  25241. var
  25242. calculations = module.get.elementCalculations()
  25243. ;
  25244. // assign callback
  25245. if(amount && newCallback) {
  25246. settings.onPassed[amount] = newCallback;
  25247. }
  25248. else if(amount !== undefined) {
  25249. return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
  25250. }
  25251. else if(calculations.passing) {
  25252. $.each(settings.onPassed, function(amount, callback) {
  25253. if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
  25254. module.execute(callback, amount);
  25255. }
  25256. else if(!settings.once) {
  25257. module.remove.occurred(callback);
  25258. }
  25259. });
  25260. }
  25261. },
  25262. onScreen: function(newCallback) {
  25263. var
  25264. calculations = module.get.elementCalculations(),
  25265. callback = newCallback || settings.onOnScreen,
  25266. callbackName = 'onScreen'
  25267. ;
  25268. if(newCallback) {
  25269. module.debug('Adding callback for onScreen', newCallback);
  25270. settings.onOnScreen = newCallback;
  25271. }
  25272. if(calculations.onScreen) {
  25273. module.execute(callback, callbackName);
  25274. }
  25275. else if(!settings.once) {
  25276. module.remove.occurred(callbackName);
  25277. }
  25278. if(newCallback !== undefined) {
  25279. return calculations.onOnScreen;
  25280. }
  25281. },
  25282. offScreen: function(newCallback) {
  25283. var
  25284. calculations = module.get.elementCalculations(),
  25285. callback = newCallback || settings.onOffScreen,
  25286. callbackName = 'offScreen'
  25287. ;
  25288. if(newCallback) {
  25289. module.debug('Adding callback for offScreen', newCallback);
  25290. settings.onOffScreen = newCallback;
  25291. }
  25292. if(calculations.offScreen) {
  25293. module.execute(callback, callbackName);
  25294. }
  25295. else if(!settings.once) {
  25296. module.remove.occurred(callbackName);
  25297. }
  25298. if(newCallback !== undefined) {
  25299. return calculations.onOffScreen;
  25300. }
  25301. },
  25302. passing: function(newCallback) {
  25303. var
  25304. calculations = module.get.elementCalculations(),
  25305. callback = newCallback || settings.onPassing,
  25306. callbackName = 'passing'
  25307. ;
  25308. if(newCallback) {
  25309. module.debug('Adding callback for passing', newCallback);
  25310. settings.onPassing = newCallback;
  25311. }
  25312. if(calculations.passing) {
  25313. module.execute(callback, callbackName);
  25314. }
  25315. else if(!settings.once) {
  25316. module.remove.occurred(callbackName);
  25317. }
  25318. if(newCallback !== undefined) {
  25319. return calculations.passing;
  25320. }
  25321. },
  25322. topVisible: function(newCallback) {
  25323. var
  25324. calculations = module.get.elementCalculations(),
  25325. callback = newCallback || settings.onTopVisible,
  25326. callbackName = 'topVisible'
  25327. ;
  25328. if(newCallback) {
  25329. module.debug('Adding callback for top visible', newCallback);
  25330. settings.onTopVisible = newCallback;
  25331. }
  25332. if(calculations.topVisible) {
  25333. module.execute(callback, callbackName);
  25334. }
  25335. else if(!settings.once) {
  25336. module.remove.occurred(callbackName);
  25337. }
  25338. if(newCallback === undefined) {
  25339. return calculations.topVisible;
  25340. }
  25341. },
  25342. bottomVisible: function(newCallback) {
  25343. var
  25344. calculations = module.get.elementCalculations(),
  25345. callback = newCallback || settings.onBottomVisible,
  25346. callbackName = 'bottomVisible'
  25347. ;
  25348. if(newCallback) {
  25349. module.debug('Adding callback for bottom visible', newCallback);
  25350. settings.onBottomVisible = newCallback;
  25351. }
  25352. if(calculations.bottomVisible) {
  25353. module.execute(callback, callbackName);
  25354. }
  25355. else if(!settings.once) {
  25356. module.remove.occurred(callbackName);
  25357. }
  25358. if(newCallback === undefined) {
  25359. return calculations.bottomVisible;
  25360. }
  25361. },
  25362. topPassed: function(newCallback) {
  25363. var
  25364. calculations = module.get.elementCalculations(),
  25365. callback = newCallback || settings.onTopPassed,
  25366. callbackName = 'topPassed'
  25367. ;
  25368. if(newCallback) {
  25369. module.debug('Adding callback for top passed', newCallback);
  25370. settings.onTopPassed = newCallback;
  25371. }
  25372. if(calculations.topPassed) {
  25373. module.execute(callback, callbackName);
  25374. }
  25375. else if(!settings.once) {
  25376. module.remove.occurred(callbackName);
  25377. }
  25378. if(newCallback === undefined) {
  25379. return calculations.topPassed;
  25380. }
  25381. },
  25382. bottomPassed: function(newCallback) {
  25383. var
  25384. calculations = module.get.elementCalculations(),
  25385. callback = newCallback || settings.onBottomPassed,
  25386. callbackName = 'bottomPassed'
  25387. ;
  25388. if(newCallback) {
  25389. module.debug('Adding callback for bottom passed', newCallback);
  25390. settings.onBottomPassed = newCallback;
  25391. }
  25392. if(calculations.bottomPassed) {
  25393. module.execute(callback, callbackName);
  25394. }
  25395. else if(!settings.once) {
  25396. module.remove.occurred(callbackName);
  25397. }
  25398. if(newCallback === undefined) {
  25399. return calculations.bottomPassed;
  25400. }
  25401. },
  25402. passingReverse: function(newCallback) {
  25403. var
  25404. calculations = module.get.elementCalculations(),
  25405. callback = newCallback || settings.onPassingReverse,
  25406. callbackName = 'passingReverse'
  25407. ;
  25408. if(newCallback) {
  25409. module.debug('Adding callback for passing reverse', newCallback);
  25410. settings.onPassingReverse = newCallback;
  25411. }
  25412. if(!calculations.passing) {
  25413. if(module.get.occurred('passing')) {
  25414. module.execute(callback, callbackName);
  25415. }
  25416. }
  25417. else if(!settings.once) {
  25418. module.remove.occurred(callbackName);
  25419. }
  25420. if(newCallback !== undefined) {
  25421. return !calculations.passing;
  25422. }
  25423. },
  25424. topVisibleReverse: function(newCallback) {
  25425. var
  25426. calculations = module.get.elementCalculations(),
  25427. callback = newCallback || settings.onTopVisibleReverse,
  25428. callbackName = 'topVisibleReverse'
  25429. ;
  25430. if(newCallback) {
  25431. module.debug('Adding callback for top visible reverse', newCallback);
  25432. settings.onTopVisibleReverse = newCallback;
  25433. }
  25434. if(!calculations.topVisible) {
  25435. if(module.get.occurred('topVisible')) {
  25436. module.execute(callback, callbackName);
  25437. }
  25438. }
  25439. else if(!settings.once) {
  25440. module.remove.occurred(callbackName);
  25441. }
  25442. if(newCallback === undefined) {
  25443. return !calculations.topVisible;
  25444. }
  25445. },
  25446. bottomVisibleReverse: function(newCallback) {
  25447. var
  25448. calculations = module.get.elementCalculations(),
  25449. callback = newCallback || settings.onBottomVisibleReverse,
  25450. callbackName = 'bottomVisibleReverse'
  25451. ;
  25452. if(newCallback) {
  25453. module.debug('Adding callback for bottom visible reverse', newCallback);
  25454. settings.onBottomVisibleReverse = newCallback;
  25455. }
  25456. if(!calculations.bottomVisible) {
  25457. if(module.get.occurred('bottomVisible')) {
  25458. module.execute(callback, callbackName);
  25459. }
  25460. }
  25461. else if(!settings.once) {
  25462. module.remove.occurred(callbackName);
  25463. }
  25464. if(newCallback === undefined) {
  25465. return !calculations.bottomVisible;
  25466. }
  25467. },
  25468. topPassedReverse: function(newCallback) {
  25469. var
  25470. calculations = module.get.elementCalculations(),
  25471. callback = newCallback || settings.onTopPassedReverse,
  25472. callbackName = 'topPassedReverse'
  25473. ;
  25474. if(newCallback) {
  25475. module.debug('Adding callback for top passed reverse', newCallback);
  25476. settings.onTopPassedReverse = newCallback;
  25477. }
  25478. if(!calculations.topPassed) {
  25479. if(module.get.occurred('topPassed')) {
  25480. module.execute(callback, callbackName);
  25481. }
  25482. }
  25483. else if(!settings.once) {
  25484. module.remove.occurred(callbackName);
  25485. }
  25486. if(newCallback === undefined) {
  25487. return !calculations.onTopPassed;
  25488. }
  25489. },
  25490. bottomPassedReverse: function(newCallback) {
  25491. var
  25492. calculations = module.get.elementCalculations(),
  25493. callback = newCallback || settings.onBottomPassedReverse,
  25494. callbackName = 'bottomPassedReverse'
  25495. ;
  25496. if(newCallback) {
  25497. module.debug('Adding callback for bottom passed reverse', newCallback);
  25498. settings.onBottomPassedReverse = newCallback;
  25499. }
  25500. if(!calculations.bottomPassed) {
  25501. if(module.get.occurred('bottomPassed')) {
  25502. module.execute(callback, callbackName);
  25503. }
  25504. }
  25505. else if(!settings.once) {
  25506. module.remove.occurred(callbackName);
  25507. }
  25508. if(newCallback === undefined) {
  25509. return !calculations.bottomPassed;
  25510. }
  25511. },
  25512. execute: function(callback, callbackName) {
  25513. var
  25514. calculations = module.get.elementCalculations(),
  25515. screen = module.get.screenCalculations()
  25516. ;
  25517. callback = callback || false;
  25518. if(callback) {
  25519. if(settings.continuous) {
  25520. module.debug('Callback being called continuously', callbackName, calculations);
  25521. callback.call(element, calculations, screen);
  25522. }
  25523. else if(!module.get.occurred(callbackName)) {
  25524. module.debug('Conditions met', callbackName, calculations);
  25525. callback.call(element, calculations, screen);
  25526. }
  25527. }
  25528. module.save.occurred(callbackName);
  25529. },
  25530. remove: {
  25531. fixed: function() {
  25532. module.debug('Removing fixed position');
  25533. $module
  25534. .removeClass(className.fixed)
  25535. .css({
  25536. position : '',
  25537. top : '',
  25538. left : '',
  25539. zIndex : ''
  25540. })
  25541. ;
  25542. settings.onUnfixed.call(element);
  25543. },
  25544. placeholder: function() {
  25545. module.debug('Removing placeholder content');
  25546. if($placeholder) {
  25547. $placeholder.remove();
  25548. }
  25549. },
  25550. occurred: function(callback) {
  25551. if(callback) {
  25552. var
  25553. occurred = module.cache.occurred
  25554. ;
  25555. if(occurred[callback] !== undefined && occurred[callback] === true) {
  25556. module.debug('Callback can now be called again', callback);
  25557. module.cache.occurred[callback] = false;
  25558. }
  25559. }
  25560. else {
  25561. module.cache.occurred = {};
  25562. }
  25563. }
  25564. },
  25565. save: {
  25566. calculations: function() {
  25567. module.verbose('Saving all calculations necessary to determine positioning');
  25568. module.save.direction();
  25569. module.save.screenCalculations();
  25570. module.save.elementCalculations();
  25571. },
  25572. occurred: function(callback) {
  25573. if(callback) {
  25574. if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
  25575. module.verbose('Saving callback occurred', callback);
  25576. module.cache.occurred[callback] = true;
  25577. }
  25578. }
  25579. },
  25580. scroll: function(scrollPosition) {
  25581. scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
  25582. module.cache.scroll = scrollPosition;
  25583. },
  25584. direction: function() {
  25585. var
  25586. scroll = module.get.scroll(),
  25587. lastScroll = module.get.lastScroll(),
  25588. direction
  25589. ;
  25590. if(scroll > lastScroll && lastScroll) {
  25591. direction = 'down';
  25592. }
  25593. else if(scroll < lastScroll && lastScroll) {
  25594. direction = 'up';
  25595. }
  25596. else {
  25597. direction = 'static';
  25598. }
  25599. module.cache.direction = direction;
  25600. return module.cache.direction;
  25601. },
  25602. elementPosition: function() {
  25603. var
  25604. element = module.cache.element,
  25605. screen = module.get.screenSize()
  25606. ;
  25607. module.verbose('Saving element position');
  25608. // (quicker than $.extend)
  25609. element.fits = (element.height < screen.height);
  25610. element.offset = $module.offset();
  25611. element.width = $module.outerWidth();
  25612. element.height = $module.outerHeight();
  25613. // compensate for scroll in context
  25614. if(module.is.verticallyScrollableContext()) {
  25615. element.offset.top += $context.scrollTop() - $context.offset().top;
  25616. }
  25617. if(module.is.horizontallyScrollableContext()) {
  25618. element.offset.left += $context.scrollLeft - $context.offset().left;
  25619. }
  25620. // store
  25621. module.cache.element = element;
  25622. return element;
  25623. },
  25624. elementCalculations: function() {
  25625. var
  25626. screen = module.get.screenCalculations(),
  25627. element = module.get.elementPosition()
  25628. ;
  25629. // offset
  25630. if(settings.includeMargin) {
  25631. element.margin = {};
  25632. element.margin.top = parseInt($module.css('margin-top'), 10);
  25633. element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
  25634. element.top = element.offset.top - element.margin.top;
  25635. element.bottom = element.offset.top + element.height + element.margin.bottom;
  25636. }
  25637. else {
  25638. element.top = element.offset.top;
  25639. element.bottom = element.offset.top + element.height;
  25640. }
  25641. // visibility
  25642. element.topPassed = (screen.top >= element.top);
  25643. element.bottomPassed = (screen.top >= element.bottom);
  25644. element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
  25645. element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
  25646. element.pixelsPassed = 0;
  25647. element.percentagePassed = 0;
  25648. // meta calculations
  25649. element.onScreen = ((element.topVisible || element.passing) && !element.bottomPassed);
  25650. element.passing = (element.topPassed && !element.bottomPassed);
  25651. element.offScreen = (!element.onScreen);
  25652. // passing calculations
  25653. if(element.passing) {
  25654. element.pixelsPassed = (screen.top - element.top);
  25655. element.percentagePassed = (screen.top - element.top) / element.height;
  25656. }
  25657. module.cache.element = element;
  25658. module.verbose('Updated element calculations', element);
  25659. return element;
  25660. },
  25661. screenCalculations: function() {
  25662. var
  25663. scroll = module.get.scroll()
  25664. ;
  25665. module.save.direction();
  25666. module.cache.screen.top = scroll;
  25667. module.cache.screen.bottom = scroll + module.cache.screen.height;
  25668. return module.cache.screen;
  25669. },
  25670. screenSize: function() {
  25671. module.verbose('Saving window position');
  25672. module.cache.screen = {
  25673. height: $context.height()
  25674. };
  25675. },
  25676. position: function() {
  25677. module.save.screenSize();
  25678. module.save.elementPosition();
  25679. }
  25680. },
  25681. get: {
  25682. pixelsPassed: function(amount) {
  25683. var
  25684. element = module.get.elementCalculations()
  25685. ;
  25686. if(amount.search('%') > -1) {
  25687. return ( element.height * (parseInt(amount, 10) / 100) );
  25688. }
  25689. return parseInt(amount, 10);
  25690. },
  25691. occurred: function(callback) {
  25692. return (module.cache.occurred !== undefined)
  25693. ? module.cache.occurred[callback] || false
  25694. : false
  25695. ;
  25696. },
  25697. direction: function() {
  25698. if(module.cache.direction === undefined) {
  25699. module.save.direction();
  25700. }
  25701. return module.cache.direction;
  25702. },
  25703. elementPosition: function() {
  25704. if(module.cache.element === undefined) {
  25705. module.save.elementPosition();
  25706. }
  25707. return module.cache.element;
  25708. },
  25709. elementCalculations: function() {
  25710. if(module.cache.element === undefined) {
  25711. module.save.elementCalculations();
  25712. }
  25713. return module.cache.element;
  25714. },
  25715. screenCalculations: function() {
  25716. if(module.cache.screen === undefined) {
  25717. module.save.screenCalculations();
  25718. }
  25719. return module.cache.screen;
  25720. },
  25721. screenSize: function() {
  25722. if(module.cache.screen === undefined) {
  25723. module.save.screenSize();
  25724. }
  25725. return module.cache.screen;
  25726. },
  25727. scroll: function() {
  25728. if(module.cache.scroll === undefined) {
  25729. module.save.scroll();
  25730. }
  25731. return module.cache.scroll;
  25732. },
  25733. lastScroll: function() {
  25734. if(module.cache.screen === undefined) {
  25735. module.debug('First scroll event, no last scroll could be found');
  25736. return false;
  25737. }
  25738. return module.cache.screen.top;
  25739. }
  25740. },
  25741. setting: function(name, value) {
  25742. if( $.isPlainObject(name) ) {
  25743. $.extend(true, settings, name);
  25744. }
  25745. else if(value !== undefined) {
  25746. settings[name] = value;
  25747. }
  25748. else {
  25749. return settings[name];
  25750. }
  25751. },
  25752. internal: function(name, value) {
  25753. if( $.isPlainObject(name) ) {
  25754. $.extend(true, module, name);
  25755. }
  25756. else if(value !== undefined) {
  25757. module[name] = value;
  25758. }
  25759. else {
  25760. return module[name];
  25761. }
  25762. },
  25763. debug: function() {
  25764. if(!settings.silent && settings.debug) {
  25765. if(settings.performance) {
  25766. module.performance.log(arguments);
  25767. }
  25768. else {
  25769. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  25770. module.debug.apply(console, arguments);
  25771. }
  25772. }
  25773. },
  25774. verbose: function() {
  25775. if(!settings.silent && settings.verbose && settings.debug) {
  25776. if(settings.performance) {
  25777. module.performance.log(arguments);
  25778. }
  25779. else {
  25780. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  25781. module.verbose.apply(console, arguments);
  25782. }
  25783. }
  25784. },
  25785. error: function() {
  25786. if(!settings.silent) {
  25787. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  25788. module.error.apply(console, arguments);
  25789. }
  25790. },
  25791. performance: {
  25792. log: function(message) {
  25793. var
  25794. currentTime,
  25795. executionTime,
  25796. previousTime
  25797. ;
  25798. if(settings.performance) {
  25799. currentTime = new Date().getTime();
  25800. previousTime = time || currentTime;
  25801. executionTime = currentTime - previousTime;
  25802. time = currentTime;
  25803. performance.push({
  25804. 'Name' : message[0],
  25805. 'Arguments' : [].slice.call(message, 1) || '',
  25806. 'Element' : element,
  25807. 'Execution Time' : executionTime
  25808. });
  25809. }
  25810. clearTimeout(module.performance.timer);
  25811. module.performance.timer = setTimeout(module.performance.display, 500);
  25812. },
  25813. display: function() {
  25814. var
  25815. title = settings.name + ':',
  25816. totalTime = 0
  25817. ;
  25818. time = false;
  25819. clearTimeout(module.performance.timer);
  25820. $.each(performance, function(index, data) {
  25821. totalTime += data['Execution Time'];
  25822. });
  25823. title += ' ' + totalTime + 'ms';
  25824. if(moduleSelector) {
  25825. title += ' \'' + moduleSelector + '\'';
  25826. }
  25827. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  25828. console.groupCollapsed(title);
  25829. if(console.table) {
  25830. console.table(performance);
  25831. }
  25832. else {
  25833. $.each(performance, function(index, data) {
  25834. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  25835. });
  25836. }
  25837. console.groupEnd();
  25838. }
  25839. performance = [];
  25840. }
  25841. },
  25842. invoke: function(query, passedArguments, context) {
  25843. var
  25844. object = instance,
  25845. maxDepth,
  25846. found,
  25847. response
  25848. ;
  25849. passedArguments = passedArguments || queryArguments;
  25850. context = element || context;
  25851. if(typeof query == 'string' && object !== undefined) {
  25852. query = query.split(/[\. ]/);
  25853. maxDepth = query.length - 1;
  25854. $.each(query, function(depth, value) {
  25855. var camelCaseValue = (depth != maxDepth)
  25856. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  25857. : query
  25858. ;
  25859. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  25860. object = object[camelCaseValue];
  25861. }
  25862. else if( object[camelCaseValue] !== undefined ) {
  25863. found = object[camelCaseValue];
  25864. return false;
  25865. }
  25866. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  25867. object = object[value];
  25868. }
  25869. else if( object[value] !== undefined ) {
  25870. found = object[value];
  25871. return false;
  25872. }
  25873. else {
  25874. module.error(error.method, query);
  25875. return false;
  25876. }
  25877. });
  25878. }
  25879. if ( $.isFunction( found ) ) {
  25880. response = found.apply(context, passedArguments);
  25881. }
  25882. else if(found !== undefined) {
  25883. response = found;
  25884. }
  25885. if(Array.isArray(returnedValue)) {
  25886. returnedValue.push(response);
  25887. }
  25888. else if(returnedValue !== undefined) {
  25889. returnedValue = [returnedValue, response];
  25890. }
  25891. else if(response !== undefined) {
  25892. returnedValue = response;
  25893. }
  25894. return found;
  25895. }
  25896. };
  25897. if(methodInvoked) {
  25898. if(instance === undefined) {
  25899. module.initialize();
  25900. }
  25901. instance.save.scroll();
  25902. instance.save.calculations();
  25903. module.invoke(query);
  25904. }
  25905. else {
  25906. if(instance !== undefined) {
  25907. instance.invoke('destroy');
  25908. }
  25909. module.initialize();
  25910. }
  25911. })
  25912. ;
  25913. return (returnedValue !== undefined)
  25914. ? returnedValue
  25915. : this
  25916. ;
  25917. };
  25918. $.fn.visibility.settings = {
  25919. name : 'Visibility',
  25920. namespace : 'visibility',
  25921. debug : false,
  25922. verbose : false,
  25923. performance : true,
  25924. // whether to use mutation observers to follow changes
  25925. observeChanges : true,
  25926. // check position immediately on init
  25927. initialCheck : true,
  25928. // whether to refresh calculations after all page images load
  25929. refreshOnLoad : true,
  25930. // whether to refresh calculations after page resize event
  25931. refreshOnResize : true,
  25932. // should call callbacks on refresh event (resize, etc)
  25933. checkOnRefresh : true,
  25934. // callback should only occur one time
  25935. once : true,
  25936. // callback should fire continuously whe evaluates to true
  25937. continuous : false,
  25938. // offset to use with scroll top
  25939. offset : 0,
  25940. // whether to include margin in elements position
  25941. includeMargin : false,
  25942. // scroll context for visibility checks
  25943. context : window,
  25944. // visibility check delay in ms (defaults to animationFrame)
  25945. throttle : false,
  25946. // special visibility type (image, fixed)
  25947. type : false,
  25948. // z-index to use with visibility 'fixed'
  25949. zIndex : '10',
  25950. // image only animation settings
  25951. transition : 'fade in',
  25952. duration : 1000,
  25953. // array of callbacks for percentage
  25954. onPassed : {},
  25955. // standard callbacks
  25956. onOnScreen : false,
  25957. onOffScreen : false,
  25958. onPassing : false,
  25959. onTopVisible : false,
  25960. onBottomVisible : false,
  25961. onTopPassed : false,
  25962. onBottomPassed : false,
  25963. // reverse callbacks
  25964. onPassingReverse : false,
  25965. onTopVisibleReverse : false,
  25966. onBottomVisibleReverse : false,
  25967. onTopPassedReverse : false,
  25968. onBottomPassedReverse : false,
  25969. // special callbacks for image
  25970. onLoad : function() {},
  25971. onAllLoaded : function() {},
  25972. // special callbacks for fixed position
  25973. onFixed : function() {},
  25974. onUnfixed : function() {},
  25975. // utility callbacks
  25976. onUpdate : false, // disabled by default for performance
  25977. onRefresh : function(){},
  25978. metadata : {
  25979. src: 'src'
  25980. },
  25981. className: {
  25982. fixed : 'fixed',
  25983. placeholder : 'constraint',
  25984. visible : 'visible'
  25985. },
  25986. error : {
  25987. method : 'The method you called is not defined.',
  25988. visible : 'Element is hidden, you must call refresh after element becomes visible'
  25989. }
  25990. };
  25991. })( jQuery, window, document );