Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pirms 3 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515
  1. /*
  2. * # Semantic UI - 2.4.1
  3. * https://github.com/Semantic-Org/Semantic-UI
  4. * http://www.semantic-ui.com/
  5. *
  6. * Copyright 2014 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. /*!
  12. * # Semantic UI 2.4.1 - Site
  13. * http://github.com/semantic-org/semantic-ui/
  14. *
  15. *
  16. * Released under the MIT license
  17. * http://opensource.org/licenses/MIT
  18. *
  19. */
  20. ;(function ($, window, document, undefined) {
  21. $.site = $.fn.site = function(parameters) {
  22. var
  23. time = new Date().getTime(),
  24. performance = [],
  25. query = arguments[0],
  26. methodInvoked = (typeof query == 'string'),
  27. queryArguments = [].slice.call(arguments, 1),
  28. settings = ( $.isPlainObject(parameters) )
  29. ? $.extend(true, {}, $.site.settings, parameters)
  30. : $.extend({}, $.site.settings),
  31. namespace = settings.namespace,
  32. error = settings.error,
  33. eventNamespace = '.' + namespace,
  34. moduleNamespace = 'module-' + namespace,
  35. $document = $(document),
  36. $module = $document,
  37. element = this,
  38. instance = $module.data(moduleNamespace),
  39. module,
  40. returnedValue
  41. ;
  42. module = {
  43. initialize: function() {
  44. module.instantiate();
  45. },
  46. instantiate: function() {
  47. module.verbose('Storing instance of site', module);
  48. instance = module;
  49. $module
  50. .data(moduleNamespace, module)
  51. ;
  52. },
  53. normalize: function() {
  54. module.fix.console();
  55. module.fix.requestAnimationFrame();
  56. },
  57. fix: {
  58. console: function() {
  59. module.debug('Normalizing window.console');
  60. if (console === undefined || console.log === undefined) {
  61. module.verbose('Console not available, normalizing events');
  62. module.disable.console();
  63. }
  64. if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
  65. module.verbose('Console group not available, normalizing events');
  66. window.console.group = function() {};
  67. window.console.groupEnd = function() {};
  68. window.console.groupCollapsed = function() {};
  69. }
  70. if (typeof console.markTimeline == 'undefined') {
  71. module.verbose('Mark timeline not available, normalizing events');
  72. window.console.markTimeline = function() {};
  73. }
  74. },
  75. consoleClear: function() {
  76. module.debug('Disabling programmatic console clearing');
  77. window.console.clear = function() {};
  78. },
  79. requestAnimationFrame: function() {
  80. module.debug('Normalizing requestAnimationFrame');
  81. if(window.requestAnimationFrame === undefined) {
  82. module.debug('RequestAnimationFrame not available, normalizing event');
  83. window.requestAnimationFrame = window.requestAnimationFrame
  84. || window.mozRequestAnimationFrame
  85. || window.webkitRequestAnimationFrame
  86. || window.msRequestAnimationFrame
  87. || function(callback) { setTimeout(callback, 0); }
  88. ;
  89. }
  90. }
  91. },
  92. moduleExists: function(name) {
  93. return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
  94. },
  95. enabled: {
  96. modules: function(modules) {
  97. var
  98. enabledModules = []
  99. ;
  100. modules = modules || settings.modules;
  101. $.each(modules, function(index, name) {
  102. if(module.moduleExists(name)) {
  103. enabledModules.push(name);
  104. }
  105. });
  106. return enabledModules;
  107. }
  108. },
  109. disabled: {
  110. modules: function(modules) {
  111. var
  112. disabledModules = []
  113. ;
  114. modules = modules || settings.modules;
  115. $.each(modules, function(index, name) {
  116. if(!module.moduleExists(name)) {
  117. disabledModules.push(name);
  118. }
  119. });
  120. return disabledModules;
  121. }
  122. },
  123. change: {
  124. setting: function(setting, value, modules, modifyExisting) {
  125. modules = (typeof modules === 'string')
  126. ? (modules === 'all')
  127. ? settings.modules
  128. : [modules]
  129. : modules || settings.modules
  130. ;
  131. modifyExisting = (modifyExisting !== undefined)
  132. ? modifyExisting
  133. : true
  134. ;
  135. $.each(modules, function(index, name) {
  136. var
  137. namespace = (module.moduleExists(name))
  138. ? $.fn[name].settings.namespace || false
  139. : true,
  140. $existingModules
  141. ;
  142. if(module.moduleExists(name)) {
  143. module.verbose('Changing default setting', setting, value, name);
  144. $.fn[name].settings[setting] = value;
  145. if(modifyExisting && namespace) {
  146. $existingModules = $(':data(module-' + namespace + ')');
  147. if($existingModules.length > 0) {
  148. module.verbose('Modifying existing settings', $existingModules);
  149. $existingModules[name]('setting', setting, value);
  150. }
  151. }
  152. }
  153. });
  154. },
  155. settings: function(newSettings, modules, modifyExisting) {
  156. modules = (typeof modules === 'string')
  157. ? [modules]
  158. : modules || settings.modules
  159. ;
  160. modifyExisting = (modifyExisting !== undefined)
  161. ? modifyExisting
  162. : true
  163. ;
  164. $.each(modules, function(index, name) {
  165. var
  166. $existingModules
  167. ;
  168. if(module.moduleExists(name)) {
  169. module.verbose('Changing default setting', newSettings, name);
  170. $.extend(true, $.fn[name].settings, newSettings);
  171. if(modifyExisting && namespace) {
  172. $existingModules = $(':data(module-' + namespace + ')');
  173. if($existingModules.length > 0) {
  174. module.verbose('Modifying existing settings', $existingModules);
  175. $existingModules[name]('setting', newSettings);
  176. }
  177. }
  178. }
  179. });
  180. }
  181. },
  182. enable: {
  183. console: function() {
  184. module.console(true);
  185. },
  186. debug: function(modules, modifyExisting) {
  187. modules = modules || settings.modules;
  188. module.debug('Enabling debug for modules', modules);
  189. module.change.setting('debug', true, modules, modifyExisting);
  190. },
  191. verbose: function(modules, modifyExisting) {
  192. modules = modules || settings.modules;
  193. module.debug('Enabling verbose debug for modules', modules);
  194. module.change.setting('verbose', true, modules, modifyExisting);
  195. }
  196. },
  197. disable: {
  198. console: function() {
  199. module.console(false);
  200. },
  201. debug: function(modules, modifyExisting) {
  202. modules = modules || settings.modules;
  203. module.debug('Disabling debug for modules', modules);
  204. module.change.setting('debug', false, modules, modifyExisting);
  205. },
  206. verbose: function(modules, modifyExisting) {
  207. modules = modules || settings.modules;
  208. module.debug('Disabling verbose debug for modules', modules);
  209. module.change.setting('verbose', false, modules, modifyExisting);
  210. }
  211. },
  212. console: function(enable) {
  213. if(enable) {
  214. if(instance.cache.console === undefined) {
  215. module.error(error.console);
  216. return;
  217. }
  218. module.debug('Restoring console function');
  219. window.console = instance.cache.console;
  220. }
  221. else {
  222. module.debug('Disabling console function');
  223. instance.cache.console = window.console;
  224. window.console = {
  225. clear : function(){},
  226. error : function(){},
  227. group : function(){},
  228. groupCollapsed : function(){},
  229. groupEnd : function(){},
  230. info : function(){},
  231. log : function(){},
  232. markTimeline : function(){},
  233. warn : function(){}
  234. };
  235. }
  236. },
  237. destroy: function() {
  238. module.verbose('Destroying previous site for', $module);
  239. $module
  240. .removeData(moduleNamespace)
  241. ;
  242. },
  243. cache: {},
  244. setting: function(name, value) {
  245. if( $.isPlainObject(name) ) {
  246. $.extend(true, settings, name);
  247. }
  248. else if(value !== undefined) {
  249. settings[name] = value;
  250. }
  251. else {
  252. return settings[name];
  253. }
  254. },
  255. internal: function(name, value) {
  256. if( $.isPlainObject(name) ) {
  257. $.extend(true, module, name);
  258. }
  259. else if(value !== undefined) {
  260. module[name] = value;
  261. }
  262. else {
  263. return module[name];
  264. }
  265. },
  266. debug: function() {
  267. if(settings.debug) {
  268. if(settings.performance) {
  269. module.performance.log(arguments);
  270. }
  271. else {
  272. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  273. module.debug.apply(console, arguments);
  274. }
  275. }
  276. },
  277. verbose: function() {
  278. if(settings.verbose && settings.debug) {
  279. if(settings.performance) {
  280. module.performance.log(arguments);
  281. }
  282. else {
  283. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  284. module.verbose.apply(console, arguments);
  285. }
  286. }
  287. },
  288. error: function() {
  289. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  290. module.error.apply(console, arguments);
  291. },
  292. performance: {
  293. log: function(message) {
  294. var
  295. currentTime,
  296. executionTime,
  297. previousTime
  298. ;
  299. if(settings.performance) {
  300. currentTime = new Date().getTime();
  301. previousTime = time || currentTime;
  302. executionTime = currentTime - previousTime;
  303. time = currentTime;
  304. performance.push({
  305. 'Element' : element,
  306. 'Name' : message[0],
  307. 'Arguments' : [].slice.call(message, 1) || '',
  308. 'Execution Time' : executionTime
  309. });
  310. }
  311. clearTimeout(module.performance.timer);
  312. module.performance.timer = setTimeout(module.performance.display, 500);
  313. },
  314. display: function() {
  315. var
  316. title = settings.name + ':',
  317. totalTime = 0
  318. ;
  319. time = false;
  320. clearTimeout(module.performance.timer);
  321. $.each(performance, function(index, data) {
  322. totalTime += data['Execution Time'];
  323. });
  324. title += ' ' + totalTime + 'ms';
  325. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  326. console.groupCollapsed(title);
  327. if(console.table) {
  328. console.table(performance);
  329. }
  330. else {
  331. $.each(performance, function(index, data) {
  332. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  333. });
  334. }
  335. console.groupEnd();
  336. }
  337. performance = [];
  338. }
  339. },
  340. invoke: function(query, passedArguments, context) {
  341. var
  342. object = instance,
  343. maxDepth,
  344. found,
  345. response
  346. ;
  347. passedArguments = passedArguments || queryArguments;
  348. context = element || context;
  349. if(typeof query == 'string' && object !== undefined) {
  350. query = query.split(/[\. ]/);
  351. maxDepth = query.length - 1;
  352. $.each(query, function(depth, value) {
  353. var camelCaseValue = (depth != maxDepth)
  354. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  355. : query
  356. ;
  357. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  358. object = object[camelCaseValue];
  359. }
  360. else if( object[camelCaseValue] !== undefined ) {
  361. found = object[camelCaseValue];
  362. return false;
  363. }
  364. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  365. object = object[value];
  366. }
  367. else if( object[value] !== undefined ) {
  368. found = object[value];
  369. return false;
  370. }
  371. else {
  372. module.error(error.method, query);
  373. return false;
  374. }
  375. });
  376. }
  377. if ( $.isFunction( found ) ) {
  378. response = found.apply(context, passedArguments);
  379. }
  380. else if(found !== undefined) {
  381. response = found;
  382. }
  383. if($.isArray(returnedValue)) {
  384. returnedValue.push(response);
  385. }
  386. else if(returnedValue !== undefined) {
  387. returnedValue = [returnedValue, response];
  388. }
  389. else if(response !== undefined) {
  390. returnedValue = response;
  391. }
  392. return found;
  393. }
  394. };
  395. if(methodInvoked) {
  396. if(instance === undefined) {
  397. module.initialize();
  398. }
  399. module.invoke(query);
  400. }
  401. else {
  402. if(instance !== undefined) {
  403. module.destroy();
  404. }
  405. module.initialize();
  406. }
  407. return (returnedValue !== undefined)
  408. ? returnedValue
  409. : this
  410. ;
  411. };
  412. $.site.settings = {
  413. name : 'Site',
  414. namespace : 'site',
  415. error : {
  416. console : 'Console cannot be restored, most likely it was overwritten outside of module',
  417. method : 'The method you called is not defined.'
  418. },
  419. debug : false,
  420. verbose : false,
  421. performance : true,
  422. modules: [
  423. 'accordion',
  424. 'api',
  425. 'checkbox',
  426. 'dimmer',
  427. 'dropdown',
  428. 'embed',
  429. 'form',
  430. 'modal',
  431. 'nag',
  432. 'popup',
  433. 'rating',
  434. 'shape',
  435. 'sidebar',
  436. 'state',
  437. 'sticky',
  438. 'tab',
  439. 'transition',
  440. 'visit',
  441. 'visibility'
  442. ],
  443. siteNamespace : 'site',
  444. namespaceStub : {
  445. cache : {},
  446. config : {},
  447. sections : {},
  448. section : {},
  449. utilities : {}
  450. }
  451. };
  452. // allows for selection of elements with data attributes
  453. $.extend($.expr[ ":" ], {
  454. data: ($.expr.createPseudo)
  455. ? $.expr.createPseudo(function(dataName) {
  456. return function(elem) {
  457. return !!$.data(elem, dataName);
  458. };
  459. })
  460. : function(elem, i, match) {
  461. // support: jQuery < 1.8
  462. return !!$.data(elem, match[ 3 ]);
  463. }
  464. });
  465. })( jQuery, window, document );
  466. /*!
  467. * # Semantic UI 2.4.1 - Form Validation
  468. * http://github.com/semantic-org/semantic-ui/
  469. *
  470. *
  471. * Released under the MIT license
  472. * http://opensource.org/licenses/MIT
  473. *
  474. */
  475. ;(function ($, window, document, undefined) {
  476. 'use strict';
  477. window = (typeof window != 'undefined' && window.Math == Math)
  478. ? window
  479. : (typeof self != 'undefined' && self.Math == Math)
  480. ? self
  481. : Function('return this')()
  482. ;
  483. $.fn.form = function(parameters) {
  484. var
  485. $allModules = $(this),
  486. moduleSelector = $allModules.selector || '',
  487. time = new Date().getTime(),
  488. performance = [],
  489. query = arguments[0],
  490. legacyParameters = arguments[1],
  491. methodInvoked = (typeof query == 'string'),
  492. queryArguments = [].slice.call(arguments, 1),
  493. returnedValue
  494. ;
  495. $allModules
  496. .each(function() {
  497. var
  498. $module = $(this),
  499. element = this,
  500. formErrors = [],
  501. keyHeldDown = false,
  502. // set at run-time
  503. $field,
  504. $group,
  505. $message,
  506. $prompt,
  507. $submit,
  508. $clear,
  509. $reset,
  510. settings,
  511. validation,
  512. metadata,
  513. selector,
  514. className,
  515. regExp,
  516. error,
  517. namespace,
  518. moduleNamespace,
  519. eventNamespace,
  520. instance,
  521. module
  522. ;
  523. module = {
  524. initialize: function() {
  525. // settings grabbed at run time
  526. module.get.settings();
  527. if(methodInvoked) {
  528. if(instance === undefined) {
  529. module.instantiate();
  530. }
  531. module.invoke(query);
  532. }
  533. else {
  534. if(instance !== undefined) {
  535. instance.invoke('destroy');
  536. }
  537. module.verbose('Initializing form validation', $module, settings);
  538. module.bindEvents();
  539. module.set.defaults();
  540. module.instantiate();
  541. }
  542. },
  543. instantiate: function() {
  544. module.verbose('Storing instance of module', module);
  545. instance = module;
  546. $module
  547. .data(moduleNamespace, module)
  548. ;
  549. },
  550. destroy: function() {
  551. module.verbose('Destroying previous module', instance);
  552. module.removeEvents();
  553. $module
  554. .removeData(moduleNamespace)
  555. ;
  556. },
  557. refresh: function() {
  558. module.verbose('Refreshing selector cache');
  559. $field = $module.find(selector.field);
  560. $group = $module.find(selector.group);
  561. $message = $module.find(selector.message);
  562. $prompt = $module.find(selector.prompt);
  563. $submit = $module.find(selector.submit);
  564. $clear = $module.find(selector.clear);
  565. $reset = $module.find(selector.reset);
  566. },
  567. submit: function() {
  568. module.verbose('Submitting form', $module);
  569. $module
  570. .submit()
  571. ;
  572. },
  573. attachEvents: function(selector, action) {
  574. action = action || 'submit';
  575. $(selector)
  576. .on('click' + eventNamespace, function(event) {
  577. module[action]();
  578. event.preventDefault();
  579. })
  580. ;
  581. },
  582. bindEvents: function() {
  583. module.verbose('Attaching form events');
  584. $module
  585. .on('submit' + eventNamespace, module.validate.form)
  586. .on('blur' + eventNamespace, selector.field, module.event.field.blur)
  587. .on('click' + eventNamespace, selector.submit, module.submit)
  588. .on('click' + eventNamespace, selector.reset, module.reset)
  589. .on('click' + eventNamespace, selector.clear, module.clear)
  590. ;
  591. if(settings.keyboardShortcuts) {
  592. $module
  593. .on('keydown' + eventNamespace, selector.field, module.event.field.keydown)
  594. ;
  595. }
  596. $field
  597. .each(function() {
  598. var
  599. $input = $(this),
  600. type = $input.prop('type'),
  601. inputEvent = module.get.changeEvent(type, $input)
  602. ;
  603. $(this)
  604. .on(inputEvent + eventNamespace, module.event.field.change)
  605. ;
  606. })
  607. ;
  608. },
  609. clear: function() {
  610. $field
  611. .each(function () {
  612. var
  613. $field = $(this),
  614. $element = $field.parent(),
  615. $fieldGroup = $field.closest($group),
  616. $prompt = $fieldGroup.find(selector.prompt),
  617. defaultValue = $field.data(metadata.defaultValue) || '',
  618. isCheckbox = $element.is(selector.uiCheckbox),
  619. isDropdown = $element.is(selector.uiDropdown),
  620. isErrored = $fieldGroup.hasClass(className.error)
  621. ;
  622. if(isErrored) {
  623. module.verbose('Resetting error on field', $fieldGroup);
  624. $fieldGroup.removeClass(className.error);
  625. $prompt.remove();
  626. }
  627. if(isDropdown) {
  628. module.verbose('Resetting dropdown value', $element, defaultValue);
  629. $element.dropdown('clear');
  630. }
  631. else if(isCheckbox) {
  632. $field.prop('checked', false);
  633. }
  634. else {
  635. module.verbose('Resetting field value', $field, defaultValue);
  636. $field.val('');
  637. }
  638. })
  639. ;
  640. },
  641. reset: function() {
  642. $field
  643. .each(function () {
  644. var
  645. $field = $(this),
  646. $element = $field.parent(),
  647. $fieldGroup = $field.closest($group),
  648. $prompt = $fieldGroup.find(selector.prompt),
  649. defaultValue = $field.data(metadata.defaultValue),
  650. isCheckbox = $element.is(selector.uiCheckbox),
  651. isDropdown = $element.is(selector.uiDropdown),
  652. isErrored = $fieldGroup.hasClass(className.error)
  653. ;
  654. if(defaultValue === undefined) {
  655. return;
  656. }
  657. if(isErrored) {
  658. module.verbose('Resetting error on field', $fieldGroup);
  659. $fieldGroup.removeClass(className.error);
  660. $prompt.remove();
  661. }
  662. if(isDropdown) {
  663. module.verbose('Resetting dropdown value', $element, defaultValue);
  664. $element.dropdown('restore defaults');
  665. }
  666. else if(isCheckbox) {
  667. module.verbose('Resetting checkbox value', $element, defaultValue);
  668. $field.prop('checked', defaultValue);
  669. }
  670. else {
  671. module.verbose('Resetting field value', $field, defaultValue);
  672. $field.val(defaultValue);
  673. }
  674. })
  675. ;
  676. },
  677. determine: {
  678. isValid: function() {
  679. var
  680. allValid = true
  681. ;
  682. $.each(validation, function(fieldName, field) {
  683. if( !( module.validate.field(field, fieldName, true) ) ) {
  684. allValid = false;
  685. }
  686. });
  687. return allValid;
  688. }
  689. },
  690. is: {
  691. bracketedRule: function(rule) {
  692. return (rule.type && rule.type.match(settings.regExp.bracket));
  693. },
  694. shorthandFields: function(fields) {
  695. var
  696. fieldKeys = Object.keys(fields),
  697. firstRule = fields[fieldKeys[0]]
  698. ;
  699. return module.is.shorthandRules(firstRule);
  700. },
  701. // duck type rule test
  702. shorthandRules: function(rules) {
  703. return (typeof rules == 'string' || $.isArray(rules));
  704. },
  705. empty: function($field) {
  706. if(!$field || $field.length === 0) {
  707. return true;
  708. }
  709. else if($field.is('input[type="checkbox"]')) {
  710. return !$field.is(':checked');
  711. }
  712. else {
  713. return module.is.blank($field);
  714. }
  715. },
  716. blank: function($field) {
  717. return $.trim($field.val()) === '';
  718. },
  719. valid: function(field) {
  720. var
  721. allValid = true
  722. ;
  723. if(field) {
  724. module.verbose('Checking if field is valid', field);
  725. return module.validate.field(validation[field], field, false);
  726. }
  727. else {
  728. module.verbose('Checking if form is valid');
  729. $.each(validation, function(fieldName, field) {
  730. if( !module.is.valid(fieldName) ) {
  731. allValid = false;
  732. }
  733. });
  734. return allValid;
  735. }
  736. }
  737. },
  738. removeEvents: function() {
  739. $module
  740. .off(eventNamespace)
  741. ;
  742. $field
  743. .off(eventNamespace)
  744. ;
  745. $submit
  746. .off(eventNamespace)
  747. ;
  748. $field
  749. .off(eventNamespace)
  750. ;
  751. },
  752. event: {
  753. field: {
  754. keydown: function(event) {
  755. var
  756. $field = $(this),
  757. key = event.which,
  758. isInput = $field.is(selector.input),
  759. isCheckbox = $field.is(selector.checkbox),
  760. isInDropdown = ($field.closest(selector.uiDropdown).length > 0),
  761. keyCode = {
  762. enter : 13,
  763. escape : 27
  764. }
  765. ;
  766. if( key == keyCode.escape) {
  767. module.verbose('Escape key pressed blurring field');
  768. $field
  769. .blur()
  770. ;
  771. }
  772. if(!event.ctrlKey && key == keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
  773. if(!keyHeldDown) {
  774. $field
  775. .one('keyup' + eventNamespace, module.event.field.keyup)
  776. ;
  777. module.submit();
  778. module.debug('Enter pressed on input submitting form');
  779. }
  780. keyHeldDown = true;
  781. }
  782. },
  783. keyup: function() {
  784. keyHeldDown = false;
  785. },
  786. blur: function(event) {
  787. var
  788. $field = $(this),
  789. $fieldGroup = $field.closest($group),
  790. validationRules = module.get.validation($field)
  791. ;
  792. if( $fieldGroup.hasClass(className.error) ) {
  793. module.debug('Revalidating field', $field, validationRules);
  794. if(validationRules) {
  795. module.validate.field( validationRules );
  796. }
  797. }
  798. else if(settings.on == 'blur') {
  799. if(validationRules) {
  800. module.validate.field( validationRules );
  801. }
  802. }
  803. },
  804. change: function(event) {
  805. var
  806. $field = $(this),
  807. $fieldGroup = $field.closest($group),
  808. validationRules = module.get.validation($field)
  809. ;
  810. if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
  811. clearTimeout(module.timer);
  812. module.timer = setTimeout(function() {
  813. module.debug('Revalidating field', $field, module.get.validation($field));
  814. module.validate.field( validationRules );
  815. }, settings.delay);
  816. }
  817. }
  818. }
  819. },
  820. get: {
  821. ancillaryValue: function(rule) {
  822. if(!rule.type || (!rule.value && !module.is.bracketedRule(rule))) {
  823. return false;
  824. }
  825. return (rule.value !== undefined)
  826. ? rule.value
  827. : rule.type.match(settings.regExp.bracket)[1] + ''
  828. ;
  829. },
  830. ruleName: function(rule) {
  831. if( module.is.bracketedRule(rule) ) {
  832. return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
  833. }
  834. return rule.type;
  835. },
  836. changeEvent: function(type, $input) {
  837. if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
  838. return 'change';
  839. }
  840. else {
  841. return module.get.inputEvent();
  842. }
  843. },
  844. inputEvent: function() {
  845. return (document.createElement('input').oninput !== undefined)
  846. ? 'input'
  847. : (document.createElement('input').onpropertychange !== undefined)
  848. ? 'propertychange'
  849. : 'keyup'
  850. ;
  851. },
  852. fieldsFromShorthand: function(fields) {
  853. var
  854. fullFields = {}
  855. ;
  856. $.each(fields, function(name, rules) {
  857. if(typeof rules == 'string') {
  858. rules = [rules];
  859. }
  860. fullFields[name] = {
  861. rules: []
  862. };
  863. $.each(rules, function(index, rule) {
  864. fullFields[name].rules.push({ type: rule });
  865. });
  866. });
  867. return fullFields;
  868. },
  869. prompt: function(rule, field) {
  870. var
  871. ruleName = module.get.ruleName(rule),
  872. ancillary = module.get.ancillaryValue(rule),
  873. $field = module.get.field(field.identifier),
  874. value = $field.val(),
  875. prompt = $.isFunction(rule.prompt)
  876. ? rule.prompt(value)
  877. : rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
  878. requiresValue = (prompt.search('{value}') !== -1),
  879. requiresName = (prompt.search('{name}') !== -1),
  880. $label,
  881. name
  882. ;
  883. if(requiresValue) {
  884. prompt = prompt.replace('{value}', $field.val());
  885. }
  886. if(requiresName) {
  887. $label = $field.closest(selector.group).find('label').eq(0);
  888. name = ($label.length == 1)
  889. ? $label.text()
  890. : $field.prop('placeholder') || settings.text.unspecifiedField
  891. ;
  892. prompt = prompt.replace('{name}', name);
  893. }
  894. prompt = prompt.replace('{identifier}', field.identifier);
  895. prompt = prompt.replace('{ruleValue}', ancillary);
  896. if(!rule.prompt) {
  897. module.verbose('Using default validation prompt for type', prompt, ruleName);
  898. }
  899. return prompt;
  900. },
  901. settings: function() {
  902. if($.isPlainObject(parameters)) {
  903. var
  904. keys = Object.keys(parameters),
  905. isLegacySettings = (keys.length > 0)
  906. ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
  907. : false,
  908. ruleKeys
  909. ;
  910. if(isLegacySettings) {
  911. // 1.x (ducktyped)
  912. settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
  913. validation = $.extend({}, $.fn.form.settings.defaults, parameters);
  914. module.error(settings.error.oldSyntax, element);
  915. module.verbose('Extending settings from legacy parameters', validation, settings);
  916. }
  917. else {
  918. // 2.x
  919. if(parameters.fields && module.is.shorthandFields(parameters.fields)) {
  920. parameters.fields = module.get.fieldsFromShorthand(parameters.fields);
  921. }
  922. settings = $.extend(true, {}, $.fn.form.settings, parameters);
  923. validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
  924. module.verbose('Extending settings', validation, settings);
  925. }
  926. }
  927. else {
  928. settings = $.fn.form.settings;
  929. validation = $.fn.form.settings.defaults;
  930. module.verbose('Using default form validation', validation, settings);
  931. }
  932. // shorthand
  933. namespace = settings.namespace;
  934. metadata = settings.metadata;
  935. selector = settings.selector;
  936. className = settings.className;
  937. regExp = settings.regExp;
  938. error = settings.error;
  939. moduleNamespace = 'module-' + namespace;
  940. eventNamespace = '.' + namespace;
  941. // grab instance
  942. instance = $module.data(moduleNamespace);
  943. // refresh selector cache
  944. module.refresh();
  945. },
  946. field: function(identifier) {
  947. module.verbose('Finding field with identifier', identifier);
  948. identifier = module.escape.string(identifier);
  949. if($field.filter('#' + identifier).length > 0 ) {
  950. return $field.filter('#' + identifier);
  951. }
  952. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  953. return $field.filter('[name="' + identifier +'"]');
  954. }
  955. else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) {
  956. return $field.filter('[name="' + identifier +'[]"]');
  957. }
  958. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  959. return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]');
  960. }
  961. return $('<input/>');
  962. },
  963. fields: function(fields) {
  964. var
  965. $fields = $()
  966. ;
  967. $.each(fields, function(index, name) {
  968. $fields = $fields.add( module.get.field(name) );
  969. });
  970. return $fields;
  971. },
  972. validation: function($field) {
  973. var
  974. fieldValidation,
  975. identifier
  976. ;
  977. if(!validation) {
  978. return false;
  979. }
  980. $.each(validation, function(fieldName, field) {
  981. identifier = field.identifier || fieldName;
  982. if( module.get.field(identifier)[0] == $field[0] ) {
  983. field.identifier = identifier;
  984. fieldValidation = field;
  985. }
  986. });
  987. return fieldValidation || false;
  988. },
  989. value: function (field) {
  990. var
  991. fields = [],
  992. results
  993. ;
  994. fields.push(field);
  995. results = module.get.values.call(element, fields);
  996. return results[field];
  997. },
  998. values: function (fields) {
  999. var
  1000. $fields = $.isArray(fields)
  1001. ? module.get.fields(fields)
  1002. : $field,
  1003. values = {}
  1004. ;
  1005. $fields.each(function(index, field) {
  1006. var
  1007. $field = $(field),
  1008. type = $field.prop('type'),
  1009. name = $field.prop('name'),
  1010. value = $field.val(),
  1011. isCheckbox = $field.is(selector.checkbox),
  1012. isRadio = $field.is(selector.radio),
  1013. isMultiple = (name.indexOf('[]') !== -1),
  1014. isChecked = (isCheckbox)
  1015. ? $field.is(':checked')
  1016. : false
  1017. ;
  1018. if(name) {
  1019. if(isMultiple) {
  1020. name = name.replace('[]', '');
  1021. if(!values[name]) {
  1022. values[name] = [];
  1023. }
  1024. if(isCheckbox) {
  1025. if(isChecked) {
  1026. values[name].push(value || true);
  1027. }
  1028. else {
  1029. values[name].push(false);
  1030. }
  1031. }
  1032. else {
  1033. values[name].push(value);
  1034. }
  1035. }
  1036. else {
  1037. if(isRadio) {
  1038. if(values[name] === undefined || values[name] == false) {
  1039. values[name] = (isChecked)
  1040. ? value || true
  1041. : false
  1042. ;
  1043. }
  1044. }
  1045. else if(isCheckbox) {
  1046. if(isChecked) {
  1047. values[name] = value || true;
  1048. }
  1049. else {
  1050. values[name] = false;
  1051. }
  1052. }
  1053. else {
  1054. values[name] = value;
  1055. }
  1056. }
  1057. }
  1058. });
  1059. return values;
  1060. }
  1061. },
  1062. has: {
  1063. field: function(identifier) {
  1064. module.verbose('Checking for existence of a field with identifier', identifier);
  1065. identifier = module.escape.string(identifier);
  1066. if(typeof identifier !== 'string') {
  1067. module.error(error.identifier, identifier);
  1068. }
  1069. if($field.filter('#' + identifier).length > 0 ) {
  1070. return true;
  1071. }
  1072. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  1073. return true;
  1074. }
  1075. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  1076. return true;
  1077. }
  1078. return false;
  1079. }
  1080. },
  1081. escape: {
  1082. string: function(text) {
  1083. text = String(text);
  1084. return text.replace(regExp.escape, '\\$&');
  1085. }
  1086. },
  1087. add: {
  1088. // alias
  1089. rule: function(name, rules) {
  1090. module.add.field(name, rules);
  1091. },
  1092. field: function(name, rules) {
  1093. var
  1094. newValidation = {}
  1095. ;
  1096. if(module.is.shorthandRules(rules)) {
  1097. rules = $.isArray(rules)
  1098. ? rules
  1099. : [rules]
  1100. ;
  1101. newValidation[name] = {
  1102. rules: []
  1103. };
  1104. $.each(rules, function(index, rule) {
  1105. newValidation[name].rules.push({ type: rule });
  1106. });
  1107. }
  1108. else {
  1109. newValidation[name] = rules;
  1110. }
  1111. validation = $.extend({}, validation, newValidation);
  1112. module.debug('Adding rules', newValidation, validation);
  1113. },
  1114. fields: function(fields) {
  1115. var
  1116. newValidation
  1117. ;
  1118. if(fields && module.is.shorthandFields(fields)) {
  1119. newValidation = module.get.fieldsFromShorthand(fields);
  1120. }
  1121. else {
  1122. newValidation = fields;
  1123. }
  1124. validation = $.extend({}, validation, newValidation);
  1125. },
  1126. prompt: function(identifier, errors) {
  1127. var
  1128. $field = module.get.field(identifier),
  1129. $fieldGroup = $field.closest($group),
  1130. $prompt = $fieldGroup.children(selector.prompt),
  1131. promptExists = ($prompt.length !== 0)
  1132. ;
  1133. errors = (typeof errors == 'string')
  1134. ? [errors]
  1135. : errors
  1136. ;
  1137. module.verbose('Adding field error state', identifier);
  1138. $fieldGroup
  1139. .addClass(className.error)
  1140. ;
  1141. if(settings.inline) {
  1142. if(!promptExists) {
  1143. $prompt = settings.templates.prompt(errors);
  1144. $prompt
  1145. .appendTo($fieldGroup)
  1146. ;
  1147. }
  1148. $prompt
  1149. .html(errors[0])
  1150. ;
  1151. if(!promptExists) {
  1152. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  1153. module.verbose('Displaying error with css transition', settings.transition);
  1154. $prompt.transition(settings.transition + ' in', settings.duration);
  1155. }
  1156. else {
  1157. module.verbose('Displaying error with fallback javascript animation');
  1158. $prompt
  1159. .fadeIn(settings.duration)
  1160. ;
  1161. }
  1162. }
  1163. else {
  1164. module.verbose('Inline errors are disabled, no inline error added', identifier);
  1165. }
  1166. }
  1167. },
  1168. errors: function(errors) {
  1169. module.debug('Adding form error messages', errors);
  1170. module.set.error();
  1171. $message
  1172. .html( settings.templates.error(errors) )
  1173. ;
  1174. }
  1175. },
  1176. remove: {
  1177. rule: function(field, rule) {
  1178. var
  1179. rules = $.isArray(rule)
  1180. ? rule
  1181. : [rule]
  1182. ;
  1183. if(rule == undefined) {
  1184. module.debug('Removed all rules');
  1185. validation[field].rules = [];
  1186. return;
  1187. }
  1188. if(validation[field] == undefined || !$.isArray(validation[field].rules)) {
  1189. return;
  1190. }
  1191. $.each(validation[field].rules, function(index, rule) {
  1192. if(rules.indexOf(rule.type) !== -1) {
  1193. module.debug('Removed rule', rule.type);
  1194. validation[field].rules.splice(index, 1);
  1195. }
  1196. });
  1197. },
  1198. field: function(field) {
  1199. var
  1200. fields = $.isArray(field)
  1201. ? field
  1202. : [field]
  1203. ;
  1204. $.each(fields, function(index, field) {
  1205. module.remove.rule(field);
  1206. });
  1207. },
  1208. // alias
  1209. rules: function(field, rules) {
  1210. if($.isArray(field)) {
  1211. $.each(fields, function(index, field) {
  1212. module.remove.rule(field, rules);
  1213. });
  1214. }
  1215. else {
  1216. module.remove.rule(field, rules);
  1217. }
  1218. },
  1219. fields: function(fields) {
  1220. module.remove.field(fields);
  1221. },
  1222. prompt: function(identifier) {
  1223. var
  1224. $field = module.get.field(identifier),
  1225. $fieldGroup = $field.closest($group),
  1226. $prompt = $fieldGroup.children(selector.prompt)
  1227. ;
  1228. $fieldGroup
  1229. .removeClass(className.error)
  1230. ;
  1231. if(settings.inline && $prompt.is(':visible')) {
  1232. module.verbose('Removing prompt for field', identifier);
  1233. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  1234. $prompt.transition(settings.transition + ' out', settings.duration, function() {
  1235. $prompt.remove();
  1236. });
  1237. }
  1238. else {
  1239. $prompt
  1240. .fadeOut(settings.duration, function(){
  1241. $prompt.remove();
  1242. })
  1243. ;
  1244. }
  1245. }
  1246. }
  1247. },
  1248. set: {
  1249. success: function() {
  1250. $module
  1251. .removeClass(className.error)
  1252. .addClass(className.success)
  1253. ;
  1254. },
  1255. defaults: function () {
  1256. $field
  1257. .each(function () {
  1258. var
  1259. $field = $(this),
  1260. isCheckbox = ($field.filter(selector.checkbox).length > 0),
  1261. value = (isCheckbox)
  1262. ? $field.is(':checked')
  1263. : $field.val()
  1264. ;
  1265. $field.data(metadata.defaultValue, value);
  1266. })
  1267. ;
  1268. },
  1269. error: function() {
  1270. $module
  1271. .removeClass(className.success)
  1272. .addClass(className.error)
  1273. ;
  1274. },
  1275. value: function (field, value) {
  1276. var
  1277. fields = {}
  1278. ;
  1279. fields[field] = value;
  1280. return module.set.values.call(element, fields);
  1281. },
  1282. values: function (fields) {
  1283. if($.isEmptyObject(fields)) {
  1284. return;
  1285. }
  1286. $.each(fields, function(key, value) {
  1287. var
  1288. $field = module.get.field(key),
  1289. $element = $field.parent(),
  1290. isMultiple = $.isArray(value),
  1291. isCheckbox = $element.is(selector.uiCheckbox),
  1292. isDropdown = $element.is(selector.uiDropdown),
  1293. isRadio = ($field.is(selector.radio) && isCheckbox),
  1294. fieldExists = ($field.length > 0),
  1295. $multipleField
  1296. ;
  1297. if(fieldExists) {
  1298. if(isMultiple && isCheckbox) {
  1299. module.verbose('Selecting multiple', value, $field);
  1300. $element.checkbox('uncheck');
  1301. $.each(value, function(index, value) {
  1302. $multipleField = $field.filter('[value="' + value + '"]');
  1303. $element = $multipleField.parent();
  1304. if($multipleField.length > 0) {
  1305. $element.checkbox('check');
  1306. }
  1307. });
  1308. }
  1309. else if(isRadio) {
  1310. module.verbose('Selecting radio value', value, $field);
  1311. $field.filter('[value="' + value + '"]')
  1312. .parent(selector.uiCheckbox)
  1313. .checkbox('check')
  1314. ;
  1315. }
  1316. else if(isCheckbox) {
  1317. module.verbose('Setting checkbox value', value, $element);
  1318. if(value === true) {
  1319. $element.checkbox('check');
  1320. }
  1321. else {
  1322. $element.checkbox('uncheck');
  1323. }
  1324. }
  1325. else if(isDropdown) {
  1326. module.verbose('Setting dropdown value', value, $element);
  1327. $element.dropdown('set selected', value);
  1328. }
  1329. else {
  1330. module.verbose('Setting field value', value, $field);
  1331. $field.val(value);
  1332. }
  1333. }
  1334. });
  1335. }
  1336. },
  1337. validate: {
  1338. form: function(event, ignoreCallbacks) {
  1339. var
  1340. values = module.get.values(),
  1341. apiRequest
  1342. ;
  1343. // input keydown event will fire submit repeatedly by browser default
  1344. if(keyHeldDown) {
  1345. return false;
  1346. }
  1347. // reset errors
  1348. formErrors = [];
  1349. if( module.determine.isValid() ) {
  1350. module.debug('Form has no validation errors, submitting');
  1351. module.set.success();
  1352. if(ignoreCallbacks !== true) {
  1353. return settings.onSuccess.call(element, event, values);
  1354. }
  1355. }
  1356. else {
  1357. module.debug('Form has errors');
  1358. module.set.error();
  1359. if(!settings.inline) {
  1360. module.add.errors(formErrors);
  1361. }
  1362. // prevent ajax submit
  1363. if($module.data('moduleApi') !== undefined) {
  1364. event.stopImmediatePropagation();
  1365. }
  1366. if(ignoreCallbacks !== true) {
  1367. return settings.onFailure.call(element, formErrors, values);
  1368. }
  1369. }
  1370. },
  1371. // takes a validation object and returns whether field passes validation
  1372. field: function(field, fieldName, showErrors) {
  1373. showErrors = (showErrors !== undefined)
  1374. ? showErrors
  1375. : true
  1376. ;
  1377. if(typeof field == 'string') {
  1378. module.verbose('Validating field', field);
  1379. fieldName = field;
  1380. field = validation[field];
  1381. }
  1382. var
  1383. identifier = field.identifier || fieldName,
  1384. $field = module.get.field(identifier),
  1385. $dependsField = (field.depends)
  1386. ? module.get.field(field.depends)
  1387. : false,
  1388. fieldValid = true,
  1389. fieldErrors = []
  1390. ;
  1391. if(!field.identifier) {
  1392. module.debug('Using field name as identifier', identifier);
  1393. field.identifier = identifier;
  1394. }
  1395. if($field.prop('disabled')) {
  1396. module.debug('Field is disabled. Skipping', identifier);
  1397. fieldValid = true;
  1398. }
  1399. else if(field.optional && module.is.blank($field)){
  1400. module.debug('Field is optional and blank. Skipping', identifier);
  1401. fieldValid = true;
  1402. }
  1403. else if(field.depends && module.is.empty($dependsField)) {
  1404. module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
  1405. fieldValid = true;
  1406. }
  1407. else if(field.rules !== undefined) {
  1408. $.each(field.rules, function(index, rule) {
  1409. if( module.has.field(identifier) && !( module.validate.rule(field, rule) ) ) {
  1410. module.debug('Field is invalid', identifier, rule.type);
  1411. fieldErrors.push(module.get.prompt(rule, field));
  1412. fieldValid = false;
  1413. }
  1414. });
  1415. }
  1416. if(fieldValid) {
  1417. if(showErrors) {
  1418. module.remove.prompt(identifier, fieldErrors);
  1419. settings.onValid.call($field);
  1420. }
  1421. }
  1422. else {
  1423. if(showErrors) {
  1424. formErrors = formErrors.concat(fieldErrors);
  1425. module.add.prompt(identifier, fieldErrors);
  1426. settings.onInvalid.call($field, fieldErrors);
  1427. }
  1428. return false;
  1429. }
  1430. return true;
  1431. },
  1432. // takes validation rule and returns whether field passes rule
  1433. rule: function(field, rule) {
  1434. var
  1435. $field = module.get.field(field.identifier),
  1436. type = rule.type,
  1437. value = $field.val(),
  1438. isValid = true,
  1439. ancillary = module.get.ancillaryValue(rule),
  1440. ruleName = module.get.ruleName(rule),
  1441. ruleFunction = settings.rules[ruleName]
  1442. ;
  1443. if( !$.isFunction(ruleFunction) ) {
  1444. module.error(error.noRule, ruleName);
  1445. return;
  1446. }
  1447. // cast to string avoiding encoding special values
  1448. value = (value === undefined || value === '' || value === null)
  1449. ? ''
  1450. : $.trim(value + '')
  1451. ;
  1452. return ruleFunction.call($field, value, ancillary);
  1453. }
  1454. },
  1455. setting: function(name, value) {
  1456. if( $.isPlainObject(name) ) {
  1457. $.extend(true, settings, name);
  1458. }
  1459. else if(value !== undefined) {
  1460. settings[name] = value;
  1461. }
  1462. else {
  1463. return settings[name];
  1464. }
  1465. },
  1466. internal: function(name, value) {
  1467. if( $.isPlainObject(name) ) {
  1468. $.extend(true, module, name);
  1469. }
  1470. else if(value !== undefined) {
  1471. module[name] = value;
  1472. }
  1473. else {
  1474. return module[name];
  1475. }
  1476. },
  1477. debug: function() {
  1478. if(!settings.silent && settings.debug) {
  1479. if(settings.performance) {
  1480. module.performance.log(arguments);
  1481. }
  1482. else {
  1483. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1484. module.debug.apply(console, arguments);
  1485. }
  1486. }
  1487. },
  1488. verbose: function() {
  1489. if(!settings.silent && settings.verbose && settings.debug) {
  1490. if(settings.performance) {
  1491. module.performance.log(arguments);
  1492. }
  1493. else {
  1494. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1495. module.verbose.apply(console, arguments);
  1496. }
  1497. }
  1498. },
  1499. error: function() {
  1500. if(!settings.silent) {
  1501. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  1502. module.error.apply(console, arguments);
  1503. }
  1504. },
  1505. performance: {
  1506. log: function(message) {
  1507. var
  1508. currentTime,
  1509. executionTime,
  1510. previousTime
  1511. ;
  1512. if(settings.performance) {
  1513. currentTime = new Date().getTime();
  1514. previousTime = time || currentTime;
  1515. executionTime = currentTime - previousTime;
  1516. time = currentTime;
  1517. performance.push({
  1518. 'Name' : message[0],
  1519. 'Arguments' : [].slice.call(message, 1) || '',
  1520. 'Element' : element,
  1521. 'Execution Time' : executionTime
  1522. });
  1523. }
  1524. clearTimeout(module.performance.timer);
  1525. module.performance.timer = setTimeout(module.performance.display, 500);
  1526. },
  1527. display: function() {
  1528. var
  1529. title = settings.name + ':',
  1530. totalTime = 0
  1531. ;
  1532. time = false;
  1533. clearTimeout(module.performance.timer);
  1534. $.each(performance, function(index, data) {
  1535. totalTime += data['Execution Time'];
  1536. });
  1537. title += ' ' + totalTime + 'ms';
  1538. if(moduleSelector) {
  1539. title += ' \'' + moduleSelector + '\'';
  1540. }
  1541. if($allModules.length > 1) {
  1542. title += ' ' + '(' + $allModules.length + ')';
  1543. }
  1544. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  1545. console.groupCollapsed(title);
  1546. if(console.table) {
  1547. console.table(performance);
  1548. }
  1549. else {
  1550. $.each(performance, function(index, data) {
  1551. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  1552. });
  1553. }
  1554. console.groupEnd();
  1555. }
  1556. performance = [];
  1557. }
  1558. },
  1559. invoke: function(query, passedArguments, context) {
  1560. var
  1561. object = instance,
  1562. maxDepth,
  1563. found,
  1564. response
  1565. ;
  1566. passedArguments = passedArguments || queryArguments;
  1567. context = element || context;
  1568. if(typeof query == 'string' && object !== undefined) {
  1569. query = query.split(/[\. ]/);
  1570. maxDepth = query.length - 1;
  1571. $.each(query, function(depth, value) {
  1572. var camelCaseValue = (depth != maxDepth)
  1573. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  1574. : query
  1575. ;
  1576. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  1577. object = object[camelCaseValue];
  1578. }
  1579. else if( object[camelCaseValue] !== undefined ) {
  1580. found = object[camelCaseValue];
  1581. return false;
  1582. }
  1583. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  1584. object = object[value];
  1585. }
  1586. else if( object[value] !== undefined ) {
  1587. found = object[value];
  1588. return false;
  1589. }
  1590. else {
  1591. return false;
  1592. }
  1593. });
  1594. }
  1595. if( $.isFunction( found ) ) {
  1596. response = found.apply(context, passedArguments);
  1597. }
  1598. else if(found !== undefined) {
  1599. response = found;
  1600. }
  1601. if($.isArray(returnedValue)) {
  1602. returnedValue.push(response);
  1603. }
  1604. else if(returnedValue !== undefined) {
  1605. returnedValue = [returnedValue, response];
  1606. }
  1607. else if(response !== undefined) {
  1608. returnedValue = response;
  1609. }
  1610. return found;
  1611. }
  1612. };
  1613. module.initialize();
  1614. })
  1615. ;
  1616. return (returnedValue !== undefined)
  1617. ? returnedValue
  1618. : this
  1619. ;
  1620. };
  1621. $.fn.form.settings = {
  1622. name : 'Form',
  1623. namespace : 'form',
  1624. debug : false,
  1625. verbose : false,
  1626. performance : true,
  1627. fields : false,
  1628. keyboardShortcuts : true,
  1629. on : 'submit',
  1630. inline : false,
  1631. delay : 200,
  1632. revalidate : true,
  1633. transition : 'scale',
  1634. duration : 200,
  1635. onValid : function() {},
  1636. onInvalid : function() {},
  1637. onSuccess : function() { return true; },
  1638. onFailure : function() { return false; },
  1639. metadata : {
  1640. defaultValue : 'default',
  1641. validate : 'validate'
  1642. },
  1643. regExp: {
  1644. htmlID : /^[a-zA-Z][\w:.-]*$/g,
  1645. bracket : /\[(.*)\]/i,
  1646. decimal : /^\d+\.?\d*$/,
  1647. email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
  1648. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  1649. flags : /^\/(.*)\/(.*)?/,
  1650. integer : /^\-?\d+$/,
  1651. number : /^\-?\d*(\.\d+)?$/,
  1652. url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
  1653. },
  1654. text: {
  1655. unspecifiedRule : 'Please enter a valid value',
  1656. unspecifiedField : 'This field'
  1657. },
  1658. prompt: {
  1659. empty : '{name} must have a value',
  1660. checked : '{name} must be checked',
  1661. email : '{name} must be a valid e-mail',
  1662. url : '{name} must be a valid url',
  1663. regExp : '{name} is not formatted correctly',
  1664. integer : '{name} must be an integer',
  1665. decimal : '{name} must be a decimal number',
  1666. number : '{name} must be set to a number',
  1667. is : '{name} must be "{ruleValue}"',
  1668. isExactly : '{name} must be exactly "{ruleValue}"',
  1669. not : '{name} cannot be set to "{ruleValue}"',
  1670. notExactly : '{name} cannot be set to exactly "{ruleValue}"',
  1671. contain : '{name} must contain "{ruleValue}"',
  1672. containExactly : '{name} must contain exactly "{ruleValue}"',
  1673. doesntContain : '{name} cannot contain "{ruleValue}"',
  1674. doesntContainExactly : '{name} cannot contain exactly "{ruleValue}"',
  1675. minLength : '{name} must be at least {ruleValue} characters',
  1676. length : '{name} must be at least {ruleValue} characters',
  1677. exactLength : '{name} must be exactly {ruleValue} characters',
  1678. maxLength : '{name} cannot be longer than {ruleValue} characters',
  1679. match : '{name} must match {ruleValue} field',
  1680. different : '{name} must have a different value than {ruleValue} field',
  1681. creditCard : '{name} must be a valid credit card number',
  1682. minCount : '{name} must have at least {ruleValue} choices',
  1683. exactCount : '{name} must have exactly {ruleValue} choices',
  1684. maxCount : '{name} must have {ruleValue} or less choices'
  1685. },
  1686. selector : {
  1687. checkbox : 'input[type="checkbox"], input[type="radio"]',
  1688. clear : '.clear',
  1689. field : 'input, textarea, select',
  1690. group : '.field',
  1691. input : 'input',
  1692. message : '.error.message',
  1693. prompt : '.prompt.label',
  1694. radio : 'input[type="radio"]',
  1695. reset : '.reset:not([type="reset"])',
  1696. submit : '.submit:not([type="submit"])',
  1697. uiCheckbox : '.ui.checkbox',
  1698. uiDropdown : '.ui.dropdown'
  1699. },
  1700. className : {
  1701. error : 'error',
  1702. label : 'ui prompt label',
  1703. pressed : 'down',
  1704. success : 'success'
  1705. },
  1706. error: {
  1707. identifier : 'You must specify a string identifier for each field',
  1708. method : 'The method you called is not defined.',
  1709. noRule : 'There is no rule matching the one you specified',
  1710. oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.'
  1711. },
  1712. templates: {
  1713. // template that produces error message
  1714. error: function(errors) {
  1715. var
  1716. html = '<ul class="list">'
  1717. ;
  1718. $.each(errors, function(index, value) {
  1719. html += '<li>' + value + '</li>';
  1720. });
  1721. html += '</ul>';
  1722. return $(html);
  1723. },
  1724. // template that produces label
  1725. prompt: function(errors) {
  1726. return $('<div/>')
  1727. .addClass('ui basic red pointing prompt label')
  1728. .html(errors[0])
  1729. ;
  1730. }
  1731. },
  1732. rules: {
  1733. // is not empty or blank string
  1734. empty: function(value) {
  1735. return !(value === undefined || '' === value || $.isArray(value) && value.length === 0);
  1736. },
  1737. // checkbox checked
  1738. checked: function() {
  1739. return ($(this).filter(':checked').length > 0);
  1740. },
  1741. // is most likely an email
  1742. email: function(value){
  1743. return $.fn.form.settings.regExp.email.test(value);
  1744. },
  1745. // value is most likely url
  1746. url: function(value) {
  1747. return $.fn.form.settings.regExp.url.test(value);
  1748. },
  1749. // matches specified regExp
  1750. regExp: function(value, regExp) {
  1751. if(regExp instanceof RegExp) {
  1752. return value.match(regExp);
  1753. }
  1754. var
  1755. regExpParts = regExp.match($.fn.form.settings.regExp.flags),
  1756. flags
  1757. ;
  1758. // regular expression specified as /baz/gi (flags)
  1759. if(regExpParts) {
  1760. regExp = (regExpParts.length >= 2)
  1761. ? regExpParts[1]
  1762. : regExp
  1763. ;
  1764. flags = (regExpParts.length >= 3)
  1765. ? regExpParts[2]
  1766. : ''
  1767. ;
  1768. }
  1769. return value.match( new RegExp(regExp, flags) );
  1770. },
  1771. // is valid integer or matches range
  1772. integer: function(value, range) {
  1773. var
  1774. intRegExp = $.fn.form.settings.regExp.integer,
  1775. min,
  1776. max,
  1777. parts
  1778. ;
  1779. if( !range || ['', '..'].indexOf(range) !== -1) {
  1780. // do nothing
  1781. }
  1782. else if(range.indexOf('..') == -1) {
  1783. if(intRegExp.test(range)) {
  1784. min = max = range - 0;
  1785. }
  1786. }
  1787. else {
  1788. parts = range.split('..', 2);
  1789. if(intRegExp.test(parts[0])) {
  1790. min = parts[0] - 0;
  1791. }
  1792. if(intRegExp.test(parts[1])) {
  1793. max = parts[1] - 0;
  1794. }
  1795. }
  1796. return (
  1797. intRegExp.test(value) &&
  1798. (min === undefined || value >= min) &&
  1799. (max === undefined || value <= max)
  1800. );
  1801. },
  1802. // is valid number (with decimal)
  1803. decimal: function(value) {
  1804. return $.fn.form.settings.regExp.decimal.test(value);
  1805. },
  1806. // is valid number
  1807. number: function(value) {
  1808. return $.fn.form.settings.regExp.number.test(value);
  1809. },
  1810. // is value (case insensitive)
  1811. is: function(value, text) {
  1812. text = (typeof text == 'string')
  1813. ? text.toLowerCase()
  1814. : text
  1815. ;
  1816. value = (typeof value == 'string')
  1817. ? value.toLowerCase()
  1818. : value
  1819. ;
  1820. return (value == text);
  1821. },
  1822. // is value
  1823. isExactly: function(value, text) {
  1824. return (value == text);
  1825. },
  1826. // value is not another value (case insensitive)
  1827. not: function(value, notValue) {
  1828. value = (typeof value == 'string')
  1829. ? value.toLowerCase()
  1830. : value
  1831. ;
  1832. notValue = (typeof notValue == 'string')
  1833. ? notValue.toLowerCase()
  1834. : notValue
  1835. ;
  1836. return (value != notValue);
  1837. },
  1838. // value is not another value (case sensitive)
  1839. notExactly: function(value, notValue) {
  1840. return (value != notValue);
  1841. },
  1842. // value contains text (insensitive)
  1843. contains: function(value, text) {
  1844. // escape regex characters
  1845. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1846. return (value.search( new RegExp(text, 'i') ) !== -1);
  1847. },
  1848. // value contains text (case sensitive)
  1849. containsExactly: function(value, text) {
  1850. // escape regex characters
  1851. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1852. return (value.search( new RegExp(text) ) !== -1);
  1853. },
  1854. // value contains text (insensitive)
  1855. doesntContain: function(value, text) {
  1856. // escape regex characters
  1857. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1858. return (value.search( new RegExp(text, 'i') ) === -1);
  1859. },
  1860. // value contains text (case sensitive)
  1861. doesntContainExactly: function(value, text) {
  1862. // escape regex characters
  1863. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1864. return (value.search( new RegExp(text) ) === -1);
  1865. },
  1866. // is at least string length
  1867. minLength: function(value, requiredLength) {
  1868. return (value !== undefined)
  1869. ? (value.length >= requiredLength)
  1870. : false
  1871. ;
  1872. },
  1873. // see rls notes for 2.0.6 (this is a duplicate of minLength)
  1874. length: function(value, requiredLength) {
  1875. return (value !== undefined)
  1876. ? (value.length >= requiredLength)
  1877. : false
  1878. ;
  1879. },
  1880. // is exactly length
  1881. exactLength: function(value, requiredLength) {
  1882. return (value !== undefined)
  1883. ? (value.length == requiredLength)
  1884. : false
  1885. ;
  1886. },
  1887. // is less than length
  1888. maxLength: function(value, maxLength) {
  1889. return (value !== undefined)
  1890. ? (value.length <= maxLength)
  1891. : false
  1892. ;
  1893. },
  1894. // matches another field
  1895. match: function(value, identifier) {
  1896. var
  1897. $form = $(this),
  1898. matchingValue
  1899. ;
  1900. if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
  1901. matchingValue = $('[data-validate="'+ identifier +'"]').val();
  1902. }
  1903. else if($('#' + identifier).length > 0) {
  1904. matchingValue = $('#' + identifier).val();
  1905. }
  1906. else if($('[name="' + identifier +'"]').length > 0) {
  1907. matchingValue = $('[name="' + identifier + '"]').val();
  1908. }
  1909. else if( $('[name="' + identifier +'[]"]').length > 0 ) {
  1910. matchingValue = $('[name="' + identifier +'[]"]');
  1911. }
  1912. return (matchingValue !== undefined)
  1913. ? ( value.toString() == matchingValue.toString() )
  1914. : false
  1915. ;
  1916. },
  1917. // different than another field
  1918. different: function(value, identifier) {
  1919. // use either id or name of field
  1920. var
  1921. $form = $(this),
  1922. matchingValue
  1923. ;
  1924. if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
  1925. matchingValue = $('[data-validate="'+ identifier +'"]').val();
  1926. }
  1927. else if($('#' + identifier).length > 0) {
  1928. matchingValue = $('#' + identifier).val();
  1929. }
  1930. else if($('[name="' + identifier +'"]').length > 0) {
  1931. matchingValue = $('[name="' + identifier + '"]').val();
  1932. }
  1933. else if( $('[name="' + identifier +'[]"]').length > 0 ) {
  1934. matchingValue = $('[name="' + identifier +'[]"]');
  1935. }
  1936. return (matchingValue !== undefined)
  1937. ? ( value.toString() !== matchingValue.toString() )
  1938. : false
  1939. ;
  1940. },
  1941. creditCard: function(cardNumber, cardTypes) {
  1942. var
  1943. cards = {
  1944. visa: {
  1945. pattern : /^4/,
  1946. length : [16]
  1947. },
  1948. amex: {
  1949. pattern : /^3[47]/,
  1950. length : [15]
  1951. },
  1952. mastercard: {
  1953. pattern : /^5[1-5]/,
  1954. length : [16]
  1955. },
  1956. discover: {
  1957. pattern : /^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/,
  1958. length : [16]
  1959. },
  1960. unionPay: {
  1961. pattern : /^(62|88)/,
  1962. length : [16, 17, 18, 19]
  1963. },
  1964. jcb: {
  1965. pattern : /^35(2[89]|[3-8][0-9])/,
  1966. length : [16]
  1967. },
  1968. maestro: {
  1969. pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
  1970. length : [12, 13, 14, 15, 16, 17, 18, 19]
  1971. },
  1972. dinersClub: {
  1973. pattern : /^(30[0-5]|^36)/,
  1974. length : [14]
  1975. },
  1976. laser: {
  1977. pattern : /^(6304|670[69]|6771)/,
  1978. length : [16, 17, 18, 19]
  1979. },
  1980. visaElectron: {
  1981. pattern : /^(4026|417500|4508|4844|491(3|7))/,
  1982. length : [16]
  1983. }
  1984. },
  1985. valid = {},
  1986. validCard = false,
  1987. requiredTypes = (typeof cardTypes == 'string')
  1988. ? cardTypes.split(',')
  1989. : false,
  1990. unionPay,
  1991. validation
  1992. ;
  1993. if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
  1994. return;
  1995. }
  1996. // allow dashes in card
  1997. cardNumber = cardNumber.replace(/[\-]/g, '');
  1998. // verify card types
  1999. if(requiredTypes) {
  2000. $.each(requiredTypes, function(index, type){
  2001. // verify each card type
  2002. validation = cards[type];
  2003. if(validation) {
  2004. valid = {
  2005. length : ($.inArray(cardNumber.length, validation.length) !== -1),
  2006. pattern : (cardNumber.search(validation.pattern) !== -1)
  2007. };
  2008. if(valid.length && valid.pattern) {
  2009. validCard = true;
  2010. }
  2011. }
  2012. });
  2013. if(!validCard) {
  2014. return false;
  2015. }
  2016. }
  2017. // skip luhn for UnionPay
  2018. unionPay = {
  2019. number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
  2020. pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
  2021. };
  2022. if(unionPay.number && unionPay.pattern) {
  2023. return true;
  2024. }
  2025. // verify luhn, adapted from <https://gist.github.com/2134376>
  2026. var
  2027. length = cardNumber.length,
  2028. multiple = 0,
  2029. producedValue = [
  2030. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
  2031. [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
  2032. ],
  2033. sum = 0
  2034. ;
  2035. while (length--) {
  2036. sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
  2037. multiple ^= 1;
  2038. }
  2039. return (sum % 10 === 0 && sum > 0);
  2040. },
  2041. minCount: function(value, minCount) {
  2042. if(minCount == 0) {
  2043. return true;
  2044. }
  2045. if(minCount == 1) {
  2046. return (value !== '');
  2047. }
  2048. return (value.split(',').length >= minCount);
  2049. },
  2050. exactCount: function(value, exactCount) {
  2051. if(exactCount == 0) {
  2052. return (value === '');
  2053. }
  2054. if(exactCount == 1) {
  2055. return (value !== '' && value.search(',') === -1);
  2056. }
  2057. return (value.split(',').length == exactCount);
  2058. },
  2059. maxCount: function(value, maxCount) {
  2060. if(maxCount == 0) {
  2061. return false;
  2062. }
  2063. if(maxCount == 1) {
  2064. return (value.search(',') === -1);
  2065. }
  2066. return (value.split(',').length <= maxCount);
  2067. }
  2068. }
  2069. };
  2070. })( jQuery, window, document );
  2071. /*!
  2072. * # Semantic UI 2.4.1 - Accordion
  2073. * http://github.com/semantic-org/semantic-ui/
  2074. *
  2075. *
  2076. * Released under the MIT license
  2077. * http://opensource.org/licenses/MIT
  2078. *
  2079. */
  2080. ;(function ($, window, document, undefined) {
  2081. 'use strict';
  2082. window = (typeof window != 'undefined' && window.Math == Math)
  2083. ? window
  2084. : (typeof self != 'undefined' && self.Math == Math)
  2085. ? self
  2086. : Function('return this')()
  2087. ;
  2088. $.fn.accordion = function(parameters) {
  2089. var
  2090. $allModules = $(this),
  2091. time = new Date().getTime(),
  2092. performance = [],
  2093. query = arguments[0],
  2094. methodInvoked = (typeof query == 'string'),
  2095. queryArguments = [].slice.call(arguments, 1),
  2096. requestAnimationFrame = window.requestAnimationFrame
  2097. || window.mozRequestAnimationFrame
  2098. || window.webkitRequestAnimationFrame
  2099. || window.msRequestAnimationFrame
  2100. || function(callback) { setTimeout(callback, 0); },
  2101. returnedValue
  2102. ;
  2103. $allModules
  2104. .each(function() {
  2105. var
  2106. settings = ( $.isPlainObject(parameters) )
  2107. ? $.extend(true, {}, $.fn.accordion.settings, parameters)
  2108. : $.extend({}, $.fn.accordion.settings),
  2109. className = settings.className,
  2110. namespace = settings.namespace,
  2111. selector = settings.selector,
  2112. error = settings.error,
  2113. eventNamespace = '.' + namespace,
  2114. moduleNamespace = 'module-' + namespace,
  2115. moduleSelector = $allModules.selector || '',
  2116. $module = $(this),
  2117. $title = $module.find(selector.title),
  2118. $content = $module.find(selector.content),
  2119. element = this,
  2120. instance = $module.data(moduleNamespace),
  2121. observer,
  2122. module
  2123. ;
  2124. module = {
  2125. initialize: function() {
  2126. module.debug('Initializing', $module);
  2127. module.bind.events();
  2128. if(settings.observeChanges) {
  2129. module.observeChanges();
  2130. }
  2131. module.instantiate();
  2132. },
  2133. instantiate: function() {
  2134. instance = module;
  2135. $module
  2136. .data(moduleNamespace, module)
  2137. ;
  2138. },
  2139. destroy: function() {
  2140. module.debug('Destroying previous instance', $module);
  2141. $module
  2142. .off(eventNamespace)
  2143. .removeData(moduleNamespace)
  2144. ;
  2145. },
  2146. refresh: function() {
  2147. $title = $module.find(selector.title);
  2148. $content = $module.find(selector.content);
  2149. },
  2150. observeChanges: function() {
  2151. if('MutationObserver' in window) {
  2152. observer = new MutationObserver(function(mutations) {
  2153. module.debug('DOM tree modified, updating selector cache');
  2154. module.refresh();
  2155. });
  2156. observer.observe(element, {
  2157. childList : true,
  2158. subtree : true
  2159. });
  2160. module.debug('Setting up mutation observer', observer);
  2161. }
  2162. },
  2163. bind: {
  2164. events: function() {
  2165. module.debug('Binding delegated events');
  2166. $module
  2167. .on(settings.on + eventNamespace, selector.trigger, module.event.click)
  2168. ;
  2169. }
  2170. },
  2171. event: {
  2172. click: function() {
  2173. module.toggle.call(this);
  2174. }
  2175. },
  2176. toggle: function(query) {
  2177. var
  2178. $activeTitle = (query !== undefined)
  2179. ? (typeof query === 'number')
  2180. ? $title.eq(query)
  2181. : $(query).closest(selector.title)
  2182. : $(this).closest(selector.title),
  2183. $activeContent = $activeTitle.next($content),
  2184. isAnimating = $activeContent.hasClass(className.animating),
  2185. isActive = $activeContent.hasClass(className.active),
  2186. isOpen = (isActive && !isAnimating),
  2187. isOpening = (!isActive && isAnimating)
  2188. ;
  2189. module.debug('Toggling visibility of content', $activeTitle);
  2190. if(isOpen || isOpening) {
  2191. if(settings.collapsible) {
  2192. module.close.call($activeTitle);
  2193. }
  2194. else {
  2195. module.debug('Cannot close accordion content collapsing is disabled');
  2196. }
  2197. }
  2198. else {
  2199. module.open.call($activeTitle);
  2200. }
  2201. },
  2202. open: function(query) {
  2203. var
  2204. $activeTitle = (query !== undefined)
  2205. ? (typeof query === 'number')
  2206. ? $title.eq(query)
  2207. : $(query).closest(selector.title)
  2208. : $(this).closest(selector.title),
  2209. $activeContent = $activeTitle.next($content),
  2210. isAnimating = $activeContent.hasClass(className.animating),
  2211. isActive = $activeContent.hasClass(className.active),
  2212. isOpen = (isActive || isAnimating)
  2213. ;
  2214. if(isOpen) {
  2215. module.debug('Accordion already open, skipping', $activeContent);
  2216. return;
  2217. }
  2218. module.debug('Opening accordion content', $activeTitle);
  2219. settings.onOpening.call($activeContent);
  2220. settings.onChanging.call($activeContent);
  2221. if(settings.exclusive) {
  2222. module.closeOthers.call($activeTitle);
  2223. }
  2224. $activeTitle
  2225. .addClass(className.active)
  2226. ;
  2227. $activeContent
  2228. .stop(true, true)
  2229. .addClass(className.animating)
  2230. ;
  2231. if(settings.animateChildren) {
  2232. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2233. $activeContent
  2234. .children()
  2235. .transition({
  2236. animation : 'fade in',
  2237. queue : false,
  2238. useFailSafe : true,
  2239. debug : settings.debug,
  2240. verbose : settings.verbose,
  2241. duration : settings.duration
  2242. })
  2243. ;
  2244. }
  2245. else {
  2246. $activeContent
  2247. .children()
  2248. .stop(true, true)
  2249. .animate({
  2250. opacity: 1
  2251. }, settings.duration, module.resetOpacity)
  2252. ;
  2253. }
  2254. }
  2255. $activeContent
  2256. .slideDown(settings.duration, settings.easing, function() {
  2257. $activeContent
  2258. .removeClass(className.animating)
  2259. .addClass(className.active)
  2260. ;
  2261. module.reset.display.call(this);
  2262. settings.onOpen.call(this);
  2263. settings.onChange.call(this);
  2264. })
  2265. ;
  2266. },
  2267. close: function(query) {
  2268. var
  2269. $activeTitle = (query !== undefined)
  2270. ? (typeof query === 'number')
  2271. ? $title.eq(query)
  2272. : $(query).closest(selector.title)
  2273. : $(this).closest(selector.title),
  2274. $activeContent = $activeTitle.next($content),
  2275. isAnimating = $activeContent.hasClass(className.animating),
  2276. isActive = $activeContent.hasClass(className.active),
  2277. isOpening = (!isActive && isAnimating),
  2278. isClosing = (isActive && isAnimating)
  2279. ;
  2280. if((isActive || isOpening) && !isClosing) {
  2281. module.debug('Closing accordion content', $activeContent);
  2282. settings.onClosing.call($activeContent);
  2283. settings.onChanging.call($activeContent);
  2284. $activeTitle
  2285. .removeClass(className.active)
  2286. ;
  2287. $activeContent
  2288. .stop(true, true)
  2289. .addClass(className.animating)
  2290. ;
  2291. if(settings.animateChildren) {
  2292. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2293. $activeContent
  2294. .children()
  2295. .transition({
  2296. animation : 'fade out',
  2297. queue : false,
  2298. useFailSafe : true,
  2299. debug : settings.debug,
  2300. verbose : settings.verbose,
  2301. duration : settings.duration
  2302. })
  2303. ;
  2304. }
  2305. else {
  2306. $activeContent
  2307. .children()
  2308. .stop(true, true)
  2309. .animate({
  2310. opacity: 0
  2311. }, settings.duration, module.resetOpacity)
  2312. ;
  2313. }
  2314. }
  2315. $activeContent
  2316. .slideUp(settings.duration, settings.easing, function() {
  2317. $activeContent
  2318. .removeClass(className.animating)
  2319. .removeClass(className.active)
  2320. ;
  2321. module.reset.display.call(this);
  2322. settings.onClose.call(this);
  2323. settings.onChange.call(this);
  2324. })
  2325. ;
  2326. }
  2327. },
  2328. closeOthers: function(index) {
  2329. var
  2330. $activeTitle = (index !== undefined)
  2331. ? $title.eq(index)
  2332. : $(this).closest(selector.title),
  2333. $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
  2334. $activeAccordion = $activeTitle.closest(selector.accordion),
  2335. activeSelector = selector.title + '.' + className.active + ':visible',
  2336. activeContent = selector.content + '.' + className.active + ':visible',
  2337. $openTitles,
  2338. $nestedTitles,
  2339. $openContents
  2340. ;
  2341. if(settings.closeNested) {
  2342. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2343. $openContents = $openTitles.next($content);
  2344. }
  2345. else {
  2346. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2347. $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
  2348. $openTitles = $openTitles.not($nestedTitles);
  2349. $openContents = $openTitles.next($content);
  2350. }
  2351. if( ($openTitles.length > 0) ) {
  2352. module.debug('Exclusive enabled, closing other content', $openTitles);
  2353. $openTitles
  2354. .removeClass(className.active)
  2355. ;
  2356. $openContents
  2357. .removeClass(className.animating)
  2358. .stop(true, true)
  2359. ;
  2360. if(settings.animateChildren) {
  2361. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2362. $openContents
  2363. .children()
  2364. .transition({
  2365. animation : 'fade out',
  2366. useFailSafe : true,
  2367. debug : settings.debug,
  2368. verbose : settings.verbose,
  2369. duration : settings.duration
  2370. })
  2371. ;
  2372. }
  2373. else {
  2374. $openContents
  2375. .children()
  2376. .stop(true, true)
  2377. .animate({
  2378. opacity: 0
  2379. }, settings.duration, module.resetOpacity)
  2380. ;
  2381. }
  2382. }
  2383. $openContents
  2384. .slideUp(settings.duration , settings.easing, function() {
  2385. $(this).removeClass(className.active);
  2386. module.reset.display.call(this);
  2387. })
  2388. ;
  2389. }
  2390. },
  2391. reset: {
  2392. display: function() {
  2393. module.verbose('Removing inline display from element', this);
  2394. $(this).css('display', '');
  2395. if( $(this).attr('style') === '') {
  2396. $(this)
  2397. .attr('style', '')
  2398. .removeAttr('style')
  2399. ;
  2400. }
  2401. },
  2402. opacity: function() {
  2403. module.verbose('Removing inline opacity from element', this);
  2404. $(this).css('opacity', '');
  2405. if( $(this).attr('style') === '') {
  2406. $(this)
  2407. .attr('style', '')
  2408. .removeAttr('style')
  2409. ;
  2410. }
  2411. },
  2412. },
  2413. setting: function(name, value) {
  2414. module.debug('Changing setting', name, value);
  2415. if( $.isPlainObject(name) ) {
  2416. $.extend(true, settings, name);
  2417. }
  2418. else if(value !== undefined) {
  2419. if($.isPlainObject(settings[name])) {
  2420. $.extend(true, settings[name], value);
  2421. }
  2422. else {
  2423. settings[name] = value;
  2424. }
  2425. }
  2426. else {
  2427. return settings[name];
  2428. }
  2429. },
  2430. internal: function(name, value) {
  2431. module.debug('Changing internal', name, value);
  2432. if(value !== undefined) {
  2433. if( $.isPlainObject(name) ) {
  2434. $.extend(true, module, name);
  2435. }
  2436. else {
  2437. module[name] = value;
  2438. }
  2439. }
  2440. else {
  2441. return module[name];
  2442. }
  2443. },
  2444. debug: function() {
  2445. if(!settings.silent && settings.debug) {
  2446. if(settings.performance) {
  2447. module.performance.log(arguments);
  2448. }
  2449. else {
  2450. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2451. module.debug.apply(console, arguments);
  2452. }
  2453. }
  2454. },
  2455. verbose: function() {
  2456. if(!settings.silent && settings.verbose && settings.debug) {
  2457. if(settings.performance) {
  2458. module.performance.log(arguments);
  2459. }
  2460. else {
  2461. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2462. module.verbose.apply(console, arguments);
  2463. }
  2464. }
  2465. },
  2466. error: function() {
  2467. if(!settings.silent) {
  2468. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  2469. module.error.apply(console, arguments);
  2470. }
  2471. },
  2472. performance: {
  2473. log: function(message) {
  2474. var
  2475. currentTime,
  2476. executionTime,
  2477. previousTime
  2478. ;
  2479. if(settings.performance) {
  2480. currentTime = new Date().getTime();
  2481. previousTime = time || currentTime;
  2482. executionTime = currentTime - previousTime;
  2483. time = currentTime;
  2484. performance.push({
  2485. 'Name' : message[0],
  2486. 'Arguments' : [].slice.call(message, 1) || '',
  2487. 'Element' : element,
  2488. 'Execution Time' : executionTime
  2489. });
  2490. }
  2491. clearTimeout(module.performance.timer);
  2492. module.performance.timer = setTimeout(module.performance.display, 500);
  2493. },
  2494. display: function() {
  2495. var
  2496. title = settings.name + ':',
  2497. totalTime = 0
  2498. ;
  2499. time = false;
  2500. clearTimeout(module.performance.timer);
  2501. $.each(performance, function(index, data) {
  2502. totalTime += data['Execution Time'];
  2503. });
  2504. title += ' ' + totalTime + 'ms';
  2505. if(moduleSelector) {
  2506. title += ' \'' + moduleSelector + '\'';
  2507. }
  2508. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  2509. console.groupCollapsed(title);
  2510. if(console.table) {
  2511. console.table(performance);
  2512. }
  2513. else {
  2514. $.each(performance, function(index, data) {
  2515. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  2516. });
  2517. }
  2518. console.groupEnd();
  2519. }
  2520. performance = [];
  2521. }
  2522. },
  2523. invoke: function(query, passedArguments, context) {
  2524. var
  2525. object = instance,
  2526. maxDepth,
  2527. found,
  2528. response
  2529. ;
  2530. passedArguments = passedArguments || queryArguments;
  2531. context = element || context;
  2532. if(typeof query == 'string' && object !== undefined) {
  2533. query = query.split(/[\. ]/);
  2534. maxDepth = query.length - 1;
  2535. $.each(query, function(depth, value) {
  2536. var camelCaseValue = (depth != maxDepth)
  2537. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  2538. : query
  2539. ;
  2540. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  2541. object = object[camelCaseValue];
  2542. }
  2543. else if( object[camelCaseValue] !== undefined ) {
  2544. found = object[camelCaseValue];
  2545. return false;
  2546. }
  2547. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  2548. object = object[value];
  2549. }
  2550. else if( object[value] !== undefined ) {
  2551. found = object[value];
  2552. return false;
  2553. }
  2554. else {
  2555. module.error(error.method, query);
  2556. return false;
  2557. }
  2558. });
  2559. }
  2560. if ( $.isFunction( found ) ) {
  2561. response = found.apply(context, passedArguments);
  2562. }
  2563. else if(found !== undefined) {
  2564. response = found;
  2565. }
  2566. if($.isArray(returnedValue)) {
  2567. returnedValue.push(response);
  2568. }
  2569. else if(returnedValue !== undefined) {
  2570. returnedValue = [returnedValue, response];
  2571. }
  2572. else if(response !== undefined) {
  2573. returnedValue = response;
  2574. }
  2575. return found;
  2576. }
  2577. };
  2578. if(methodInvoked) {
  2579. if(instance === undefined) {
  2580. module.initialize();
  2581. }
  2582. module.invoke(query);
  2583. }
  2584. else {
  2585. if(instance !== undefined) {
  2586. instance.invoke('destroy');
  2587. }
  2588. module.initialize();
  2589. }
  2590. })
  2591. ;
  2592. return (returnedValue !== undefined)
  2593. ? returnedValue
  2594. : this
  2595. ;
  2596. };
  2597. $.fn.accordion.settings = {
  2598. name : 'Accordion',
  2599. namespace : 'accordion',
  2600. silent : false,
  2601. debug : false,
  2602. verbose : false,
  2603. performance : true,
  2604. on : 'click', // event on title that opens accordion
  2605. observeChanges : true, // whether accordion should automatically refresh on DOM insertion
  2606. exclusive : true, // whether a single accordion content panel should be open at once
  2607. collapsible : true, // whether accordion content can be closed
  2608. closeNested : false, // whether nested content should be closed when a panel is closed
  2609. animateChildren : true, // whether children opacity should be animated
  2610. duration : 350, // duration of animation
  2611. easing : 'easeOutQuad', // easing equation for animation
  2612. onOpening : function(){}, // callback before open animation
  2613. onClosing : function(){}, // callback before closing animation
  2614. onChanging : function(){}, // callback before closing or opening animation
  2615. onOpen : function(){}, // callback after open animation
  2616. onClose : function(){}, // callback after closing animation
  2617. onChange : function(){}, // callback after closing or opening animation
  2618. error: {
  2619. method : 'The method you called is not defined'
  2620. },
  2621. className : {
  2622. active : 'active',
  2623. animating : 'animating'
  2624. },
  2625. selector : {
  2626. accordion : '.accordion',
  2627. title : '.title',
  2628. trigger : '.title',
  2629. content : '.content'
  2630. }
  2631. };
  2632. // Adds easing
  2633. $.extend( $.easing, {
  2634. easeOutQuad: function (x, t, b, c, d) {
  2635. return -c *(t/=d)*(t-2) + b;
  2636. }
  2637. });
  2638. })( jQuery, window, document );
  2639. /*!
  2640. * # Semantic UI 2.4.1 - Checkbox
  2641. * http://github.com/semantic-org/semantic-ui/
  2642. *
  2643. *
  2644. * Released under the MIT license
  2645. * http://opensource.org/licenses/MIT
  2646. *
  2647. */
  2648. ;(function ($, window, document, undefined) {
  2649. 'use strict';
  2650. window = (typeof window != 'undefined' && window.Math == Math)
  2651. ? window
  2652. : (typeof self != 'undefined' && self.Math == Math)
  2653. ? self
  2654. : Function('return this')()
  2655. ;
  2656. $.fn.checkbox = function(parameters) {
  2657. var
  2658. $allModules = $(this),
  2659. moduleSelector = $allModules.selector || '',
  2660. time = new Date().getTime(),
  2661. performance = [],
  2662. query = arguments[0],
  2663. methodInvoked = (typeof query == 'string'),
  2664. queryArguments = [].slice.call(arguments, 1),
  2665. returnedValue
  2666. ;
  2667. $allModules
  2668. .each(function() {
  2669. var
  2670. settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
  2671. className = settings.className,
  2672. namespace = settings.namespace,
  2673. selector = settings.selector,
  2674. error = settings.error,
  2675. eventNamespace = '.' + namespace,
  2676. moduleNamespace = 'module-' + namespace,
  2677. $module = $(this),
  2678. $label = $(this).children(selector.label),
  2679. $input = $(this).children(selector.input),
  2680. input = $input[0],
  2681. initialLoad = false,
  2682. shortcutPressed = false,
  2683. instance = $module.data(moduleNamespace),
  2684. observer,
  2685. element = this,
  2686. module
  2687. ;
  2688. module = {
  2689. initialize: function() {
  2690. module.verbose('Initializing checkbox', settings);
  2691. module.create.label();
  2692. module.bind.events();
  2693. module.set.tabbable();
  2694. module.hide.input();
  2695. module.observeChanges();
  2696. module.instantiate();
  2697. module.setup();
  2698. },
  2699. instantiate: function() {
  2700. module.verbose('Storing instance of module', module);
  2701. instance = module;
  2702. $module
  2703. .data(moduleNamespace, module)
  2704. ;
  2705. },
  2706. destroy: function() {
  2707. module.verbose('Destroying module');
  2708. module.unbind.events();
  2709. module.show.input();
  2710. $module.removeData(moduleNamespace);
  2711. },
  2712. fix: {
  2713. reference: function() {
  2714. if( $module.is(selector.input) ) {
  2715. module.debug('Behavior called on <input> adjusting invoked element');
  2716. $module = $module.closest(selector.checkbox);
  2717. module.refresh();
  2718. }
  2719. }
  2720. },
  2721. setup: function() {
  2722. module.set.initialLoad();
  2723. if( module.is.indeterminate() ) {
  2724. module.debug('Initial value is indeterminate');
  2725. module.indeterminate();
  2726. }
  2727. else if( module.is.checked() ) {
  2728. module.debug('Initial value is checked');
  2729. module.check();
  2730. }
  2731. else {
  2732. module.debug('Initial value is unchecked');
  2733. module.uncheck();
  2734. }
  2735. module.remove.initialLoad();
  2736. },
  2737. refresh: function() {
  2738. $label = $module.children(selector.label);
  2739. $input = $module.children(selector.input);
  2740. input = $input[0];
  2741. },
  2742. hide: {
  2743. input: function() {
  2744. module.verbose('Modifying <input> z-index to be unselectable');
  2745. $input.addClass(className.hidden);
  2746. }
  2747. },
  2748. show: {
  2749. input: function() {
  2750. module.verbose('Modifying <input> z-index to be selectable');
  2751. $input.removeClass(className.hidden);
  2752. }
  2753. },
  2754. observeChanges: function() {
  2755. if('MutationObserver' in window) {
  2756. observer = new MutationObserver(function(mutations) {
  2757. module.debug('DOM tree modified, updating selector cache');
  2758. module.refresh();
  2759. });
  2760. observer.observe(element, {
  2761. childList : true,
  2762. subtree : true
  2763. });
  2764. module.debug('Setting up mutation observer', observer);
  2765. }
  2766. },
  2767. attachEvents: function(selector, event) {
  2768. var
  2769. $element = $(selector)
  2770. ;
  2771. event = $.isFunction(module[event])
  2772. ? module[event]
  2773. : module.toggle
  2774. ;
  2775. if($element.length > 0) {
  2776. module.debug('Attaching checkbox events to element', selector, event);
  2777. $element
  2778. .on('click' + eventNamespace, event)
  2779. ;
  2780. }
  2781. else {
  2782. module.error(error.notFound);
  2783. }
  2784. },
  2785. event: {
  2786. click: function(event) {
  2787. var
  2788. $target = $(event.target)
  2789. ;
  2790. if( $target.is(selector.input) ) {
  2791. module.verbose('Using default check action on initialized checkbox');
  2792. return;
  2793. }
  2794. if( $target.is(selector.link) ) {
  2795. module.debug('Clicking link inside checkbox, skipping toggle');
  2796. return;
  2797. }
  2798. module.toggle();
  2799. $input.focus();
  2800. event.preventDefault();
  2801. },
  2802. keydown: function(event) {
  2803. var
  2804. key = event.which,
  2805. keyCode = {
  2806. enter : 13,
  2807. space : 32,
  2808. escape : 27
  2809. }
  2810. ;
  2811. if(key == keyCode.escape) {
  2812. module.verbose('Escape key pressed blurring field');
  2813. $input.blur();
  2814. shortcutPressed = true;
  2815. }
  2816. else if(!event.ctrlKey && ( key == keyCode.space || key == keyCode.enter) ) {
  2817. module.verbose('Enter/space key pressed, toggling checkbox');
  2818. module.toggle();
  2819. shortcutPressed = true;
  2820. }
  2821. else {
  2822. shortcutPressed = false;
  2823. }
  2824. },
  2825. keyup: function(event) {
  2826. if(shortcutPressed) {
  2827. event.preventDefault();
  2828. }
  2829. }
  2830. },
  2831. check: function() {
  2832. if( !module.should.allowCheck() ) {
  2833. return;
  2834. }
  2835. module.debug('Checking checkbox', $input);
  2836. module.set.checked();
  2837. if( !module.should.ignoreCallbacks() ) {
  2838. settings.onChecked.call(input);
  2839. settings.onChange.call(input);
  2840. }
  2841. },
  2842. uncheck: function() {
  2843. if( !module.should.allowUncheck() ) {
  2844. return;
  2845. }
  2846. module.debug('Unchecking checkbox');
  2847. module.set.unchecked();
  2848. if( !module.should.ignoreCallbacks() ) {
  2849. settings.onUnchecked.call(input);
  2850. settings.onChange.call(input);
  2851. }
  2852. },
  2853. indeterminate: function() {
  2854. if( module.should.allowIndeterminate() ) {
  2855. module.debug('Checkbox is already indeterminate');
  2856. return;
  2857. }
  2858. module.debug('Making checkbox indeterminate');
  2859. module.set.indeterminate();
  2860. if( !module.should.ignoreCallbacks() ) {
  2861. settings.onIndeterminate.call(input);
  2862. settings.onChange.call(input);
  2863. }
  2864. },
  2865. determinate: function() {
  2866. if( module.should.allowDeterminate() ) {
  2867. module.debug('Checkbox is already determinate');
  2868. return;
  2869. }
  2870. module.debug('Making checkbox determinate');
  2871. module.set.determinate();
  2872. if( !module.should.ignoreCallbacks() ) {
  2873. settings.onDeterminate.call(input);
  2874. settings.onChange.call(input);
  2875. }
  2876. },
  2877. enable: function() {
  2878. if( module.is.enabled() ) {
  2879. module.debug('Checkbox is already enabled');
  2880. return;
  2881. }
  2882. module.debug('Enabling checkbox');
  2883. module.set.enabled();
  2884. settings.onEnable.call(input);
  2885. // preserve legacy callbacks
  2886. settings.onEnabled.call(input);
  2887. },
  2888. disable: function() {
  2889. if( module.is.disabled() ) {
  2890. module.debug('Checkbox is already disabled');
  2891. return;
  2892. }
  2893. module.debug('Disabling checkbox');
  2894. module.set.disabled();
  2895. settings.onDisable.call(input);
  2896. // preserve legacy callbacks
  2897. settings.onDisabled.call(input);
  2898. },
  2899. get: {
  2900. radios: function() {
  2901. var
  2902. name = module.get.name()
  2903. ;
  2904. return $('input[name="' + name + '"]').closest(selector.checkbox);
  2905. },
  2906. otherRadios: function() {
  2907. return module.get.radios().not($module);
  2908. },
  2909. name: function() {
  2910. return $input.attr('name');
  2911. }
  2912. },
  2913. is: {
  2914. initialLoad: function() {
  2915. return initialLoad;
  2916. },
  2917. radio: function() {
  2918. return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
  2919. },
  2920. indeterminate: function() {
  2921. return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
  2922. },
  2923. checked: function() {
  2924. return $input.prop('checked') !== undefined && $input.prop('checked');
  2925. },
  2926. disabled: function() {
  2927. return $input.prop('disabled') !== undefined && $input.prop('disabled');
  2928. },
  2929. enabled: function() {
  2930. return !module.is.disabled();
  2931. },
  2932. determinate: function() {
  2933. return !module.is.indeterminate();
  2934. },
  2935. unchecked: function() {
  2936. return !module.is.checked();
  2937. }
  2938. },
  2939. should: {
  2940. allowCheck: function() {
  2941. if(module.is.determinate() && module.is.checked() && !module.should.forceCallbacks() ) {
  2942. module.debug('Should not allow check, checkbox is already checked');
  2943. return false;
  2944. }
  2945. if(settings.beforeChecked.apply(input) === false) {
  2946. module.debug('Should not allow check, beforeChecked cancelled');
  2947. return false;
  2948. }
  2949. return true;
  2950. },
  2951. allowUncheck: function() {
  2952. if(module.is.determinate() && module.is.unchecked() && !module.should.forceCallbacks() ) {
  2953. module.debug('Should not allow uncheck, checkbox is already unchecked');
  2954. return false;
  2955. }
  2956. if(settings.beforeUnchecked.apply(input) === false) {
  2957. module.debug('Should not allow uncheck, beforeUnchecked cancelled');
  2958. return false;
  2959. }
  2960. return true;
  2961. },
  2962. allowIndeterminate: function() {
  2963. if(module.is.indeterminate() && !module.should.forceCallbacks() ) {
  2964. module.debug('Should not allow indeterminate, checkbox is already indeterminate');
  2965. return false;
  2966. }
  2967. if(settings.beforeIndeterminate.apply(input) === false) {
  2968. module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
  2969. return false;
  2970. }
  2971. return true;
  2972. },
  2973. allowDeterminate: function() {
  2974. if(module.is.determinate() && !module.should.forceCallbacks() ) {
  2975. module.debug('Should not allow determinate, checkbox is already determinate');
  2976. return false;
  2977. }
  2978. if(settings.beforeDeterminate.apply(input) === false) {
  2979. module.debug('Should not allow determinate, beforeDeterminate cancelled');
  2980. return false;
  2981. }
  2982. return true;
  2983. },
  2984. forceCallbacks: function() {
  2985. return (module.is.initialLoad() && settings.fireOnInit);
  2986. },
  2987. ignoreCallbacks: function() {
  2988. return (initialLoad && !settings.fireOnInit);
  2989. }
  2990. },
  2991. can: {
  2992. change: function() {
  2993. return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
  2994. },
  2995. uncheck: function() {
  2996. return (typeof settings.uncheckable === 'boolean')
  2997. ? settings.uncheckable
  2998. : !module.is.radio()
  2999. ;
  3000. }
  3001. },
  3002. set: {
  3003. initialLoad: function() {
  3004. initialLoad = true;
  3005. },
  3006. checked: function() {
  3007. module.verbose('Setting class to checked');
  3008. $module
  3009. .removeClass(className.indeterminate)
  3010. .addClass(className.checked)
  3011. ;
  3012. if( module.is.radio() ) {
  3013. module.uncheckOthers();
  3014. }
  3015. if(!module.is.indeterminate() && module.is.checked()) {
  3016. module.debug('Input is already checked, skipping input property change');
  3017. return;
  3018. }
  3019. module.verbose('Setting state to checked', input);
  3020. $input
  3021. .prop('indeterminate', false)
  3022. .prop('checked', true)
  3023. ;
  3024. module.trigger.change();
  3025. },
  3026. unchecked: function() {
  3027. module.verbose('Removing checked class');
  3028. $module
  3029. .removeClass(className.indeterminate)
  3030. .removeClass(className.checked)
  3031. ;
  3032. if(!module.is.indeterminate() && module.is.unchecked() ) {
  3033. module.debug('Input is already unchecked');
  3034. return;
  3035. }
  3036. module.debug('Setting state to unchecked');
  3037. $input
  3038. .prop('indeterminate', false)
  3039. .prop('checked', false)
  3040. ;
  3041. module.trigger.change();
  3042. },
  3043. indeterminate: function() {
  3044. module.verbose('Setting class to indeterminate');
  3045. $module
  3046. .addClass(className.indeterminate)
  3047. ;
  3048. if( module.is.indeterminate() ) {
  3049. module.debug('Input is already indeterminate, skipping input property change');
  3050. return;
  3051. }
  3052. module.debug('Setting state to indeterminate');
  3053. $input
  3054. .prop('indeterminate', true)
  3055. ;
  3056. module.trigger.change();
  3057. },
  3058. determinate: function() {
  3059. module.verbose('Removing indeterminate class');
  3060. $module
  3061. .removeClass(className.indeterminate)
  3062. ;
  3063. if( module.is.determinate() ) {
  3064. module.debug('Input is already determinate, skipping input property change');
  3065. return;
  3066. }
  3067. module.debug('Setting state to determinate');
  3068. $input
  3069. .prop('indeterminate', false)
  3070. ;
  3071. },
  3072. disabled: function() {
  3073. module.verbose('Setting class to disabled');
  3074. $module
  3075. .addClass(className.disabled)
  3076. ;
  3077. if( module.is.disabled() ) {
  3078. module.debug('Input is already disabled, skipping input property change');
  3079. return;
  3080. }
  3081. module.debug('Setting state to disabled');
  3082. $input
  3083. .prop('disabled', 'disabled')
  3084. ;
  3085. module.trigger.change();
  3086. },
  3087. enabled: function() {
  3088. module.verbose('Removing disabled class');
  3089. $module.removeClass(className.disabled);
  3090. if( module.is.enabled() ) {
  3091. module.debug('Input is already enabled, skipping input property change');
  3092. return;
  3093. }
  3094. module.debug('Setting state to enabled');
  3095. $input
  3096. .prop('disabled', false)
  3097. ;
  3098. module.trigger.change();
  3099. },
  3100. tabbable: function() {
  3101. module.verbose('Adding tabindex to checkbox');
  3102. if( $input.attr('tabindex') === undefined) {
  3103. $input.attr('tabindex', 0);
  3104. }
  3105. }
  3106. },
  3107. remove: {
  3108. initialLoad: function() {
  3109. initialLoad = false;
  3110. }
  3111. },
  3112. trigger: {
  3113. change: function() {
  3114. var
  3115. events = document.createEvent('HTMLEvents'),
  3116. inputElement = $input[0]
  3117. ;
  3118. if(inputElement) {
  3119. module.verbose('Triggering native change event');
  3120. events.initEvent('change', true, false);
  3121. inputElement.dispatchEvent(events);
  3122. }
  3123. }
  3124. },
  3125. create: {
  3126. label: function() {
  3127. if($input.prevAll(selector.label).length > 0) {
  3128. $input.prev(selector.label).detach().insertAfter($input);
  3129. module.debug('Moving existing label', $label);
  3130. }
  3131. else if( !module.has.label() ) {
  3132. $label = $('<label>').insertAfter($input);
  3133. module.debug('Creating label', $label);
  3134. }
  3135. }
  3136. },
  3137. has: {
  3138. label: function() {
  3139. return ($label.length > 0);
  3140. }
  3141. },
  3142. bind: {
  3143. events: function() {
  3144. module.verbose('Attaching checkbox events');
  3145. $module
  3146. .on('click' + eventNamespace, module.event.click)
  3147. .on('keydown' + eventNamespace, selector.input, module.event.keydown)
  3148. .on('keyup' + eventNamespace, selector.input, module.event.keyup)
  3149. ;
  3150. }
  3151. },
  3152. unbind: {
  3153. events: function() {
  3154. module.debug('Removing events');
  3155. $module
  3156. .off(eventNamespace)
  3157. ;
  3158. }
  3159. },
  3160. uncheckOthers: function() {
  3161. var
  3162. $radios = module.get.otherRadios()
  3163. ;
  3164. module.debug('Unchecking other radios', $radios);
  3165. $radios.removeClass(className.checked);
  3166. },
  3167. toggle: function() {
  3168. if( !module.can.change() ) {
  3169. if(!module.is.radio()) {
  3170. module.debug('Checkbox is read-only or disabled, ignoring toggle');
  3171. }
  3172. return;
  3173. }
  3174. if( module.is.indeterminate() || module.is.unchecked() ) {
  3175. module.debug('Currently unchecked');
  3176. module.check();
  3177. }
  3178. else if( module.is.checked() && module.can.uncheck() ) {
  3179. module.debug('Currently checked');
  3180. module.uncheck();
  3181. }
  3182. },
  3183. setting: function(name, value) {
  3184. module.debug('Changing setting', name, value);
  3185. if( $.isPlainObject(name) ) {
  3186. $.extend(true, settings, name);
  3187. }
  3188. else if(value !== undefined) {
  3189. if($.isPlainObject(settings[name])) {
  3190. $.extend(true, settings[name], value);
  3191. }
  3192. else {
  3193. settings[name] = value;
  3194. }
  3195. }
  3196. else {
  3197. return settings[name];
  3198. }
  3199. },
  3200. internal: function(name, value) {
  3201. if( $.isPlainObject(name) ) {
  3202. $.extend(true, module, name);
  3203. }
  3204. else if(value !== undefined) {
  3205. module[name] = value;
  3206. }
  3207. else {
  3208. return module[name];
  3209. }
  3210. },
  3211. debug: function() {
  3212. if(!settings.silent && settings.debug) {
  3213. if(settings.performance) {
  3214. module.performance.log(arguments);
  3215. }
  3216. else {
  3217. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3218. module.debug.apply(console, arguments);
  3219. }
  3220. }
  3221. },
  3222. verbose: function() {
  3223. if(!settings.silent && settings.verbose && settings.debug) {
  3224. if(settings.performance) {
  3225. module.performance.log(arguments);
  3226. }
  3227. else {
  3228. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3229. module.verbose.apply(console, arguments);
  3230. }
  3231. }
  3232. },
  3233. error: function() {
  3234. if(!settings.silent) {
  3235. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3236. module.error.apply(console, arguments);
  3237. }
  3238. },
  3239. performance: {
  3240. log: function(message) {
  3241. var
  3242. currentTime,
  3243. executionTime,
  3244. previousTime
  3245. ;
  3246. if(settings.performance) {
  3247. currentTime = new Date().getTime();
  3248. previousTime = time || currentTime;
  3249. executionTime = currentTime - previousTime;
  3250. time = currentTime;
  3251. performance.push({
  3252. 'Name' : message[0],
  3253. 'Arguments' : [].slice.call(message, 1) || '',
  3254. 'Element' : element,
  3255. 'Execution Time' : executionTime
  3256. });
  3257. }
  3258. clearTimeout(module.performance.timer);
  3259. module.performance.timer = setTimeout(module.performance.display, 500);
  3260. },
  3261. display: function() {
  3262. var
  3263. title = settings.name + ':',
  3264. totalTime = 0
  3265. ;
  3266. time = false;
  3267. clearTimeout(module.performance.timer);
  3268. $.each(performance, function(index, data) {
  3269. totalTime += data['Execution Time'];
  3270. });
  3271. title += ' ' + totalTime + 'ms';
  3272. if(moduleSelector) {
  3273. title += ' \'' + moduleSelector + '\'';
  3274. }
  3275. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3276. console.groupCollapsed(title);
  3277. if(console.table) {
  3278. console.table(performance);
  3279. }
  3280. else {
  3281. $.each(performance, function(index, data) {
  3282. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  3283. });
  3284. }
  3285. console.groupEnd();
  3286. }
  3287. performance = [];
  3288. }
  3289. },
  3290. invoke: function(query, passedArguments, context) {
  3291. var
  3292. object = instance,
  3293. maxDepth,
  3294. found,
  3295. response
  3296. ;
  3297. passedArguments = passedArguments || queryArguments;
  3298. context = element || context;
  3299. if(typeof query == 'string' && object !== undefined) {
  3300. query = query.split(/[\. ]/);
  3301. maxDepth = query.length - 1;
  3302. $.each(query, function(depth, value) {
  3303. var camelCaseValue = (depth != maxDepth)
  3304. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3305. : query
  3306. ;
  3307. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  3308. object = object[camelCaseValue];
  3309. }
  3310. else if( object[camelCaseValue] !== undefined ) {
  3311. found = object[camelCaseValue];
  3312. return false;
  3313. }
  3314. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  3315. object = object[value];
  3316. }
  3317. else if( object[value] !== undefined ) {
  3318. found = object[value];
  3319. return false;
  3320. }
  3321. else {
  3322. module.error(error.method, query);
  3323. return false;
  3324. }
  3325. });
  3326. }
  3327. if ( $.isFunction( found ) ) {
  3328. response = found.apply(context, passedArguments);
  3329. }
  3330. else if(found !== undefined) {
  3331. response = found;
  3332. }
  3333. if($.isArray(returnedValue)) {
  3334. returnedValue.push(response);
  3335. }
  3336. else if(returnedValue !== undefined) {
  3337. returnedValue = [returnedValue, response];
  3338. }
  3339. else if(response !== undefined) {
  3340. returnedValue = response;
  3341. }
  3342. return found;
  3343. }
  3344. };
  3345. if(methodInvoked) {
  3346. if(instance === undefined) {
  3347. module.initialize();
  3348. }
  3349. module.invoke(query);
  3350. }
  3351. else {
  3352. if(instance !== undefined) {
  3353. instance.invoke('destroy');
  3354. }
  3355. module.initialize();
  3356. }
  3357. })
  3358. ;
  3359. return (returnedValue !== undefined)
  3360. ? returnedValue
  3361. : this
  3362. ;
  3363. };
  3364. $.fn.checkbox.settings = {
  3365. name : 'Checkbox',
  3366. namespace : 'checkbox',
  3367. silent : false,
  3368. debug : false,
  3369. verbose : true,
  3370. performance : true,
  3371. // delegated event context
  3372. uncheckable : 'auto',
  3373. fireOnInit : false,
  3374. onChange : function(){},
  3375. beforeChecked : function(){},
  3376. beforeUnchecked : function(){},
  3377. beforeDeterminate : function(){},
  3378. beforeIndeterminate : function(){},
  3379. onChecked : function(){},
  3380. onUnchecked : function(){},
  3381. onDeterminate : function() {},
  3382. onIndeterminate : function() {},
  3383. onEnable : function(){},
  3384. onDisable : function(){},
  3385. // preserve misspelled callbacks (will be removed in 3.0)
  3386. onEnabled : function(){},
  3387. onDisabled : function(){},
  3388. className : {
  3389. checked : 'checked',
  3390. indeterminate : 'indeterminate',
  3391. disabled : 'disabled',
  3392. hidden : 'hidden',
  3393. radio : 'radio',
  3394. readOnly : 'read-only'
  3395. },
  3396. error : {
  3397. method : 'The method you called is not defined'
  3398. },
  3399. selector : {
  3400. checkbox : '.ui.checkbox',
  3401. label : 'label, .box',
  3402. input : 'input[type="checkbox"], input[type="radio"]',
  3403. link : 'a[href]'
  3404. }
  3405. };
  3406. })( jQuery, window, document );
  3407. /*!
  3408. * # Semantic UI 2.4.1 - Dimmer
  3409. * http://github.com/semantic-org/semantic-ui/
  3410. *
  3411. *
  3412. * Released under the MIT license
  3413. * http://opensource.org/licenses/MIT
  3414. *
  3415. */
  3416. ;(function ($, window, document, undefined) {
  3417. 'use strict';
  3418. window = (typeof window != 'undefined' && window.Math == Math)
  3419. ? window
  3420. : (typeof self != 'undefined' && self.Math == Math)
  3421. ? self
  3422. : Function('return this')()
  3423. ;
  3424. $.fn.dimmer = function(parameters) {
  3425. var
  3426. $allModules = $(this),
  3427. time = new Date().getTime(),
  3428. performance = [],
  3429. query = arguments[0],
  3430. methodInvoked = (typeof query == 'string'),
  3431. queryArguments = [].slice.call(arguments, 1),
  3432. returnedValue
  3433. ;
  3434. $allModules
  3435. .each(function() {
  3436. var
  3437. settings = ( $.isPlainObject(parameters) )
  3438. ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
  3439. : $.extend({}, $.fn.dimmer.settings),
  3440. selector = settings.selector,
  3441. namespace = settings.namespace,
  3442. className = settings.className,
  3443. error = settings.error,
  3444. eventNamespace = '.' + namespace,
  3445. moduleNamespace = 'module-' + namespace,
  3446. moduleSelector = $allModules.selector || '',
  3447. clickEvent = ('ontouchstart' in document.documentElement)
  3448. ? 'touchstart'
  3449. : 'click',
  3450. $module = $(this),
  3451. $dimmer,
  3452. $dimmable,
  3453. element = this,
  3454. instance = $module.data(moduleNamespace),
  3455. module
  3456. ;
  3457. module = {
  3458. preinitialize: function() {
  3459. if( module.is.dimmer() ) {
  3460. $dimmable = $module.parent();
  3461. $dimmer = $module;
  3462. }
  3463. else {
  3464. $dimmable = $module;
  3465. if( module.has.dimmer() ) {
  3466. if(settings.dimmerName) {
  3467. $dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
  3468. }
  3469. else {
  3470. $dimmer = $dimmable.find(selector.dimmer);
  3471. }
  3472. }
  3473. else {
  3474. $dimmer = module.create();
  3475. }
  3476. }
  3477. },
  3478. initialize: function() {
  3479. module.debug('Initializing dimmer', settings);
  3480. module.bind.events();
  3481. module.set.dimmable();
  3482. module.instantiate();
  3483. },
  3484. instantiate: function() {
  3485. module.verbose('Storing instance of module', module);
  3486. instance = module;
  3487. $module
  3488. .data(moduleNamespace, instance)
  3489. ;
  3490. },
  3491. destroy: function() {
  3492. module.verbose('Destroying previous module', $dimmer);
  3493. module.unbind.events();
  3494. module.remove.variation();
  3495. $dimmable
  3496. .off(eventNamespace)
  3497. ;
  3498. },
  3499. bind: {
  3500. events: function() {
  3501. if(settings.on == 'hover') {
  3502. $dimmable
  3503. .on('mouseenter' + eventNamespace, module.show)
  3504. .on('mouseleave' + eventNamespace, module.hide)
  3505. ;
  3506. }
  3507. else if(settings.on == 'click') {
  3508. $dimmable
  3509. .on(clickEvent + eventNamespace, module.toggle)
  3510. ;
  3511. }
  3512. if( module.is.page() ) {
  3513. module.debug('Setting as a page dimmer', $dimmable);
  3514. module.set.pageDimmer();
  3515. }
  3516. if( module.is.closable() ) {
  3517. module.verbose('Adding dimmer close event', $dimmer);
  3518. $dimmable
  3519. .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
  3520. ;
  3521. }
  3522. }
  3523. },
  3524. unbind: {
  3525. events: function() {
  3526. $module
  3527. .removeData(moduleNamespace)
  3528. ;
  3529. $dimmable
  3530. .off(eventNamespace)
  3531. ;
  3532. }
  3533. },
  3534. event: {
  3535. click: function(event) {
  3536. module.verbose('Determining if event occured on dimmer', event);
  3537. if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
  3538. module.hide();
  3539. event.stopImmediatePropagation();
  3540. }
  3541. },
  3542. },
  3543. addContent: function(element) {
  3544. var
  3545. $content = $(element)
  3546. ;
  3547. module.debug('Add content to dimmer', $content);
  3548. if($content.parent()[0] !== $dimmer[0]) {
  3549. $content.detach().appendTo($dimmer);
  3550. }
  3551. },
  3552. create: function() {
  3553. var
  3554. $element = $( settings.template.dimmer() )
  3555. ;
  3556. if(settings.dimmerName) {
  3557. module.debug('Creating named dimmer', settings.dimmerName);
  3558. $element.addClass(settings.dimmerName);
  3559. }
  3560. $element
  3561. .appendTo($dimmable)
  3562. ;
  3563. return $element;
  3564. },
  3565. show: function(callback) {
  3566. callback = $.isFunction(callback)
  3567. ? callback
  3568. : function(){}
  3569. ;
  3570. module.debug('Showing dimmer', $dimmer, settings);
  3571. module.set.variation();
  3572. if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
  3573. module.animate.show(callback);
  3574. settings.onShow.call(element);
  3575. settings.onChange.call(element);
  3576. }
  3577. else {
  3578. module.debug('Dimmer is already shown or disabled');
  3579. }
  3580. },
  3581. hide: function(callback) {
  3582. callback = $.isFunction(callback)
  3583. ? callback
  3584. : function(){}
  3585. ;
  3586. if( module.is.dimmed() || module.is.animating() ) {
  3587. module.debug('Hiding dimmer', $dimmer);
  3588. module.animate.hide(callback);
  3589. settings.onHide.call(element);
  3590. settings.onChange.call(element);
  3591. }
  3592. else {
  3593. module.debug('Dimmer is not visible');
  3594. }
  3595. },
  3596. toggle: function() {
  3597. module.verbose('Toggling dimmer visibility', $dimmer);
  3598. if( !module.is.dimmed() ) {
  3599. module.show();
  3600. }
  3601. else {
  3602. module.hide();
  3603. }
  3604. },
  3605. animate: {
  3606. show: function(callback) {
  3607. callback = $.isFunction(callback)
  3608. ? callback
  3609. : function(){}
  3610. ;
  3611. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3612. if(settings.useFlex) {
  3613. module.debug('Using flex dimmer');
  3614. module.remove.legacy();
  3615. }
  3616. else {
  3617. module.debug('Using legacy non-flex dimmer');
  3618. module.set.legacy();
  3619. }
  3620. if(settings.opacity !== 'auto') {
  3621. module.set.opacity();
  3622. }
  3623. $dimmer
  3624. .transition({
  3625. displayType : settings.useFlex
  3626. ? 'flex'
  3627. : 'block',
  3628. animation : settings.transition + ' in',
  3629. queue : false,
  3630. duration : module.get.duration(),
  3631. useFailSafe : true,
  3632. onStart : function() {
  3633. module.set.dimmed();
  3634. },
  3635. onComplete : function() {
  3636. module.set.active();
  3637. callback();
  3638. }
  3639. })
  3640. ;
  3641. }
  3642. else {
  3643. module.verbose('Showing dimmer animation with javascript');
  3644. module.set.dimmed();
  3645. if(settings.opacity == 'auto') {
  3646. settings.opacity = 0.8;
  3647. }
  3648. $dimmer
  3649. .stop()
  3650. .css({
  3651. opacity : 0,
  3652. width : '100%',
  3653. height : '100%'
  3654. })
  3655. .fadeTo(module.get.duration(), settings.opacity, function() {
  3656. $dimmer.removeAttr('style');
  3657. module.set.active();
  3658. callback();
  3659. })
  3660. ;
  3661. }
  3662. },
  3663. hide: function(callback) {
  3664. callback = $.isFunction(callback)
  3665. ? callback
  3666. : function(){}
  3667. ;
  3668. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3669. module.verbose('Hiding dimmer with css');
  3670. $dimmer
  3671. .transition({
  3672. displayType : settings.useFlex
  3673. ? 'flex'
  3674. : 'block',
  3675. animation : settings.transition + ' out',
  3676. queue : false,
  3677. duration : module.get.duration(),
  3678. useFailSafe : true,
  3679. onStart : function() {
  3680. module.remove.dimmed();
  3681. },
  3682. onComplete : function() {
  3683. module.remove.variation();
  3684. module.remove.active();
  3685. callback();
  3686. }
  3687. })
  3688. ;
  3689. }
  3690. else {
  3691. module.verbose('Hiding dimmer with javascript');
  3692. module.remove.dimmed();
  3693. $dimmer
  3694. .stop()
  3695. .fadeOut(module.get.duration(), function() {
  3696. module.remove.active();
  3697. $dimmer.removeAttr('style');
  3698. callback();
  3699. })
  3700. ;
  3701. }
  3702. }
  3703. },
  3704. get: {
  3705. dimmer: function() {
  3706. return $dimmer;
  3707. },
  3708. duration: function() {
  3709. if(typeof settings.duration == 'object') {
  3710. if( module.is.active() ) {
  3711. return settings.duration.hide;
  3712. }
  3713. else {
  3714. return settings.duration.show;
  3715. }
  3716. }
  3717. return settings.duration;
  3718. }
  3719. },
  3720. has: {
  3721. dimmer: function() {
  3722. if(settings.dimmerName) {
  3723. return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
  3724. }
  3725. else {
  3726. return ( $module.find(selector.dimmer).length > 0 );
  3727. }
  3728. }
  3729. },
  3730. is: {
  3731. active: function() {
  3732. return $dimmer.hasClass(className.active);
  3733. },
  3734. animating: function() {
  3735. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
  3736. },
  3737. closable: function() {
  3738. if(settings.closable == 'auto') {
  3739. if(settings.on == 'hover') {
  3740. return false;
  3741. }
  3742. return true;
  3743. }
  3744. return settings.closable;
  3745. },
  3746. dimmer: function() {
  3747. return $module.hasClass(className.dimmer);
  3748. },
  3749. dimmable: function() {
  3750. return $module.hasClass(className.dimmable);
  3751. },
  3752. dimmed: function() {
  3753. return $dimmable.hasClass(className.dimmed);
  3754. },
  3755. disabled: function() {
  3756. return $dimmable.hasClass(className.disabled);
  3757. },
  3758. enabled: function() {
  3759. return !module.is.disabled();
  3760. },
  3761. page: function () {
  3762. return $dimmable.is('body');
  3763. },
  3764. pageDimmer: function() {
  3765. return $dimmer.hasClass(className.pageDimmer);
  3766. }
  3767. },
  3768. can: {
  3769. show: function() {
  3770. return !$dimmer.hasClass(className.disabled);
  3771. }
  3772. },
  3773. set: {
  3774. opacity: function(opacity) {
  3775. var
  3776. color = $dimmer.css('background-color'),
  3777. colorArray = color.split(','),
  3778. isRGB = (colorArray && colorArray.length == 3),
  3779. isRGBA = (colorArray && colorArray.length == 4)
  3780. ;
  3781. opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
  3782. if(isRGB || isRGBA) {
  3783. colorArray[3] = opacity + ')';
  3784. color = colorArray.join(',');
  3785. }
  3786. else {
  3787. color = 'rgba(0, 0, 0, ' + opacity + ')';
  3788. }
  3789. module.debug('Setting opacity to', opacity);
  3790. $dimmer.css('background-color', color);
  3791. },
  3792. legacy: function() {
  3793. $dimmer.addClass(className.legacy);
  3794. },
  3795. active: function() {
  3796. $dimmer.addClass(className.active);
  3797. },
  3798. dimmable: function() {
  3799. $dimmable.addClass(className.dimmable);
  3800. },
  3801. dimmed: function() {
  3802. $dimmable.addClass(className.dimmed);
  3803. },
  3804. pageDimmer: function() {
  3805. $dimmer.addClass(className.pageDimmer);
  3806. },
  3807. disabled: function() {
  3808. $dimmer.addClass(className.disabled);
  3809. },
  3810. variation: function(variation) {
  3811. variation = variation || settings.variation;
  3812. if(variation) {
  3813. $dimmer.addClass(variation);
  3814. }
  3815. }
  3816. },
  3817. remove: {
  3818. active: function() {
  3819. $dimmer
  3820. .removeClass(className.active)
  3821. ;
  3822. },
  3823. legacy: function() {
  3824. $dimmer.removeClass(className.legacy);
  3825. },
  3826. dimmed: function() {
  3827. $dimmable.removeClass(className.dimmed);
  3828. },
  3829. disabled: function() {
  3830. $dimmer.removeClass(className.disabled);
  3831. },
  3832. variation: function(variation) {
  3833. variation = variation || settings.variation;
  3834. if(variation) {
  3835. $dimmer.removeClass(variation);
  3836. }
  3837. }
  3838. },
  3839. setting: function(name, value) {
  3840. module.debug('Changing setting', name, value);
  3841. if( $.isPlainObject(name) ) {
  3842. $.extend(true, settings, name);
  3843. }
  3844. else if(value !== undefined) {
  3845. if($.isPlainObject(settings[name])) {
  3846. $.extend(true, settings[name], value);
  3847. }
  3848. else {
  3849. settings[name] = value;
  3850. }
  3851. }
  3852. else {
  3853. return settings[name];
  3854. }
  3855. },
  3856. internal: function(name, value) {
  3857. if( $.isPlainObject(name) ) {
  3858. $.extend(true, module, name);
  3859. }
  3860. else if(value !== undefined) {
  3861. module[name] = value;
  3862. }
  3863. else {
  3864. return module[name];
  3865. }
  3866. },
  3867. debug: function() {
  3868. if(!settings.silent && settings.debug) {
  3869. if(settings.performance) {
  3870. module.performance.log(arguments);
  3871. }
  3872. else {
  3873. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3874. module.debug.apply(console, arguments);
  3875. }
  3876. }
  3877. },
  3878. verbose: function() {
  3879. if(!settings.silent && settings.verbose && settings.debug) {
  3880. if(settings.performance) {
  3881. module.performance.log(arguments);
  3882. }
  3883. else {
  3884. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3885. module.verbose.apply(console, arguments);
  3886. }
  3887. }
  3888. },
  3889. error: function() {
  3890. if(!settings.silent) {
  3891. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3892. module.error.apply(console, arguments);
  3893. }
  3894. },
  3895. performance: {
  3896. log: function(message) {
  3897. var
  3898. currentTime,
  3899. executionTime,
  3900. previousTime
  3901. ;
  3902. if(settings.performance) {
  3903. currentTime = new Date().getTime();
  3904. previousTime = time || currentTime;
  3905. executionTime = currentTime - previousTime;
  3906. time = currentTime;
  3907. performance.push({
  3908. 'Name' : message[0],
  3909. 'Arguments' : [].slice.call(message, 1) || '',
  3910. 'Element' : element,
  3911. 'Execution Time' : executionTime
  3912. });
  3913. }
  3914. clearTimeout(module.performance.timer);
  3915. module.performance.timer = setTimeout(module.performance.display, 500);
  3916. },
  3917. display: function() {
  3918. var
  3919. title = settings.name + ':',
  3920. totalTime = 0
  3921. ;
  3922. time = false;
  3923. clearTimeout(module.performance.timer);
  3924. $.each(performance, function(index, data) {
  3925. totalTime += data['Execution Time'];
  3926. });
  3927. title += ' ' + totalTime + 'ms';
  3928. if(moduleSelector) {
  3929. title += ' \'' + moduleSelector + '\'';
  3930. }
  3931. if($allModules.length > 1) {
  3932. title += ' ' + '(' + $allModules.length + ')';
  3933. }
  3934. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3935. console.groupCollapsed(title);
  3936. if(console.table) {
  3937. console.table(performance);
  3938. }
  3939. else {
  3940. $.each(performance, function(index, data) {
  3941. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  3942. });
  3943. }
  3944. console.groupEnd();
  3945. }
  3946. performance = [];
  3947. }
  3948. },
  3949. invoke: function(query, passedArguments, context) {
  3950. var
  3951. object = instance,
  3952. maxDepth,
  3953. found,
  3954. response
  3955. ;
  3956. passedArguments = passedArguments || queryArguments;
  3957. context = element || context;
  3958. if(typeof query == 'string' && object !== undefined) {
  3959. query = query.split(/[\. ]/);
  3960. maxDepth = query.length - 1;
  3961. $.each(query, function(depth, value) {
  3962. var camelCaseValue = (depth != maxDepth)
  3963. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3964. : query
  3965. ;
  3966. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  3967. object = object[camelCaseValue];
  3968. }
  3969. else if( object[camelCaseValue] !== undefined ) {
  3970. found = object[camelCaseValue];
  3971. return false;
  3972. }
  3973. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  3974. object = object[value];
  3975. }
  3976. else if( object[value] !== undefined ) {
  3977. found = object[value];
  3978. return false;
  3979. }
  3980. else {
  3981. module.error(error.method, query);
  3982. return false;
  3983. }
  3984. });
  3985. }
  3986. if ( $.isFunction( found ) ) {
  3987. response = found.apply(context, passedArguments);
  3988. }
  3989. else if(found !== undefined) {
  3990. response = found;
  3991. }
  3992. if($.isArray(returnedValue)) {
  3993. returnedValue.push(response);
  3994. }
  3995. else if(returnedValue !== undefined) {
  3996. returnedValue = [returnedValue, response];
  3997. }
  3998. else if(response !== undefined) {
  3999. returnedValue = response;
  4000. }
  4001. return found;
  4002. }
  4003. };
  4004. module.preinitialize();
  4005. if(methodInvoked) {
  4006. if(instance === undefined) {
  4007. module.initialize();
  4008. }
  4009. module.invoke(query);
  4010. }
  4011. else {
  4012. if(instance !== undefined) {
  4013. instance.invoke('destroy');
  4014. }
  4015. module.initialize();
  4016. }
  4017. })
  4018. ;
  4019. return (returnedValue !== undefined)
  4020. ? returnedValue
  4021. : this
  4022. ;
  4023. };
  4024. $.fn.dimmer.settings = {
  4025. name : 'Dimmer',
  4026. namespace : 'dimmer',
  4027. silent : false,
  4028. debug : false,
  4029. verbose : false,
  4030. performance : true,
  4031. // whether should use flex layout
  4032. useFlex : true,
  4033. // name to distinguish between multiple dimmers in context
  4034. dimmerName : false,
  4035. // whether to add a variation type
  4036. variation : false,
  4037. // whether to bind close events
  4038. closable : 'auto',
  4039. // whether to use css animations
  4040. useCSS : true,
  4041. // css animation to use
  4042. transition : 'fade',
  4043. // event to bind to
  4044. on : false,
  4045. // overriding opacity value
  4046. opacity : 'auto',
  4047. // transition durations
  4048. duration : {
  4049. show : 500,
  4050. hide : 500
  4051. },
  4052. onChange : function(){},
  4053. onShow : function(){},
  4054. onHide : function(){},
  4055. error : {
  4056. method : 'The method you called is not defined.'
  4057. },
  4058. className : {
  4059. active : 'active',
  4060. animating : 'animating',
  4061. dimmable : 'dimmable',
  4062. dimmed : 'dimmed',
  4063. dimmer : 'dimmer',
  4064. disabled : 'disabled',
  4065. hide : 'hide',
  4066. legacy : 'legacy',
  4067. pageDimmer : 'page',
  4068. show : 'show'
  4069. },
  4070. selector: {
  4071. dimmer : '> .ui.dimmer',
  4072. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  4073. },
  4074. template: {
  4075. dimmer: function() {
  4076. return $('<div />').attr('class', 'ui dimmer');
  4077. }
  4078. }
  4079. };
  4080. })( jQuery, window, document );
  4081. /*!
  4082. * # Semantic UI 2.4.1 - Dropdown
  4083. * http://github.com/semantic-org/semantic-ui/
  4084. *
  4085. *
  4086. * Released under the MIT license
  4087. * http://opensource.org/licenses/MIT
  4088. *
  4089. */
  4090. ;(function ($, window, document, undefined) {
  4091. 'use strict';
  4092. window = (typeof window != 'undefined' && window.Math == Math)
  4093. ? window
  4094. : (typeof self != 'undefined' && self.Math == Math)
  4095. ? self
  4096. : Function('return this')()
  4097. ;
  4098. $.fn.dropdown = function(parameters) {
  4099. var
  4100. $allModules = $(this),
  4101. $document = $(document),
  4102. moduleSelector = $allModules.selector || '',
  4103. hasTouch = ('ontouchstart' in document.documentElement),
  4104. time = new Date().getTime(),
  4105. performance = [],
  4106. query = arguments[0],
  4107. methodInvoked = (typeof query == 'string'),
  4108. queryArguments = [].slice.call(arguments, 1),
  4109. returnedValue
  4110. ;
  4111. $allModules
  4112. .each(function(elementIndex) {
  4113. var
  4114. settings = ( $.isPlainObject(parameters) )
  4115. ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
  4116. : $.extend({}, $.fn.dropdown.settings),
  4117. className = settings.className,
  4118. message = settings.message,
  4119. fields = settings.fields,
  4120. keys = settings.keys,
  4121. metadata = settings.metadata,
  4122. namespace = settings.namespace,
  4123. regExp = settings.regExp,
  4124. selector = settings.selector,
  4125. error = settings.error,
  4126. templates = settings.templates,
  4127. eventNamespace = '.' + namespace,
  4128. moduleNamespace = 'module-' + namespace,
  4129. $module = $(this),
  4130. $context = $(settings.context),
  4131. $text = $module.find(selector.text),
  4132. $search = $module.find(selector.search),
  4133. $sizer = $module.find(selector.sizer),
  4134. $input = $module.find(selector.input),
  4135. $icon = $module.find(selector.icon),
  4136. $combo = ($module.prev().find(selector.text).length > 0)
  4137. ? $module.prev().find(selector.text)
  4138. : $module.prev(),
  4139. $menu = $module.children(selector.menu),
  4140. $item = $menu.find(selector.item),
  4141. activated = false,
  4142. itemActivated = false,
  4143. internalChange = false,
  4144. element = this,
  4145. instance = $module.data(moduleNamespace),
  4146. initialLoad,
  4147. pageLostFocus,
  4148. willRefocus,
  4149. elementNamespace,
  4150. id,
  4151. selectObserver,
  4152. menuObserver,
  4153. module
  4154. ;
  4155. module = {
  4156. initialize: function() {
  4157. module.debug('Initializing dropdown', settings);
  4158. if( module.is.alreadySetup() ) {
  4159. module.setup.reference();
  4160. }
  4161. else {
  4162. module.setup.layout();
  4163. if(settings.values) {
  4164. module.change.values(settings.values);
  4165. }
  4166. module.refreshData();
  4167. module.save.defaults();
  4168. module.restore.selected();
  4169. module.create.id();
  4170. module.bind.events();
  4171. module.observeChanges();
  4172. module.instantiate();
  4173. }
  4174. },
  4175. instantiate: function() {
  4176. module.verbose('Storing instance of dropdown', module);
  4177. instance = module;
  4178. $module
  4179. .data(moduleNamespace, module)
  4180. ;
  4181. },
  4182. destroy: function() {
  4183. module.verbose('Destroying previous dropdown', $module);
  4184. module.remove.tabbable();
  4185. $module
  4186. .off(eventNamespace)
  4187. .removeData(moduleNamespace)
  4188. ;
  4189. $menu
  4190. .off(eventNamespace)
  4191. ;
  4192. $document
  4193. .off(elementNamespace)
  4194. ;
  4195. module.disconnect.menuObserver();
  4196. module.disconnect.selectObserver();
  4197. },
  4198. observeChanges: function() {
  4199. if('MutationObserver' in window) {
  4200. selectObserver = new MutationObserver(module.event.select.mutation);
  4201. menuObserver = new MutationObserver(module.event.menu.mutation);
  4202. module.debug('Setting up mutation observer', selectObserver, menuObserver);
  4203. module.observe.select();
  4204. module.observe.menu();
  4205. }
  4206. },
  4207. disconnect: {
  4208. menuObserver: function() {
  4209. if(menuObserver) {
  4210. menuObserver.disconnect();
  4211. }
  4212. },
  4213. selectObserver: function() {
  4214. if(selectObserver) {
  4215. selectObserver.disconnect();
  4216. }
  4217. }
  4218. },
  4219. observe: {
  4220. select: function() {
  4221. if(module.has.input()) {
  4222. selectObserver.observe($module[0], {
  4223. childList : true,
  4224. subtree : true
  4225. });
  4226. }
  4227. },
  4228. menu: function() {
  4229. if(module.has.menu()) {
  4230. menuObserver.observe($menu[0], {
  4231. childList : true,
  4232. subtree : true
  4233. });
  4234. }
  4235. }
  4236. },
  4237. create: {
  4238. id: function() {
  4239. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  4240. elementNamespace = '.' + id;
  4241. module.verbose('Creating unique id for element', id);
  4242. },
  4243. userChoice: function(values) {
  4244. var
  4245. $userChoices,
  4246. $userChoice,
  4247. isUserValue,
  4248. html
  4249. ;
  4250. values = values || module.get.userValues();
  4251. if(!values) {
  4252. return false;
  4253. }
  4254. values = $.isArray(values)
  4255. ? values
  4256. : [values]
  4257. ;
  4258. $.each(values, function(index, value) {
  4259. if(module.get.item(value) === false) {
  4260. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  4261. $userChoice = $('<div />')
  4262. .html(html)
  4263. .attr('data-' + metadata.value, value)
  4264. .attr('data-' + metadata.text, value)
  4265. .addClass(className.addition)
  4266. .addClass(className.item)
  4267. ;
  4268. if(settings.hideAdditions) {
  4269. $userChoice.addClass(className.hidden);
  4270. }
  4271. $userChoices = ($userChoices === undefined)
  4272. ? $userChoice
  4273. : $userChoices.add($userChoice)
  4274. ;
  4275. module.verbose('Creating user choices for value', value, $userChoice);
  4276. }
  4277. });
  4278. return $userChoices;
  4279. },
  4280. userLabels: function(value) {
  4281. var
  4282. userValues = module.get.userValues()
  4283. ;
  4284. if(userValues) {
  4285. module.debug('Adding user labels', userValues);
  4286. $.each(userValues, function(index, value) {
  4287. module.verbose('Adding custom user value');
  4288. module.add.label(value, value);
  4289. });
  4290. }
  4291. },
  4292. menu: function() {
  4293. $menu = $('<div />')
  4294. .addClass(className.menu)
  4295. .appendTo($module)
  4296. ;
  4297. },
  4298. sizer: function() {
  4299. $sizer = $('<span />')
  4300. .addClass(className.sizer)
  4301. .insertAfter($search)
  4302. ;
  4303. }
  4304. },
  4305. search: function(query) {
  4306. query = (query !== undefined)
  4307. ? query
  4308. : module.get.query()
  4309. ;
  4310. module.verbose('Searching for query', query);
  4311. if(module.has.minCharacters(query)) {
  4312. module.filter(query);
  4313. }
  4314. else {
  4315. module.hide();
  4316. }
  4317. },
  4318. select: {
  4319. firstUnfiltered: function() {
  4320. module.verbose('Selecting first non-filtered element');
  4321. module.remove.selectedItem();
  4322. $item
  4323. .not(selector.unselectable)
  4324. .not(selector.addition + selector.hidden)
  4325. .eq(0)
  4326. .addClass(className.selected)
  4327. ;
  4328. },
  4329. nextAvailable: function($selected) {
  4330. $selected = $selected.eq(0);
  4331. var
  4332. $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
  4333. $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
  4334. hasNext = ($nextAvailable.length > 0)
  4335. ;
  4336. if(hasNext) {
  4337. module.verbose('Moving selection to', $nextAvailable);
  4338. $nextAvailable.addClass(className.selected);
  4339. }
  4340. else {
  4341. module.verbose('Moving selection to', $prevAvailable);
  4342. $prevAvailable.addClass(className.selected);
  4343. }
  4344. }
  4345. },
  4346. setup: {
  4347. api: function() {
  4348. var
  4349. apiSettings = {
  4350. debug : settings.debug,
  4351. urlData : {
  4352. value : module.get.value(),
  4353. query : module.get.query()
  4354. },
  4355. on : false
  4356. }
  4357. ;
  4358. module.verbose('First request, initializing API');
  4359. $module
  4360. .api(apiSettings)
  4361. ;
  4362. },
  4363. layout: function() {
  4364. if( $module.is('select') ) {
  4365. module.setup.select();
  4366. module.setup.returnedObject();
  4367. }
  4368. if( !module.has.menu() ) {
  4369. module.create.menu();
  4370. }
  4371. if( module.is.search() && !module.has.search() ) {
  4372. module.verbose('Adding search input');
  4373. $search = $('<input />')
  4374. .addClass(className.search)
  4375. .prop('autocomplete', 'off')
  4376. .insertBefore($text)
  4377. ;
  4378. }
  4379. if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
  4380. module.create.sizer();
  4381. }
  4382. if(settings.allowTab) {
  4383. module.set.tabbable();
  4384. }
  4385. },
  4386. select: function() {
  4387. var
  4388. selectValues = module.get.selectValues()
  4389. ;
  4390. module.debug('Dropdown initialized on a select', selectValues);
  4391. if( $module.is('select') ) {
  4392. $input = $module;
  4393. }
  4394. // see if select is placed correctly already
  4395. if($input.parent(selector.dropdown).length > 0) {
  4396. module.debug('UI dropdown already exists. Creating dropdown menu only');
  4397. $module = $input.closest(selector.dropdown);
  4398. if( !module.has.menu() ) {
  4399. module.create.menu();
  4400. }
  4401. $menu = $module.children(selector.menu);
  4402. module.setup.menu(selectValues);
  4403. }
  4404. else {
  4405. module.debug('Creating entire dropdown from select');
  4406. $module = $('<div />')
  4407. .attr('class', $input.attr('class') )
  4408. .addClass(className.selection)
  4409. .addClass(className.dropdown)
  4410. .html( templates.dropdown(selectValues) )
  4411. .insertBefore($input)
  4412. ;
  4413. if($input.hasClass(className.multiple) && $input.prop('multiple') === false) {
  4414. module.error(error.missingMultiple);
  4415. $input.prop('multiple', true);
  4416. }
  4417. if($input.is('[multiple]')) {
  4418. module.set.multiple();
  4419. }
  4420. if ($input.prop('disabled')) {
  4421. module.debug('Disabling dropdown');
  4422. $module.addClass(className.disabled);
  4423. }
  4424. $input
  4425. .removeAttr('class')
  4426. .detach()
  4427. .prependTo($module)
  4428. ;
  4429. }
  4430. module.refresh();
  4431. },
  4432. menu: function(values) {
  4433. $menu.html( templates.menu(values, fields));
  4434. $item = $menu.find(selector.item);
  4435. },
  4436. reference: function() {
  4437. module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
  4438. // replace module reference
  4439. $module = $module.parent(selector.dropdown);
  4440. instance = $module.data(moduleNamespace);
  4441. element = $module.get(0);
  4442. module.refresh();
  4443. module.setup.returnedObject();
  4444. },
  4445. returnedObject: function() {
  4446. var
  4447. $firstModules = $allModules.slice(0, elementIndex),
  4448. $lastModules = $allModules.slice(elementIndex + 1)
  4449. ;
  4450. // adjust all modules to use correct reference
  4451. $allModules = $firstModules.add($module).add($lastModules);
  4452. }
  4453. },
  4454. refresh: function() {
  4455. module.refreshSelectors();
  4456. module.refreshData();
  4457. },
  4458. refreshItems: function() {
  4459. $item = $menu.find(selector.item);
  4460. },
  4461. refreshSelectors: function() {
  4462. module.verbose('Refreshing selector cache');
  4463. $text = $module.find(selector.text);
  4464. $search = $module.find(selector.search);
  4465. $input = $module.find(selector.input);
  4466. $icon = $module.find(selector.icon);
  4467. $combo = ($module.prev().find(selector.text).length > 0)
  4468. ? $module.prev().find(selector.text)
  4469. : $module.prev()
  4470. ;
  4471. $menu = $module.children(selector.menu);
  4472. $item = $menu.find(selector.item);
  4473. },
  4474. refreshData: function() {
  4475. module.verbose('Refreshing cached metadata');
  4476. $item
  4477. .removeData(metadata.text)
  4478. .removeData(metadata.value)
  4479. ;
  4480. },
  4481. clearData: function() {
  4482. module.verbose('Clearing metadata');
  4483. $item
  4484. .removeData(metadata.text)
  4485. .removeData(metadata.value)
  4486. ;
  4487. $module
  4488. .removeData(metadata.defaultText)
  4489. .removeData(metadata.defaultValue)
  4490. .removeData(metadata.placeholderText)
  4491. ;
  4492. },
  4493. toggle: function() {
  4494. module.verbose('Toggling menu visibility');
  4495. if( !module.is.active() ) {
  4496. module.show();
  4497. }
  4498. else {
  4499. module.hide();
  4500. }
  4501. },
  4502. show: function(callback) {
  4503. callback = $.isFunction(callback)
  4504. ? callback
  4505. : function(){}
  4506. ;
  4507. if(!module.can.show() && module.is.remote()) {
  4508. module.debug('No API results retrieved, searching before show');
  4509. module.queryRemote(module.get.query(), module.show);
  4510. }
  4511. if( module.can.show() && !module.is.active() ) {
  4512. module.debug('Showing dropdown');
  4513. if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
  4514. module.remove.message();
  4515. }
  4516. if(module.is.allFiltered()) {
  4517. return true;
  4518. }
  4519. if(settings.onShow.call(element) !== false) {
  4520. module.animate.show(function() {
  4521. if( module.can.click() ) {
  4522. module.bind.intent();
  4523. }
  4524. if(module.has.menuSearch()) {
  4525. module.focusSearch();
  4526. }
  4527. module.set.visible();
  4528. callback.call(element);
  4529. });
  4530. }
  4531. }
  4532. },
  4533. hide: function(callback) {
  4534. callback = $.isFunction(callback)
  4535. ? callback
  4536. : function(){}
  4537. ;
  4538. if( module.is.active() && !module.is.animatingOutward() ) {
  4539. module.debug('Hiding dropdown');
  4540. if(settings.onHide.call(element) !== false) {
  4541. module.animate.hide(function() {
  4542. module.remove.visible();
  4543. callback.call(element);
  4544. });
  4545. }
  4546. }
  4547. },
  4548. hideOthers: function() {
  4549. module.verbose('Finding other dropdowns to hide');
  4550. $allModules
  4551. .not($module)
  4552. .has(selector.menu + '.' + className.visible)
  4553. .dropdown('hide')
  4554. ;
  4555. },
  4556. hideMenu: function() {
  4557. module.verbose('Hiding menu instantaneously');
  4558. module.remove.active();
  4559. module.remove.visible();
  4560. $menu.transition('hide');
  4561. },
  4562. hideSubMenus: function() {
  4563. var
  4564. $subMenus = $menu.children(selector.item).find(selector.menu)
  4565. ;
  4566. module.verbose('Hiding sub menus', $subMenus);
  4567. $subMenus.transition('hide');
  4568. },
  4569. bind: {
  4570. events: function() {
  4571. if(hasTouch) {
  4572. module.bind.touchEvents();
  4573. }
  4574. module.bind.keyboardEvents();
  4575. module.bind.inputEvents();
  4576. module.bind.mouseEvents();
  4577. },
  4578. touchEvents: function() {
  4579. module.debug('Touch device detected binding additional touch events');
  4580. if( module.is.searchSelection() ) {
  4581. // do nothing special yet
  4582. }
  4583. else if( module.is.single() ) {
  4584. $module
  4585. .on('touchstart' + eventNamespace, module.event.test.toggle)
  4586. ;
  4587. }
  4588. $menu
  4589. .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
  4590. ;
  4591. },
  4592. keyboardEvents: function() {
  4593. module.verbose('Binding keyboard events');
  4594. $module
  4595. .on('keydown' + eventNamespace, module.event.keydown)
  4596. ;
  4597. if( module.has.search() ) {
  4598. $module
  4599. .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
  4600. ;
  4601. }
  4602. if( module.is.multiple() ) {
  4603. $document
  4604. .on('keydown' + elementNamespace, module.event.document.keydown)
  4605. ;
  4606. }
  4607. },
  4608. inputEvents: function() {
  4609. module.verbose('Binding input change events');
  4610. $module
  4611. .on('change' + eventNamespace, selector.input, module.event.change)
  4612. ;
  4613. },
  4614. mouseEvents: function() {
  4615. module.verbose('Binding mouse events');
  4616. if(module.is.multiple()) {
  4617. $module
  4618. .on('click' + eventNamespace, selector.label, module.event.label.click)
  4619. .on('click' + eventNamespace, selector.remove, module.event.remove.click)
  4620. ;
  4621. }
  4622. if( module.is.searchSelection() ) {
  4623. $module
  4624. .on('mousedown' + eventNamespace, module.event.mousedown)
  4625. .on('mouseup' + eventNamespace, module.event.mouseup)
  4626. .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
  4627. .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
  4628. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  4629. .on('focus' + eventNamespace, selector.search, module.event.search.focus)
  4630. .on('click' + eventNamespace, selector.search, module.event.search.focus)
  4631. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  4632. .on('click' + eventNamespace, selector.text, module.event.text.focus)
  4633. ;
  4634. if(module.is.multiple()) {
  4635. $module
  4636. .on('click' + eventNamespace, module.event.click)
  4637. ;
  4638. }
  4639. }
  4640. else {
  4641. if(settings.on == 'click') {
  4642. $module
  4643. .on('click' + eventNamespace, module.event.test.toggle)
  4644. ;
  4645. }
  4646. else if(settings.on == 'hover') {
  4647. $module
  4648. .on('mouseenter' + eventNamespace, module.delay.show)
  4649. .on('mouseleave' + eventNamespace, module.delay.hide)
  4650. ;
  4651. }
  4652. else {
  4653. $module
  4654. .on(settings.on + eventNamespace, module.toggle)
  4655. ;
  4656. }
  4657. $module
  4658. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  4659. .on('mousedown' + eventNamespace, module.event.mousedown)
  4660. .on('mouseup' + eventNamespace, module.event.mouseup)
  4661. .on('focus' + eventNamespace, module.event.focus)
  4662. ;
  4663. if(module.has.menuSearch() ) {
  4664. $module
  4665. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  4666. ;
  4667. }
  4668. else {
  4669. $module
  4670. .on('blur' + eventNamespace, module.event.blur)
  4671. ;
  4672. }
  4673. }
  4674. $menu
  4675. .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
  4676. .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
  4677. .on('click' + eventNamespace, selector.item, module.event.item.click)
  4678. ;
  4679. },
  4680. intent: function() {
  4681. module.verbose('Binding hide intent event to document');
  4682. if(hasTouch) {
  4683. $document
  4684. .on('touchstart' + elementNamespace, module.event.test.touch)
  4685. .on('touchmove' + elementNamespace, module.event.test.touch)
  4686. ;
  4687. }
  4688. $document
  4689. .on('click' + elementNamespace, module.event.test.hide)
  4690. ;
  4691. }
  4692. },
  4693. unbind: {
  4694. intent: function() {
  4695. module.verbose('Removing hide intent event from document');
  4696. if(hasTouch) {
  4697. $document
  4698. .off('touchstart' + elementNamespace)
  4699. .off('touchmove' + elementNamespace)
  4700. ;
  4701. }
  4702. $document
  4703. .off('click' + elementNamespace)
  4704. ;
  4705. }
  4706. },
  4707. filter: function(query) {
  4708. var
  4709. searchTerm = (query !== undefined)
  4710. ? query
  4711. : module.get.query(),
  4712. afterFiltered = function() {
  4713. if(module.is.multiple()) {
  4714. module.filterActive();
  4715. }
  4716. if(query || (!query && module.get.activeItem().length == 0)) {
  4717. module.select.firstUnfiltered();
  4718. }
  4719. if( module.has.allResultsFiltered() ) {
  4720. if( settings.onNoResults.call(element, searchTerm) ) {
  4721. if(settings.allowAdditions) {
  4722. if(settings.hideAdditions) {
  4723. module.verbose('User addition with no menu, setting empty style');
  4724. module.set.empty();
  4725. module.hideMenu();
  4726. }
  4727. }
  4728. else {
  4729. module.verbose('All items filtered, showing message', searchTerm);
  4730. module.add.message(message.noResults);
  4731. }
  4732. }
  4733. else {
  4734. module.verbose('All items filtered, hiding dropdown', searchTerm);
  4735. module.hideMenu();
  4736. }
  4737. }
  4738. else {
  4739. module.remove.empty();
  4740. module.remove.message();
  4741. }
  4742. if(settings.allowAdditions) {
  4743. module.add.userSuggestion(query);
  4744. }
  4745. if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
  4746. module.show();
  4747. }
  4748. }
  4749. ;
  4750. if(settings.useLabels && module.has.maxSelections()) {
  4751. return;
  4752. }
  4753. if(settings.apiSettings) {
  4754. if( module.can.useAPI() ) {
  4755. module.queryRemote(searchTerm, function() {
  4756. if(settings.filterRemoteData) {
  4757. module.filterItems(searchTerm);
  4758. }
  4759. afterFiltered();
  4760. });
  4761. }
  4762. else {
  4763. module.error(error.noAPI);
  4764. }
  4765. }
  4766. else {
  4767. module.filterItems(searchTerm);
  4768. afterFiltered();
  4769. }
  4770. },
  4771. queryRemote: function(query, callback) {
  4772. var
  4773. apiSettings = {
  4774. errorDuration : false,
  4775. cache : 'local',
  4776. throttle : settings.throttle,
  4777. urlData : {
  4778. query: query
  4779. },
  4780. onError: function() {
  4781. module.add.message(message.serverError);
  4782. callback();
  4783. },
  4784. onFailure: function() {
  4785. module.add.message(message.serverError);
  4786. callback();
  4787. },
  4788. onSuccess : function(response) {
  4789. var
  4790. values = response[fields.remoteValues],
  4791. hasRemoteValues = ($.isArray(values) && values.length > 0)
  4792. ;
  4793. if(hasRemoteValues) {
  4794. module.remove.message();
  4795. module.setup.menu({
  4796. values: response[fields.remoteValues]
  4797. });
  4798. }
  4799. else {
  4800. module.add.message(message.noResults);
  4801. }
  4802. callback();
  4803. }
  4804. }
  4805. ;
  4806. if( !$module.api('get request') ) {
  4807. module.setup.api();
  4808. }
  4809. apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
  4810. $module
  4811. .api('setting', apiSettings)
  4812. .api('query')
  4813. ;
  4814. },
  4815. filterItems: function(query) {
  4816. var
  4817. searchTerm = (query !== undefined)
  4818. ? query
  4819. : module.get.query(),
  4820. results = null,
  4821. escapedTerm = module.escape.string(searchTerm),
  4822. beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm')
  4823. ;
  4824. // avoid loop if we're matching nothing
  4825. if( module.has.query() ) {
  4826. results = [];
  4827. module.verbose('Searching for matching values', searchTerm);
  4828. $item
  4829. .each(function(){
  4830. var
  4831. $choice = $(this),
  4832. text,
  4833. value
  4834. ;
  4835. if(settings.match == 'both' || settings.match == 'text') {
  4836. text = String(module.get.choiceText($choice, false));
  4837. if(text.search(beginsWithRegExp) !== -1) {
  4838. results.push(this);
  4839. return true;
  4840. }
  4841. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) {
  4842. results.push(this);
  4843. return true;
  4844. }
  4845. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) {
  4846. results.push(this);
  4847. return true;
  4848. }
  4849. }
  4850. if(settings.match == 'both' || settings.match == 'value') {
  4851. value = String(module.get.choiceValue($choice, text));
  4852. if(value.search(beginsWithRegExp) !== -1) {
  4853. results.push(this);
  4854. return true;
  4855. }
  4856. else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, value)) {
  4857. results.push(this);
  4858. return true;
  4859. }
  4860. else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, value)) {
  4861. results.push(this);
  4862. return true;
  4863. }
  4864. }
  4865. })
  4866. ;
  4867. }
  4868. module.debug('Showing only matched items', searchTerm);
  4869. module.remove.filteredItem();
  4870. if(results) {
  4871. $item
  4872. .not(results)
  4873. .addClass(className.filtered)
  4874. ;
  4875. }
  4876. },
  4877. fuzzySearch: function(query, term) {
  4878. var
  4879. termLength = term.length,
  4880. queryLength = query.length
  4881. ;
  4882. query = query.toLowerCase();
  4883. term = term.toLowerCase();
  4884. if(queryLength > termLength) {
  4885. return false;
  4886. }
  4887. if(queryLength === termLength) {
  4888. return (query === term);
  4889. }
  4890. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  4891. var
  4892. queryCharacter = query.charCodeAt(characterIndex)
  4893. ;
  4894. while(nextCharacterIndex < termLength) {
  4895. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  4896. continue search;
  4897. }
  4898. }
  4899. return false;
  4900. }
  4901. return true;
  4902. },
  4903. exactSearch: function (query, term) {
  4904. query = query.toLowerCase();
  4905. term = term.toLowerCase();
  4906. if(term.indexOf(query) > -1) {
  4907. return true;
  4908. }
  4909. return false;
  4910. },
  4911. filterActive: function() {
  4912. if(settings.useLabels) {
  4913. $item.filter('.' + className.active)
  4914. .addClass(className.filtered)
  4915. ;
  4916. }
  4917. },
  4918. focusSearch: function(skipHandler) {
  4919. if( module.has.search() && !module.is.focusedOnSearch() ) {
  4920. if(skipHandler) {
  4921. $module.off('focus' + eventNamespace, selector.search);
  4922. $search.focus();
  4923. $module.on('focus' + eventNamespace, selector.search, module.event.search.focus);
  4924. }
  4925. else {
  4926. $search.focus();
  4927. }
  4928. }
  4929. },
  4930. forceSelection: function() {
  4931. var
  4932. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  4933. $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
  4934. $selectedItem = ($currentlySelected.length > 0)
  4935. ? $currentlySelected
  4936. : $activeItem,
  4937. hasSelected = ($selectedItem.length > 0)
  4938. ;
  4939. if(hasSelected && !module.is.multiple()) {
  4940. module.debug('Forcing partial selection to selected item', $selectedItem);
  4941. module.event.item.click.call($selectedItem, {}, true);
  4942. return;
  4943. }
  4944. else {
  4945. if(settings.allowAdditions) {
  4946. module.set.selected(module.get.query());
  4947. module.remove.searchTerm();
  4948. }
  4949. else {
  4950. module.remove.searchTerm();
  4951. }
  4952. }
  4953. },
  4954. change: {
  4955. values: function(values) {
  4956. if(!settings.allowAdditions) {
  4957. module.clear();
  4958. }
  4959. module.debug('Creating dropdown with specified values', values);
  4960. module.setup.menu({values: values});
  4961. $.each(values, function(index, item) {
  4962. if(item.selected == true) {
  4963. module.debug('Setting initial selection to', item.value);
  4964. module.set.selected(item.value);
  4965. return true;
  4966. }
  4967. });
  4968. }
  4969. },
  4970. event: {
  4971. change: function() {
  4972. if(!internalChange) {
  4973. module.debug('Input changed, updating selection');
  4974. module.set.selected();
  4975. }
  4976. },
  4977. focus: function() {
  4978. if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
  4979. module.show();
  4980. }
  4981. },
  4982. blur: function(event) {
  4983. pageLostFocus = (document.activeElement === this);
  4984. if(!activated && !pageLostFocus) {
  4985. module.remove.activeLabel();
  4986. module.hide();
  4987. }
  4988. },
  4989. mousedown: function() {
  4990. if(module.is.searchSelection()) {
  4991. // prevent menu hiding on immediate re-focus
  4992. willRefocus = true;
  4993. }
  4994. else {
  4995. // prevents focus callback from occurring on mousedown
  4996. activated = true;
  4997. }
  4998. },
  4999. mouseup: function() {
  5000. if(module.is.searchSelection()) {
  5001. // prevent menu hiding on immediate re-focus
  5002. willRefocus = false;
  5003. }
  5004. else {
  5005. activated = false;
  5006. }
  5007. },
  5008. click: function(event) {
  5009. var
  5010. $target = $(event.target)
  5011. ;
  5012. // focus search
  5013. if($target.is($module)) {
  5014. if(!module.is.focusedOnSearch()) {
  5015. module.focusSearch();
  5016. }
  5017. else {
  5018. module.show();
  5019. }
  5020. }
  5021. },
  5022. search: {
  5023. focus: function() {
  5024. activated = true;
  5025. if(module.is.multiple()) {
  5026. module.remove.activeLabel();
  5027. }
  5028. if(settings.showOnFocus) {
  5029. module.search();
  5030. }
  5031. },
  5032. blur: function(event) {
  5033. pageLostFocus = (document.activeElement === this);
  5034. if(module.is.searchSelection() && !willRefocus) {
  5035. if(!itemActivated && !pageLostFocus) {
  5036. if(settings.forceSelection) {
  5037. module.forceSelection();
  5038. }
  5039. module.hide();
  5040. }
  5041. }
  5042. willRefocus = false;
  5043. }
  5044. },
  5045. icon: {
  5046. click: function(event) {
  5047. if($icon.hasClass(className.clear)) {
  5048. module.clear();
  5049. }
  5050. else if (module.can.click()) {
  5051. module.toggle();
  5052. }
  5053. }
  5054. },
  5055. text: {
  5056. focus: function(event) {
  5057. activated = true;
  5058. module.focusSearch();
  5059. }
  5060. },
  5061. input: function(event) {
  5062. if(module.is.multiple() || module.is.searchSelection()) {
  5063. module.set.filtered();
  5064. }
  5065. clearTimeout(module.timer);
  5066. module.timer = setTimeout(module.search, settings.delay.search);
  5067. },
  5068. label: {
  5069. click: function(event) {
  5070. var
  5071. $label = $(this),
  5072. $labels = $module.find(selector.label),
  5073. $activeLabels = $labels.filter('.' + className.active),
  5074. $nextActive = $label.nextAll('.' + className.active),
  5075. $prevActive = $label.prevAll('.' + className.active),
  5076. $range = ($nextActive.length > 0)
  5077. ? $label.nextUntil($nextActive).add($activeLabels).add($label)
  5078. : $label.prevUntil($prevActive).add($activeLabels).add($label)
  5079. ;
  5080. if(event.shiftKey) {
  5081. $activeLabels.removeClass(className.active);
  5082. $range.addClass(className.active);
  5083. }
  5084. else if(event.ctrlKey) {
  5085. $label.toggleClass(className.active);
  5086. }
  5087. else {
  5088. $activeLabels.removeClass(className.active);
  5089. $label.addClass(className.active);
  5090. }
  5091. settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
  5092. }
  5093. },
  5094. remove: {
  5095. click: function() {
  5096. var
  5097. $label = $(this).parent()
  5098. ;
  5099. if( $label.hasClass(className.active) ) {
  5100. // remove all selected labels
  5101. module.remove.activeLabels();
  5102. }
  5103. else {
  5104. // remove this label only
  5105. module.remove.activeLabels( $label );
  5106. }
  5107. }
  5108. },
  5109. test: {
  5110. toggle: function(event) {
  5111. var
  5112. toggleBehavior = (module.is.multiple())
  5113. ? module.show
  5114. : module.toggle
  5115. ;
  5116. if(module.is.bubbledLabelClick(event) || module.is.bubbledIconClick(event)) {
  5117. return;
  5118. }
  5119. if( module.determine.eventOnElement(event, toggleBehavior) ) {
  5120. event.preventDefault();
  5121. }
  5122. },
  5123. touch: function(event) {
  5124. module.determine.eventOnElement(event, function() {
  5125. if(event.type == 'touchstart') {
  5126. module.timer = setTimeout(function() {
  5127. module.hide();
  5128. }, settings.delay.touch);
  5129. }
  5130. else if(event.type == 'touchmove') {
  5131. clearTimeout(module.timer);
  5132. }
  5133. });
  5134. event.stopPropagation();
  5135. },
  5136. hide: function(event) {
  5137. module.determine.eventInModule(event, module.hide);
  5138. }
  5139. },
  5140. select: {
  5141. mutation: function(mutations) {
  5142. module.debug('<select> modified, recreating menu');
  5143. var
  5144. isSelectMutation = false
  5145. ;
  5146. $.each(mutations, function(index, mutation) {
  5147. if($(mutation.target).is('select') || $(mutation.addedNodes).is('select')) {
  5148. isSelectMutation = true;
  5149. return true;
  5150. }
  5151. });
  5152. if(isSelectMutation) {
  5153. module.disconnect.selectObserver();
  5154. module.refresh();
  5155. module.setup.select();
  5156. module.set.selected();
  5157. module.observe.select();
  5158. }
  5159. }
  5160. },
  5161. menu: {
  5162. mutation: function(mutations) {
  5163. var
  5164. mutation = mutations[0],
  5165. $addedNode = mutation.addedNodes
  5166. ? $(mutation.addedNodes[0])
  5167. : $(false),
  5168. $removedNode = mutation.removedNodes
  5169. ? $(mutation.removedNodes[0])
  5170. : $(false),
  5171. $changedNodes = $addedNode.add($removedNode),
  5172. isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
  5173. isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
  5174. ;
  5175. if(isUserAddition || isMessage) {
  5176. module.debug('Updating item selector cache');
  5177. module.refreshItems();
  5178. }
  5179. else {
  5180. module.debug('Menu modified, updating selector cache');
  5181. module.refresh();
  5182. }
  5183. },
  5184. mousedown: function() {
  5185. itemActivated = true;
  5186. },
  5187. mouseup: function() {
  5188. itemActivated = false;
  5189. }
  5190. },
  5191. item: {
  5192. mouseenter: function(event) {
  5193. var
  5194. $target = $(event.target),
  5195. $item = $(this),
  5196. $subMenu = $item.children(selector.menu),
  5197. $otherMenus = $item.siblings(selector.item).children(selector.menu),
  5198. hasSubMenu = ($subMenu.length > 0),
  5199. isBubbledEvent = ($subMenu.find($target).length > 0)
  5200. ;
  5201. if( !isBubbledEvent && hasSubMenu ) {
  5202. clearTimeout(module.itemTimer);
  5203. module.itemTimer = setTimeout(function() {
  5204. module.verbose('Showing sub-menu', $subMenu);
  5205. $.each($otherMenus, function() {
  5206. module.animate.hide(false, $(this));
  5207. });
  5208. module.animate.show(false, $subMenu);
  5209. }, settings.delay.show);
  5210. event.preventDefault();
  5211. }
  5212. },
  5213. mouseleave: function(event) {
  5214. var
  5215. $subMenu = $(this).children(selector.menu)
  5216. ;
  5217. if($subMenu.length > 0) {
  5218. clearTimeout(module.itemTimer);
  5219. module.itemTimer = setTimeout(function() {
  5220. module.verbose('Hiding sub-menu', $subMenu);
  5221. module.animate.hide(false, $subMenu);
  5222. }, settings.delay.hide);
  5223. }
  5224. },
  5225. click: function (event, skipRefocus) {
  5226. var
  5227. $choice = $(this),
  5228. $target = (event)
  5229. ? $(event.target)
  5230. : $(''),
  5231. $subMenu = $choice.find(selector.menu),
  5232. text = module.get.choiceText($choice),
  5233. value = module.get.choiceValue($choice, text),
  5234. hasSubMenu = ($subMenu.length > 0),
  5235. isBubbledEvent = ($subMenu.find($target).length > 0)
  5236. ;
  5237. // prevents IE11 bug where menu receives focus even though `tabindex=-1`
  5238. if(module.has.menuSearch()) {
  5239. $(document.activeElement).blur();
  5240. }
  5241. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  5242. if(module.is.searchSelection()) {
  5243. if(settings.allowAdditions) {
  5244. module.remove.userAddition();
  5245. }
  5246. module.remove.searchTerm();
  5247. if(!module.is.focusedOnSearch() && !(skipRefocus == true)) {
  5248. module.focusSearch(true);
  5249. }
  5250. }
  5251. if(!settings.useLabels) {
  5252. module.remove.filteredItem();
  5253. module.set.scrollPosition($choice);
  5254. }
  5255. module.determine.selectAction.call(this, text, value);
  5256. }
  5257. }
  5258. },
  5259. document: {
  5260. // label selection should occur even when element has no focus
  5261. keydown: function(event) {
  5262. var
  5263. pressedKey = event.which,
  5264. isShortcutKey = module.is.inObject(pressedKey, keys)
  5265. ;
  5266. if(isShortcutKey) {
  5267. var
  5268. $label = $module.find(selector.label),
  5269. $activeLabel = $label.filter('.' + className.active),
  5270. activeValue = $activeLabel.data(metadata.value),
  5271. labelIndex = $label.index($activeLabel),
  5272. labelCount = $label.length,
  5273. hasActiveLabel = ($activeLabel.length > 0),
  5274. hasMultipleActive = ($activeLabel.length > 1),
  5275. isFirstLabel = (labelIndex === 0),
  5276. isLastLabel = (labelIndex + 1 == labelCount),
  5277. isSearch = module.is.searchSelection(),
  5278. isFocusedOnSearch = module.is.focusedOnSearch(),
  5279. isFocused = module.is.focused(),
  5280. caretAtStart = (isFocusedOnSearch && module.get.caretPosition() === 0),
  5281. $nextLabel
  5282. ;
  5283. if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
  5284. return;
  5285. }
  5286. if(pressedKey == keys.leftArrow) {
  5287. // activate previous label
  5288. if((isFocused || caretAtStart) && !hasActiveLabel) {
  5289. module.verbose('Selecting previous label');
  5290. $label.last().addClass(className.active);
  5291. }
  5292. else if(hasActiveLabel) {
  5293. if(!event.shiftKey) {
  5294. module.verbose('Selecting previous label');
  5295. $label.removeClass(className.active);
  5296. }
  5297. else {
  5298. module.verbose('Adding previous label to selection');
  5299. }
  5300. if(isFirstLabel && !hasMultipleActive) {
  5301. $activeLabel.addClass(className.active);
  5302. }
  5303. else {
  5304. $activeLabel.prev(selector.siblingLabel)
  5305. .addClass(className.active)
  5306. .end()
  5307. ;
  5308. }
  5309. event.preventDefault();
  5310. }
  5311. }
  5312. else if(pressedKey == keys.rightArrow) {
  5313. // activate first label
  5314. if(isFocused && !hasActiveLabel) {
  5315. $label.first().addClass(className.active);
  5316. }
  5317. // activate next label
  5318. if(hasActiveLabel) {
  5319. if(!event.shiftKey) {
  5320. module.verbose('Selecting next label');
  5321. $label.removeClass(className.active);
  5322. }
  5323. else {
  5324. module.verbose('Adding next label to selection');
  5325. }
  5326. if(isLastLabel) {
  5327. if(isSearch) {
  5328. if(!isFocusedOnSearch) {
  5329. module.focusSearch();
  5330. }
  5331. else {
  5332. $label.removeClass(className.active);
  5333. }
  5334. }
  5335. else if(hasMultipleActive) {
  5336. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  5337. }
  5338. else {
  5339. $activeLabel.addClass(className.active);
  5340. }
  5341. }
  5342. else {
  5343. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  5344. }
  5345. event.preventDefault();
  5346. }
  5347. }
  5348. else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
  5349. if(hasActiveLabel) {
  5350. module.verbose('Removing active labels');
  5351. if(isLastLabel) {
  5352. if(isSearch && !isFocusedOnSearch) {
  5353. module.focusSearch();
  5354. }
  5355. }
  5356. $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
  5357. module.remove.activeLabels($activeLabel);
  5358. event.preventDefault();
  5359. }
  5360. else if(caretAtStart && !hasActiveLabel && pressedKey == keys.backspace) {
  5361. module.verbose('Removing last label on input backspace');
  5362. $activeLabel = $label.last().addClass(className.active);
  5363. module.remove.activeLabels($activeLabel);
  5364. }
  5365. }
  5366. else {
  5367. $activeLabel.removeClass(className.active);
  5368. }
  5369. }
  5370. }
  5371. },
  5372. keydown: function(event) {
  5373. var
  5374. pressedKey = event.which,
  5375. isShortcutKey = module.is.inObject(pressedKey, keys)
  5376. ;
  5377. if(isShortcutKey) {
  5378. var
  5379. $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
  5380. $activeItem = $menu.children('.' + className.active).eq(0),
  5381. $selectedItem = ($currentlySelected.length > 0)
  5382. ? $currentlySelected
  5383. : $activeItem,
  5384. $visibleItems = ($selectedItem.length > 0)
  5385. ? $selectedItem.siblings(':not(.' + className.filtered +')').addBack()
  5386. : $menu.children(':not(.' + className.filtered +')'),
  5387. $subMenu = $selectedItem.children(selector.menu),
  5388. $parentMenu = $selectedItem.closest(selector.menu),
  5389. inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
  5390. hasSubMenu = ($subMenu.length> 0),
  5391. hasSelectedItem = ($selectedItem.length > 0),
  5392. selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
  5393. delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
  5394. isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable),
  5395. $nextItem,
  5396. isSubMenuItem,
  5397. newIndex
  5398. ;
  5399. // allow selection with menu closed
  5400. if(isAdditionWithoutMenu) {
  5401. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  5402. module.event.item.click.call($selectedItem, event);
  5403. if(module.is.searchSelection()) {
  5404. module.remove.searchTerm();
  5405. }
  5406. }
  5407. // visible menu keyboard shortcuts
  5408. if( module.is.visible() ) {
  5409. // enter (select or open sub-menu)
  5410. if(pressedKey == keys.enter || delimiterPressed) {
  5411. if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
  5412. module.verbose('Pressed enter on unselectable category, opening sub menu');
  5413. pressedKey = keys.rightArrow;
  5414. }
  5415. else if(selectedIsSelectable) {
  5416. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  5417. module.event.item.click.call($selectedItem, event);
  5418. if(module.is.searchSelection()) {
  5419. module.remove.searchTerm();
  5420. }
  5421. }
  5422. event.preventDefault();
  5423. }
  5424. // sub-menu actions
  5425. if(hasSelectedItem) {
  5426. if(pressedKey == keys.leftArrow) {
  5427. isSubMenuItem = ($parentMenu[0] !== $menu[0]);
  5428. if(isSubMenuItem) {
  5429. module.verbose('Left key pressed, closing sub-menu');
  5430. module.animate.hide(false, $parentMenu);
  5431. $selectedItem
  5432. .removeClass(className.selected)
  5433. ;
  5434. $parentMenu
  5435. .closest(selector.item)
  5436. .addClass(className.selected)
  5437. ;
  5438. event.preventDefault();
  5439. }
  5440. }
  5441. // right arrow (show sub-menu)
  5442. if(pressedKey == keys.rightArrow) {
  5443. if(hasSubMenu) {
  5444. module.verbose('Right key pressed, opening sub-menu');
  5445. module.animate.show(false, $subMenu);
  5446. $selectedItem
  5447. .removeClass(className.selected)
  5448. ;
  5449. $subMenu
  5450. .find(selector.item).eq(0)
  5451. .addClass(className.selected)
  5452. ;
  5453. event.preventDefault();
  5454. }
  5455. }
  5456. }
  5457. // up arrow (traverse menu up)
  5458. if(pressedKey == keys.upArrow) {
  5459. $nextItem = (hasSelectedItem && inVisibleMenu)
  5460. ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  5461. : $item.eq(0)
  5462. ;
  5463. if($visibleItems.index( $nextItem ) < 0) {
  5464. module.verbose('Up key pressed but reached top of current menu');
  5465. event.preventDefault();
  5466. return;
  5467. }
  5468. else {
  5469. module.verbose('Up key pressed, changing active item');
  5470. $selectedItem
  5471. .removeClass(className.selected)
  5472. ;
  5473. $nextItem
  5474. .addClass(className.selected)
  5475. ;
  5476. module.set.scrollPosition($nextItem);
  5477. if(settings.selectOnKeydown && module.is.single()) {
  5478. module.set.selectedItem($nextItem);
  5479. }
  5480. }
  5481. event.preventDefault();
  5482. }
  5483. // down arrow (traverse menu down)
  5484. if(pressedKey == keys.downArrow) {
  5485. $nextItem = (hasSelectedItem && inVisibleMenu)
  5486. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  5487. : $item.eq(0)
  5488. ;
  5489. if($nextItem.length === 0) {
  5490. module.verbose('Down key pressed but reached bottom of current menu');
  5491. event.preventDefault();
  5492. return;
  5493. }
  5494. else {
  5495. module.verbose('Down key pressed, changing active item');
  5496. $item
  5497. .removeClass(className.selected)
  5498. ;
  5499. $nextItem
  5500. .addClass(className.selected)
  5501. ;
  5502. module.set.scrollPosition($nextItem);
  5503. if(settings.selectOnKeydown && module.is.single()) {
  5504. module.set.selectedItem($nextItem);
  5505. }
  5506. }
  5507. event.preventDefault();
  5508. }
  5509. // page down (show next page)
  5510. if(pressedKey == keys.pageUp) {
  5511. module.scrollPage('up');
  5512. event.preventDefault();
  5513. }
  5514. if(pressedKey == keys.pageDown) {
  5515. module.scrollPage('down');
  5516. event.preventDefault();
  5517. }
  5518. // escape (close menu)
  5519. if(pressedKey == keys.escape) {
  5520. module.verbose('Escape key pressed, closing dropdown');
  5521. module.hide();
  5522. }
  5523. }
  5524. else {
  5525. // delimiter key
  5526. if(delimiterPressed) {
  5527. event.preventDefault();
  5528. }
  5529. // down arrow (open menu)
  5530. if(pressedKey == keys.downArrow && !module.is.visible()) {
  5531. module.verbose('Down key pressed, showing dropdown');
  5532. module.show();
  5533. event.preventDefault();
  5534. }
  5535. }
  5536. }
  5537. else {
  5538. if( !module.has.search() ) {
  5539. module.set.selectedLetter( String.fromCharCode(pressedKey) );
  5540. }
  5541. }
  5542. }
  5543. },
  5544. trigger: {
  5545. change: function() {
  5546. var
  5547. events = document.createEvent('HTMLEvents'),
  5548. inputElement = $input[0]
  5549. ;
  5550. if(inputElement) {
  5551. module.verbose('Triggering native change event');
  5552. events.initEvent('change', true, false);
  5553. inputElement.dispatchEvent(events);
  5554. }
  5555. }
  5556. },
  5557. determine: {
  5558. selectAction: function(text, value) {
  5559. module.verbose('Determining action', settings.action);
  5560. if( $.isFunction( module.action[settings.action] ) ) {
  5561. module.verbose('Triggering preset action', settings.action, text, value);
  5562. module.action[ settings.action ].call(element, text, value, this);
  5563. }
  5564. else if( $.isFunction(settings.action) ) {
  5565. module.verbose('Triggering user action', settings.action, text, value);
  5566. settings.action.call(element, text, value, this);
  5567. }
  5568. else {
  5569. module.error(error.action, settings.action);
  5570. }
  5571. },
  5572. eventInModule: function(event, callback) {
  5573. var
  5574. $target = $(event.target),
  5575. inDocument = ($target.closest(document.documentElement).length > 0),
  5576. inModule = ($target.closest($module).length > 0)
  5577. ;
  5578. callback = $.isFunction(callback)
  5579. ? callback
  5580. : function(){}
  5581. ;
  5582. if(inDocument && !inModule) {
  5583. module.verbose('Triggering event', callback);
  5584. callback();
  5585. return true;
  5586. }
  5587. else {
  5588. module.verbose('Event occurred in dropdown, canceling callback');
  5589. return false;
  5590. }
  5591. },
  5592. eventOnElement: function(event, callback) {
  5593. var
  5594. $target = $(event.target),
  5595. $label = $target.closest(selector.siblingLabel),
  5596. inVisibleDOM = document.body.contains(event.target),
  5597. notOnLabel = ($module.find($label).length === 0),
  5598. notInMenu = ($target.closest($menu).length === 0)
  5599. ;
  5600. callback = $.isFunction(callback)
  5601. ? callback
  5602. : function(){}
  5603. ;
  5604. if(inVisibleDOM && notOnLabel && notInMenu) {
  5605. module.verbose('Triggering event', callback);
  5606. callback();
  5607. return true;
  5608. }
  5609. else {
  5610. module.verbose('Event occurred in dropdown menu, canceling callback');
  5611. return false;
  5612. }
  5613. }
  5614. },
  5615. action: {
  5616. nothing: function() {},
  5617. activate: function(text, value, element) {
  5618. value = (value !== undefined)
  5619. ? value
  5620. : text
  5621. ;
  5622. if( module.can.activate( $(element) ) ) {
  5623. module.set.selected(value, $(element));
  5624. if(module.is.multiple() && !module.is.allFiltered()) {
  5625. return;
  5626. }
  5627. else {
  5628. module.hideAndClear();
  5629. }
  5630. }
  5631. },
  5632. select: function(text, value, element) {
  5633. value = (value !== undefined)
  5634. ? value
  5635. : text
  5636. ;
  5637. if( module.can.activate( $(element) ) ) {
  5638. module.set.value(value, text, $(element));
  5639. if(module.is.multiple() && !module.is.allFiltered()) {
  5640. return;
  5641. }
  5642. else {
  5643. module.hideAndClear();
  5644. }
  5645. }
  5646. },
  5647. combo: function(text, value, element) {
  5648. value = (value !== undefined)
  5649. ? value
  5650. : text
  5651. ;
  5652. module.set.selected(value, $(element));
  5653. module.hideAndClear();
  5654. },
  5655. hide: function(text, value, element) {
  5656. module.set.value(value, text, $(element));
  5657. module.hideAndClear();
  5658. }
  5659. },
  5660. get: {
  5661. id: function() {
  5662. return id;
  5663. },
  5664. defaultText: function() {
  5665. return $module.data(metadata.defaultText);
  5666. },
  5667. defaultValue: function() {
  5668. return $module.data(metadata.defaultValue);
  5669. },
  5670. placeholderText: function() {
  5671. if(settings.placeholder != 'auto' && typeof settings.placeholder == 'string') {
  5672. return settings.placeholder;
  5673. }
  5674. return $module.data(metadata.placeholderText) || '';
  5675. },
  5676. text: function() {
  5677. return $text.text();
  5678. },
  5679. query: function() {
  5680. return $.trim($search.val());
  5681. },
  5682. searchWidth: function(value) {
  5683. value = (value !== undefined)
  5684. ? value
  5685. : $search.val()
  5686. ;
  5687. $sizer.text(value);
  5688. // prevent rounding issues
  5689. return Math.ceil( $sizer.width() + 1);
  5690. },
  5691. selectionCount: function() {
  5692. var
  5693. values = module.get.values(),
  5694. count
  5695. ;
  5696. count = ( module.is.multiple() )
  5697. ? $.isArray(values)
  5698. ? values.length
  5699. : 0
  5700. : (module.get.value() !== '')
  5701. ? 1
  5702. : 0
  5703. ;
  5704. return count;
  5705. },
  5706. transition: function($subMenu) {
  5707. return (settings.transition == 'auto')
  5708. ? module.is.upward($subMenu)
  5709. ? 'slide up'
  5710. : 'slide down'
  5711. : settings.transition
  5712. ;
  5713. },
  5714. userValues: function() {
  5715. var
  5716. values = module.get.values()
  5717. ;
  5718. if(!values) {
  5719. return false;
  5720. }
  5721. values = $.isArray(values)
  5722. ? values
  5723. : [values]
  5724. ;
  5725. return $.grep(values, function(value) {
  5726. return (module.get.item(value) === false);
  5727. });
  5728. },
  5729. uniqueArray: function(array) {
  5730. return $.grep(array, function (value, index) {
  5731. return $.inArray(value, array) === index;
  5732. });
  5733. },
  5734. caretPosition: function() {
  5735. var
  5736. input = $search.get(0),
  5737. range,
  5738. rangeLength
  5739. ;
  5740. if('selectionStart' in input) {
  5741. return input.selectionStart;
  5742. }
  5743. else if (document.selection) {
  5744. input.focus();
  5745. range = document.selection.createRange();
  5746. rangeLength = range.text.length;
  5747. range.moveStart('character', -input.value.length);
  5748. return range.text.length - rangeLength;
  5749. }
  5750. },
  5751. value: function() {
  5752. var
  5753. value = ($input.length > 0)
  5754. ? $input.val()
  5755. : $module.data(metadata.value),
  5756. isEmptyMultiselect = ($.isArray(value) && value.length === 1 && value[0] === '')
  5757. ;
  5758. // prevents placeholder element from being selected when multiple
  5759. return (value === undefined || isEmptyMultiselect)
  5760. ? ''
  5761. : value
  5762. ;
  5763. },
  5764. values: function() {
  5765. var
  5766. value = module.get.value()
  5767. ;
  5768. if(value === '') {
  5769. return '';
  5770. }
  5771. return ( !module.has.selectInput() && module.is.multiple() )
  5772. ? (typeof value == 'string') // delimited string
  5773. ? value.split(settings.delimiter)
  5774. : ''
  5775. : value
  5776. ;
  5777. },
  5778. remoteValues: function() {
  5779. var
  5780. values = module.get.values(),
  5781. remoteValues = false
  5782. ;
  5783. if(values) {
  5784. if(typeof values == 'string') {
  5785. values = [values];
  5786. }
  5787. $.each(values, function(index, value) {
  5788. var
  5789. name = module.read.remoteData(value)
  5790. ;
  5791. module.verbose('Restoring value from session data', name, value);
  5792. if(name) {
  5793. if(!remoteValues) {
  5794. remoteValues = {};
  5795. }
  5796. remoteValues[value] = name;
  5797. }
  5798. });
  5799. }
  5800. return remoteValues;
  5801. },
  5802. choiceText: function($choice, preserveHTML) {
  5803. preserveHTML = (preserveHTML !== undefined)
  5804. ? preserveHTML
  5805. : settings.preserveHTML
  5806. ;
  5807. if($choice) {
  5808. if($choice.find(selector.menu).length > 0) {
  5809. module.verbose('Retrieving text of element with sub-menu');
  5810. $choice = $choice.clone();
  5811. $choice.find(selector.menu).remove();
  5812. $choice.find(selector.menuIcon).remove();
  5813. }
  5814. return ($choice.data(metadata.text) !== undefined)
  5815. ? $choice.data(metadata.text)
  5816. : (preserveHTML)
  5817. ? $.trim($choice.html())
  5818. : $.trim($choice.text())
  5819. ;
  5820. }
  5821. },
  5822. choiceValue: function($choice, choiceText) {
  5823. choiceText = choiceText || module.get.choiceText($choice);
  5824. if(!$choice) {
  5825. return false;
  5826. }
  5827. return ($choice.data(metadata.value) !== undefined)
  5828. ? String( $choice.data(metadata.value) )
  5829. : (typeof choiceText === 'string')
  5830. ? $.trim(choiceText.toLowerCase())
  5831. : String(choiceText)
  5832. ;
  5833. },
  5834. inputEvent: function() {
  5835. var
  5836. input = $search[0]
  5837. ;
  5838. if(input) {
  5839. return (input.oninput !== undefined)
  5840. ? 'input'
  5841. : (input.onpropertychange !== undefined)
  5842. ? 'propertychange'
  5843. : 'keyup'
  5844. ;
  5845. }
  5846. return false;
  5847. },
  5848. selectValues: function() {
  5849. var
  5850. select = {}
  5851. ;
  5852. select.values = [];
  5853. $module
  5854. .find('option')
  5855. .each(function() {
  5856. var
  5857. $option = $(this),
  5858. name = $option.html(),
  5859. disabled = $option.attr('disabled'),
  5860. value = ( $option.attr('value') !== undefined )
  5861. ? $option.attr('value')
  5862. : name
  5863. ;
  5864. if(settings.placeholder === 'auto' && value === '') {
  5865. select.placeholder = name;
  5866. }
  5867. else {
  5868. select.values.push({
  5869. name : name,
  5870. value : value,
  5871. disabled : disabled
  5872. });
  5873. }
  5874. })
  5875. ;
  5876. if(settings.placeholder && settings.placeholder !== 'auto') {
  5877. module.debug('Setting placeholder value to', settings.placeholder);
  5878. select.placeholder = settings.placeholder;
  5879. }
  5880. if(settings.sortSelect) {
  5881. select.values.sort(function(a, b) {
  5882. return (a.name > b.name)
  5883. ? 1
  5884. : -1
  5885. ;
  5886. });
  5887. module.debug('Retrieved and sorted values from select', select);
  5888. }
  5889. else {
  5890. module.debug('Retrieved values from select', select);
  5891. }
  5892. return select;
  5893. },
  5894. activeItem: function() {
  5895. return $item.filter('.' + className.active);
  5896. },
  5897. selectedItem: function() {
  5898. var
  5899. $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
  5900. ;
  5901. return ($selectedItem.length > 0)
  5902. ? $selectedItem
  5903. : $item.eq(0)
  5904. ;
  5905. },
  5906. itemWithAdditions: function(value) {
  5907. var
  5908. $items = module.get.item(value),
  5909. $userItems = module.create.userChoice(value),
  5910. hasUserItems = ($userItems && $userItems.length > 0)
  5911. ;
  5912. if(hasUserItems) {
  5913. $items = ($items.length > 0)
  5914. ? $items.add($userItems)
  5915. : $userItems
  5916. ;
  5917. }
  5918. return $items;
  5919. },
  5920. item: function(value, strict) {
  5921. var
  5922. $selectedItem = false,
  5923. shouldSearch,
  5924. isMultiple
  5925. ;
  5926. value = (value !== undefined)
  5927. ? value
  5928. : ( module.get.values() !== undefined)
  5929. ? module.get.values()
  5930. : module.get.text()
  5931. ;
  5932. shouldSearch = (isMultiple)
  5933. ? (value.length > 0)
  5934. : (value !== undefined && value !== null)
  5935. ;
  5936. isMultiple = (module.is.multiple() && $.isArray(value));
  5937. strict = (value === '' || value === 0)
  5938. ? true
  5939. : strict || false
  5940. ;
  5941. if(shouldSearch) {
  5942. $item
  5943. .each(function() {
  5944. var
  5945. $choice = $(this),
  5946. optionText = module.get.choiceText($choice),
  5947. optionValue = module.get.choiceValue($choice, optionText)
  5948. ;
  5949. // safe early exit
  5950. if(optionValue === null || optionValue === undefined) {
  5951. return;
  5952. }
  5953. if(isMultiple) {
  5954. if($.inArray( String(optionValue), value) !== -1 || $.inArray(optionText, value) !== -1) {
  5955. $selectedItem = ($selectedItem)
  5956. ? $selectedItem.add($choice)
  5957. : $choice
  5958. ;
  5959. }
  5960. }
  5961. else if(strict) {
  5962. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  5963. if( optionValue === value || optionText === value) {
  5964. $selectedItem = $choice;
  5965. return true;
  5966. }
  5967. }
  5968. else {
  5969. if( String(optionValue) == String(value) || optionText == value) {
  5970. module.verbose('Found select item by value', optionValue, value);
  5971. $selectedItem = $choice;
  5972. return true;
  5973. }
  5974. }
  5975. })
  5976. ;
  5977. }
  5978. return $selectedItem;
  5979. }
  5980. },
  5981. check: {
  5982. maxSelections: function(selectionCount) {
  5983. if(settings.maxSelections) {
  5984. selectionCount = (selectionCount !== undefined)
  5985. ? selectionCount
  5986. : module.get.selectionCount()
  5987. ;
  5988. if(selectionCount >= settings.maxSelections) {
  5989. module.debug('Maximum selection count reached');
  5990. if(settings.useLabels) {
  5991. $item.addClass(className.filtered);
  5992. module.add.message(message.maxSelections);
  5993. }
  5994. return true;
  5995. }
  5996. else {
  5997. module.verbose('No longer at maximum selection count');
  5998. module.remove.message();
  5999. module.remove.filteredItem();
  6000. if(module.is.searchSelection()) {
  6001. module.filterItems();
  6002. }
  6003. return false;
  6004. }
  6005. }
  6006. return true;
  6007. }
  6008. },
  6009. restore: {
  6010. defaults: function() {
  6011. module.clear();
  6012. module.restore.defaultText();
  6013. module.restore.defaultValue();
  6014. },
  6015. defaultText: function() {
  6016. var
  6017. defaultText = module.get.defaultText(),
  6018. placeholderText = module.get.placeholderText
  6019. ;
  6020. if(defaultText === placeholderText) {
  6021. module.debug('Restoring default placeholder text', defaultText);
  6022. module.set.placeholderText(defaultText);
  6023. }
  6024. else {
  6025. module.debug('Restoring default text', defaultText);
  6026. module.set.text(defaultText);
  6027. }
  6028. },
  6029. placeholderText: function() {
  6030. module.set.placeholderText();
  6031. },
  6032. defaultValue: function() {
  6033. var
  6034. defaultValue = module.get.defaultValue()
  6035. ;
  6036. if(defaultValue !== undefined) {
  6037. module.debug('Restoring default value', defaultValue);
  6038. if(defaultValue !== '') {
  6039. module.set.value(defaultValue);
  6040. module.set.selected();
  6041. }
  6042. else {
  6043. module.remove.activeItem();
  6044. module.remove.selectedItem();
  6045. }
  6046. }
  6047. },
  6048. labels: function() {
  6049. if(settings.allowAdditions) {
  6050. if(!settings.useLabels) {
  6051. module.error(error.labels);
  6052. settings.useLabels = true;
  6053. }
  6054. module.debug('Restoring selected values');
  6055. module.create.userLabels();
  6056. }
  6057. module.check.maxSelections();
  6058. },
  6059. selected: function() {
  6060. module.restore.values();
  6061. if(module.is.multiple()) {
  6062. module.debug('Restoring previously selected values and labels');
  6063. module.restore.labels();
  6064. }
  6065. else {
  6066. module.debug('Restoring previously selected values');
  6067. }
  6068. },
  6069. values: function() {
  6070. // prevents callbacks from occurring on initial load
  6071. module.set.initialLoad();
  6072. if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) {
  6073. module.restore.remoteValues();
  6074. }
  6075. else {
  6076. module.set.selected();
  6077. }
  6078. module.remove.initialLoad();
  6079. },
  6080. remoteValues: function() {
  6081. var
  6082. values = module.get.remoteValues()
  6083. ;
  6084. module.debug('Recreating selected from session data', values);
  6085. if(values) {
  6086. if( module.is.single() ) {
  6087. $.each(values, function(value, name) {
  6088. module.set.text(name);
  6089. });
  6090. }
  6091. else {
  6092. $.each(values, function(value, name) {
  6093. module.add.label(value, name);
  6094. });
  6095. }
  6096. }
  6097. }
  6098. },
  6099. read: {
  6100. remoteData: function(value) {
  6101. var
  6102. name
  6103. ;
  6104. if(window.Storage === undefined) {
  6105. module.error(error.noStorage);
  6106. return;
  6107. }
  6108. name = sessionStorage.getItem(value);
  6109. return (name !== undefined)
  6110. ? name
  6111. : false
  6112. ;
  6113. }
  6114. },
  6115. save: {
  6116. defaults: function() {
  6117. module.save.defaultText();
  6118. module.save.placeholderText();
  6119. module.save.defaultValue();
  6120. },
  6121. defaultValue: function() {
  6122. var
  6123. value = module.get.value()
  6124. ;
  6125. module.verbose('Saving default value as', value);
  6126. $module.data(metadata.defaultValue, value);
  6127. },
  6128. defaultText: function() {
  6129. var
  6130. text = module.get.text()
  6131. ;
  6132. module.verbose('Saving default text as', text);
  6133. $module.data(metadata.defaultText, text);
  6134. },
  6135. placeholderText: function() {
  6136. var
  6137. text
  6138. ;
  6139. if(settings.placeholder !== false && $text.hasClass(className.placeholder)) {
  6140. text = module.get.text();
  6141. module.verbose('Saving placeholder text as', text);
  6142. $module.data(metadata.placeholderText, text);
  6143. }
  6144. },
  6145. remoteData: function(name, value) {
  6146. if(window.Storage === undefined) {
  6147. module.error(error.noStorage);
  6148. return;
  6149. }
  6150. module.verbose('Saving remote data to session storage', value, name);
  6151. sessionStorage.setItem(value, name);
  6152. }
  6153. },
  6154. clear: function() {
  6155. if(module.is.multiple() && settings.useLabels) {
  6156. module.remove.labels();
  6157. }
  6158. else {
  6159. module.remove.activeItem();
  6160. module.remove.selectedItem();
  6161. }
  6162. module.set.placeholderText();
  6163. module.clearValue();
  6164. },
  6165. clearValue: function() {
  6166. module.set.value('');
  6167. },
  6168. scrollPage: function(direction, $selectedItem) {
  6169. var
  6170. $currentItem = $selectedItem || module.get.selectedItem(),
  6171. $menu = $currentItem.closest(selector.menu),
  6172. menuHeight = $menu.outerHeight(),
  6173. currentScroll = $menu.scrollTop(),
  6174. itemHeight = $item.eq(0).outerHeight(),
  6175. itemsPerPage = Math.floor(menuHeight / itemHeight),
  6176. maxScroll = $menu.prop('scrollHeight'),
  6177. newScroll = (direction == 'up')
  6178. ? currentScroll - (itemHeight * itemsPerPage)
  6179. : currentScroll + (itemHeight * itemsPerPage),
  6180. $selectableItem = $item.not(selector.unselectable),
  6181. isWithinRange,
  6182. $nextSelectedItem,
  6183. elementIndex
  6184. ;
  6185. elementIndex = (direction == 'up')
  6186. ? $selectableItem.index($currentItem) - itemsPerPage
  6187. : $selectableItem.index($currentItem) + itemsPerPage
  6188. ;
  6189. isWithinRange = (direction == 'up')
  6190. ? (elementIndex >= 0)
  6191. : (elementIndex < $selectableItem.length)
  6192. ;
  6193. $nextSelectedItem = (isWithinRange)
  6194. ? $selectableItem.eq(elementIndex)
  6195. : (direction == 'up')
  6196. ? $selectableItem.first()
  6197. : $selectableItem.last()
  6198. ;
  6199. if($nextSelectedItem.length > 0) {
  6200. module.debug('Scrolling page', direction, $nextSelectedItem);
  6201. $currentItem
  6202. .removeClass(className.selected)
  6203. ;
  6204. $nextSelectedItem
  6205. .addClass(className.selected)
  6206. ;
  6207. if(settings.selectOnKeydown && module.is.single()) {
  6208. module.set.selectedItem($nextSelectedItem);
  6209. }
  6210. $menu
  6211. .scrollTop(newScroll)
  6212. ;
  6213. }
  6214. },
  6215. set: {
  6216. filtered: function() {
  6217. var
  6218. isMultiple = module.is.multiple(),
  6219. isSearch = module.is.searchSelection(),
  6220. isSearchMultiple = (isMultiple && isSearch),
  6221. searchValue = (isSearch)
  6222. ? module.get.query()
  6223. : '',
  6224. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
  6225. searchWidth = module.get.searchWidth(),
  6226. valueIsSet = searchValue !== ''
  6227. ;
  6228. if(isMultiple && hasSearchValue) {
  6229. module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
  6230. $search.css('width', searchWidth);
  6231. }
  6232. if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
  6233. module.verbose('Hiding placeholder text');
  6234. $text.addClass(className.filtered);
  6235. }
  6236. else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
  6237. module.verbose('Showing placeholder text');
  6238. $text.removeClass(className.filtered);
  6239. }
  6240. },
  6241. empty: function() {
  6242. $module.addClass(className.empty);
  6243. },
  6244. loading: function() {
  6245. $module.addClass(className.loading);
  6246. },
  6247. placeholderText: function(text) {
  6248. text = text || module.get.placeholderText();
  6249. module.debug('Setting placeholder text', text);
  6250. module.set.text(text);
  6251. $text.addClass(className.placeholder);
  6252. },
  6253. tabbable: function() {
  6254. if( module.is.searchSelection() ) {
  6255. module.debug('Added tabindex to searchable dropdown');
  6256. $search
  6257. .val('')
  6258. .attr('tabindex', 0)
  6259. ;
  6260. $menu
  6261. .attr('tabindex', -1)
  6262. ;
  6263. }
  6264. else {
  6265. module.debug('Added tabindex to dropdown');
  6266. if( $module.attr('tabindex') === undefined) {
  6267. $module
  6268. .attr('tabindex', 0)
  6269. ;
  6270. $menu
  6271. .attr('tabindex', -1)
  6272. ;
  6273. }
  6274. }
  6275. },
  6276. initialLoad: function() {
  6277. module.verbose('Setting initial load');
  6278. initialLoad = true;
  6279. },
  6280. activeItem: function($item) {
  6281. if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) {
  6282. $item.addClass(className.filtered);
  6283. }
  6284. else {
  6285. $item.addClass(className.active);
  6286. }
  6287. },
  6288. partialSearch: function(text) {
  6289. var
  6290. length = module.get.query().length
  6291. ;
  6292. $search.val( text.substr(0, length));
  6293. },
  6294. scrollPosition: function($item, forceScroll) {
  6295. var
  6296. edgeTolerance = 5,
  6297. $menu,
  6298. hasActive,
  6299. offset,
  6300. itemHeight,
  6301. itemOffset,
  6302. menuOffset,
  6303. menuScroll,
  6304. menuHeight,
  6305. abovePage,
  6306. belowPage
  6307. ;
  6308. $item = $item || module.get.selectedItem();
  6309. $menu = $item.closest(selector.menu);
  6310. hasActive = ($item && $item.length > 0);
  6311. forceScroll = (forceScroll !== undefined)
  6312. ? forceScroll
  6313. : false
  6314. ;
  6315. if($item && $menu.length > 0 && hasActive) {
  6316. itemOffset = $item.position().top;
  6317. $menu.addClass(className.loading);
  6318. menuScroll = $menu.scrollTop();
  6319. menuOffset = $menu.offset().top;
  6320. itemOffset = $item.offset().top;
  6321. offset = menuScroll - menuOffset + itemOffset;
  6322. if(!forceScroll) {
  6323. menuHeight = $menu.height();
  6324. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  6325. abovePage = ((offset - edgeTolerance) < menuScroll);
  6326. }
  6327. module.debug('Scrolling to active item', offset);
  6328. if(forceScroll || abovePage || belowPage) {
  6329. $menu.scrollTop(offset);
  6330. }
  6331. $menu.removeClass(className.loading);
  6332. }
  6333. },
  6334. text: function(text) {
  6335. if(settings.action !== 'select') {
  6336. if(settings.action == 'combo') {
  6337. module.debug('Changing combo button text', text, $combo);
  6338. if(settings.preserveHTML) {
  6339. $combo.html(text);
  6340. }
  6341. else {
  6342. $combo.text(text);
  6343. }
  6344. }
  6345. else {
  6346. if(text !== module.get.placeholderText()) {
  6347. $text.removeClass(className.placeholder);
  6348. }
  6349. module.debug('Changing text', text, $text);
  6350. $text
  6351. .removeClass(className.filtered)
  6352. ;
  6353. if(settings.preserveHTML) {
  6354. $text.html(text);
  6355. }
  6356. else {
  6357. $text.text(text);
  6358. }
  6359. }
  6360. }
  6361. },
  6362. selectedItem: function($item) {
  6363. var
  6364. value = module.get.choiceValue($item),
  6365. searchText = module.get.choiceText($item, false),
  6366. text = module.get.choiceText($item, true)
  6367. ;
  6368. module.debug('Setting user selection to item', $item);
  6369. module.remove.activeItem();
  6370. module.set.partialSearch(searchText);
  6371. module.set.activeItem($item);
  6372. module.set.selected(value, $item);
  6373. module.set.text(text);
  6374. },
  6375. selectedLetter: function(letter) {
  6376. var
  6377. $selectedItem = $item.filter('.' + className.selected),
  6378. alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter),
  6379. $nextValue = false,
  6380. $nextItem
  6381. ;
  6382. // check next of same letter
  6383. if(alreadySelectedLetter) {
  6384. $nextItem = $selectedItem.nextAll($item).eq(0);
  6385. if( module.has.firstLetter($nextItem, letter) ) {
  6386. $nextValue = $nextItem;
  6387. }
  6388. }
  6389. // check all values
  6390. if(!$nextValue) {
  6391. $item
  6392. .each(function(){
  6393. if(module.has.firstLetter($(this), letter)) {
  6394. $nextValue = $(this);
  6395. return false;
  6396. }
  6397. })
  6398. ;
  6399. }
  6400. // set next value
  6401. if($nextValue) {
  6402. module.verbose('Scrolling to next value with letter', letter);
  6403. module.set.scrollPosition($nextValue);
  6404. $selectedItem.removeClass(className.selected);
  6405. $nextValue.addClass(className.selected);
  6406. if(settings.selectOnKeydown && module.is.single()) {
  6407. module.set.selectedItem($nextValue);
  6408. }
  6409. }
  6410. },
  6411. direction: function($menu) {
  6412. if(settings.direction == 'auto') {
  6413. // reset position
  6414. module.remove.upward();
  6415. if(module.can.openDownward($menu)) {
  6416. module.remove.upward($menu);
  6417. }
  6418. else {
  6419. module.set.upward($menu);
  6420. }
  6421. if(!module.is.leftward($menu) && !module.can.openRightward($menu)) {
  6422. module.set.leftward($menu);
  6423. }
  6424. }
  6425. else if(settings.direction == 'upward') {
  6426. module.set.upward($menu);
  6427. }
  6428. },
  6429. upward: function($currentMenu) {
  6430. var $element = $currentMenu || $module;
  6431. $element.addClass(className.upward);
  6432. },
  6433. leftward: function($currentMenu) {
  6434. var $element = $currentMenu || $menu;
  6435. $element.addClass(className.leftward);
  6436. },
  6437. value: function(value, text, $selected) {
  6438. var
  6439. escapedValue = module.escape.value(value),
  6440. hasInput = ($input.length > 0),
  6441. currentValue = module.get.values(),
  6442. stringValue = (value !== undefined)
  6443. ? String(value)
  6444. : value,
  6445. newValue
  6446. ;
  6447. if(hasInput) {
  6448. if(!settings.allowReselection && stringValue == currentValue) {
  6449. module.verbose('Skipping value update already same value', value, currentValue);
  6450. if(!module.is.initialLoad()) {
  6451. return;
  6452. }
  6453. }
  6454. if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) {
  6455. module.debug('Adding user option', value);
  6456. module.add.optionValue(value);
  6457. }
  6458. module.debug('Updating input value', escapedValue, currentValue);
  6459. internalChange = true;
  6460. $input
  6461. .val(escapedValue)
  6462. ;
  6463. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6464. module.debug('Input native change event ignored on initial load');
  6465. }
  6466. else {
  6467. module.trigger.change();
  6468. }
  6469. internalChange = false;
  6470. }
  6471. else {
  6472. module.verbose('Storing value in metadata', escapedValue, $input);
  6473. if(escapedValue !== currentValue) {
  6474. $module.data(metadata.value, stringValue);
  6475. }
  6476. }
  6477. if(module.is.single() && settings.clearable) {
  6478. // treat undefined or '' as empty
  6479. if(!escapedValue) {
  6480. module.remove.clearable();
  6481. }
  6482. else {
  6483. module.set.clearable();
  6484. }
  6485. }
  6486. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6487. module.verbose('No callback on initial load', settings.onChange);
  6488. }
  6489. else {
  6490. settings.onChange.call(element, value, text, $selected);
  6491. }
  6492. },
  6493. active: function() {
  6494. $module
  6495. .addClass(className.active)
  6496. ;
  6497. },
  6498. multiple: function() {
  6499. $module.addClass(className.multiple);
  6500. },
  6501. visible: function() {
  6502. $module.addClass(className.visible);
  6503. },
  6504. exactly: function(value, $selectedItem) {
  6505. module.debug('Setting selected to exact values');
  6506. module.clear();
  6507. module.set.selected(value, $selectedItem);
  6508. },
  6509. selected: function(value, $selectedItem) {
  6510. var
  6511. isMultiple = module.is.multiple(),
  6512. $userSelectedItem
  6513. ;
  6514. $selectedItem = (settings.allowAdditions)
  6515. ? $selectedItem || module.get.itemWithAdditions(value)
  6516. : $selectedItem || module.get.item(value)
  6517. ;
  6518. if(!$selectedItem) {
  6519. return;
  6520. }
  6521. module.debug('Setting selected menu item to', $selectedItem);
  6522. if(module.is.multiple()) {
  6523. module.remove.searchWidth();
  6524. }
  6525. if(module.is.single()) {
  6526. module.remove.activeItem();
  6527. module.remove.selectedItem();
  6528. }
  6529. else if(settings.useLabels) {
  6530. module.remove.selectedItem();
  6531. }
  6532. // select each item
  6533. $selectedItem
  6534. .each(function() {
  6535. var
  6536. $selected = $(this),
  6537. selectedText = module.get.choiceText($selected),
  6538. selectedValue = module.get.choiceValue($selected, selectedText),
  6539. isFiltered = $selected.hasClass(className.filtered),
  6540. isActive = $selected.hasClass(className.active),
  6541. isUserValue = $selected.hasClass(className.addition),
  6542. shouldAnimate = (isMultiple && $selectedItem.length == 1)
  6543. ;
  6544. if(isMultiple) {
  6545. if(!isActive || isUserValue) {
  6546. if(settings.apiSettings && settings.saveRemoteData) {
  6547. module.save.remoteData(selectedText, selectedValue);
  6548. }
  6549. if(settings.useLabels) {
  6550. module.add.label(selectedValue, selectedText, shouldAnimate);
  6551. module.add.value(selectedValue, selectedText, $selected);
  6552. module.set.activeItem($selected);
  6553. module.filterActive();
  6554. module.select.nextAvailable($selectedItem);
  6555. }
  6556. else {
  6557. module.add.value(selectedValue, selectedText, $selected);
  6558. module.set.text(module.add.variables(message.count));
  6559. module.set.activeItem($selected);
  6560. }
  6561. }
  6562. else if(!isFiltered) {
  6563. module.debug('Selected active value, removing label');
  6564. module.remove.selected(selectedValue);
  6565. }
  6566. }
  6567. else {
  6568. if(settings.apiSettings && settings.saveRemoteData) {
  6569. module.save.remoteData(selectedText, selectedValue);
  6570. }
  6571. module.set.text(selectedText);
  6572. module.set.value(selectedValue, selectedText, $selected);
  6573. $selected
  6574. .addClass(className.active)
  6575. .addClass(className.selected)
  6576. ;
  6577. }
  6578. })
  6579. ;
  6580. },
  6581. clearable: function() {
  6582. $icon.addClass(className.clear);
  6583. },
  6584. },
  6585. add: {
  6586. label: function(value, text, shouldAnimate) {
  6587. var
  6588. $next = module.is.searchSelection()
  6589. ? $search
  6590. : $text,
  6591. escapedValue = module.escape.value(value),
  6592. $label
  6593. ;
  6594. if(settings.ignoreCase) {
  6595. escapedValue = escapedValue.toLowerCase();
  6596. }
  6597. $label = $('<a />')
  6598. .addClass(className.label)
  6599. .attr('data-' + metadata.value, escapedValue)
  6600. .html(templates.label(escapedValue, text))
  6601. ;
  6602. $label = settings.onLabelCreate.call($label, escapedValue, text);
  6603. if(module.has.label(value)) {
  6604. module.debug('User selection already exists, skipping', escapedValue);
  6605. return;
  6606. }
  6607. if(settings.label.variation) {
  6608. $label.addClass(settings.label.variation);
  6609. }
  6610. if(shouldAnimate === true) {
  6611. module.debug('Animating in label', $label);
  6612. $label
  6613. .addClass(className.hidden)
  6614. .insertBefore($next)
  6615. .transition(settings.label.transition, settings.label.duration)
  6616. ;
  6617. }
  6618. else {
  6619. module.debug('Adding selection label', $label);
  6620. $label
  6621. .insertBefore($next)
  6622. ;
  6623. }
  6624. },
  6625. message: function(message) {
  6626. var
  6627. $message = $menu.children(selector.message),
  6628. html = settings.templates.message(module.add.variables(message))
  6629. ;
  6630. if($message.length > 0) {
  6631. $message
  6632. .html(html)
  6633. ;
  6634. }
  6635. else {
  6636. $message = $('<div/>')
  6637. .html(html)
  6638. .addClass(className.message)
  6639. .appendTo($menu)
  6640. ;
  6641. }
  6642. },
  6643. optionValue: function(value) {
  6644. var
  6645. escapedValue = module.escape.value(value),
  6646. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  6647. hasOption = ($option.length > 0)
  6648. ;
  6649. if(hasOption) {
  6650. return;
  6651. }
  6652. // temporarily disconnect observer
  6653. module.disconnect.selectObserver();
  6654. if( module.is.single() ) {
  6655. module.verbose('Removing previous user addition');
  6656. $input.find('option.' + className.addition).remove();
  6657. }
  6658. $('<option/>')
  6659. .prop('value', escapedValue)
  6660. .addClass(className.addition)
  6661. .html(value)
  6662. .appendTo($input)
  6663. ;
  6664. module.verbose('Adding user addition as an <option>', value);
  6665. module.observe.select();
  6666. },
  6667. userSuggestion: function(value) {
  6668. var
  6669. $addition = $menu.children(selector.addition),
  6670. $existingItem = module.get.item(value),
  6671. alreadyHasValue = $existingItem && $existingItem.not(selector.addition).length,
  6672. hasUserSuggestion = $addition.length > 0,
  6673. html
  6674. ;
  6675. if(settings.useLabels && module.has.maxSelections()) {
  6676. return;
  6677. }
  6678. if(value === '' || alreadyHasValue) {
  6679. $addition.remove();
  6680. return;
  6681. }
  6682. if(hasUserSuggestion) {
  6683. $addition
  6684. .data(metadata.value, value)
  6685. .data(metadata.text, value)
  6686. .attr('data-' + metadata.value, value)
  6687. .attr('data-' + metadata.text, value)
  6688. .removeClass(className.filtered)
  6689. ;
  6690. if(!settings.hideAdditions) {
  6691. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  6692. $addition
  6693. .html(html)
  6694. ;
  6695. }
  6696. module.verbose('Replacing user suggestion with new value', $addition);
  6697. }
  6698. else {
  6699. $addition = module.create.userChoice(value);
  6700. $addition
  6701. .prependTo($menu)
  6702. ;
  6703. module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
  6704. }
  6705. if(!settings.hideAdditions || module.is.allFiltered()) {
  6706. $addition
  6707. .addClass(className.selected)
  6708. .siblings()
  6709. .removeClass(className.selected)
  6710. ;
  6711. }
  6712. module.refreshItems();
  6713. },
  6714. variables: function(message, term) {
  6715. var
  6716. hasCount = (message.search('{count}') !== -1),
  6717. hasMaxCount = (message.search('{maxCount}') !== -1),
  6718. hasTerm = (message.search('{term}') !== -1),
  6719. values,
  6720. count,
  6721. query
  6722. ;
  6723. module.verbose('Adding templated variables to message', message);
  6724. if(hasCount) {
  6725. count = module.get.selectionCount();
  6726. message = message.replace('{count}', count);
  6727. }
  6728. if(hasMaxCount) {
  6729. count = module.get.selectionCount();
  6730. message = message.replace('{maxCount}', settings.maxSelections);
  6731. }
  6732. if(hasTerm) {
  6733. query = term || module.get.query();
  6734. message = message.replace('{term}', query);
  6735. }
  6736. return message;
  6737. },
  6738. value: function(addedValue, addedText, $selectedItem) {
  6739. var
  6740. currentValue = module.get.values(),
  6741. newValue
  6742. ;
  6743. if(module.has.value(addedValue)) {
  6744. module.debug('Value already selected');
  6745. return;
  6746. }
  6747. if(addedValue === '') {
  6748. module.debug('Cannot select blank values from multiselect');
  6749. return;
  6750. }
  6751. // extend current array
  6752. if($.isArray(currentValue)) {
  6753. newValue = currentValue.concat([addedValue]);
  6754. newValue = module.get.uniqueArray(newValue);
  6755. }
  6756. else {
  6757. newValue = [addedValue];
  6758. }
  6759. // add values
  6760. if( module.has.selectInput() ) {
  6761. if(module.can.extendSelect()) {
  6762. module.debug('Adding value to select', addedValue, newValue, $input);
  6763. module.add.optionValue(addedValue);
  6764. }
  6765. }
  6766. else {
  6767. newValue = newValue.join(settings.delimiter);
  6768. module.debug('Setting hidden input to delimited value', newValue, $input);
  6769. }
  6770. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6771. module.verbose('Skipping onadd callback on initial load', settings.onAdd);
  6772. }
  6773. else {
  6774. settings.onAdd.call(element, addedValue, addedText, $selectedItem);
  6775. }
  6776. module.set.value(newValue, addedValue, addedText, $selectedItem);
  6777. module.check.maxSelections();
  6778. },
  6779. },
  6780. remove: {
  6781. active: function() {
  6782. $module.removeClass(className.active);
  6783. },
  6784. activeLabel: function() {
  6785. $module.find(selector.label).removeClass(className.active);
  6786. },
  6787. empty: function() {
  6788. $module.removeClass(className.empty);
  6789. },
  6790. loading: function() {
  6791. $module.removeClass(className.loading);
  6792. },
  6793. initialLoad: function() {
  6794. initialLoad = false;
  6795. },
  6796. upward: function($currentMenu) {
  6797. var $element = $currentMenu || $module;
  6798. $element.removeClass(className.upward);
  6799. },
  6800. leftward: function($currentMenu) {
  6801. var $element = $currentMenu || $menu;
  6802. $element.removeClass(className.leftward);
  6803. },
  6804. visible: function() {
  6805. $module.removeClass(className.visible);
  6806. },
  6807. activeItem: function() {
  6808. $item.removeClass(className.active);
  6809. },
  6810. filteredItem: function() {
  6811. if(settings.useLabels && module.has.maxSelections() ) {
  6812. return;
  6813. }
  6814. if(settings.useLabels && module.is.multiple()) {
  6815. $item.not('.' + className.active).removeClass(className.filtered);
  6816. }
  6817. else {
  6818. $item.removeClass(className.filtered);
  6819. }
  6820. module.remove.empty();
  6821. },
  6822. optionValue: function(value) {
  6823. var
  6824. escapedValue = module.escape.value(value),
  6825. $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
  6826. hasOption = ($option.length > 0)
  6827. ;
  6828. if(!hasOption || !$option.hasClass(className.addition)) {
  6829. return;
  6830. }
  6831. // temporarily disconnect observer
  6832. if(selectObserver) {
  6833. selectObserver.disconnect();
  6834. module.verbose('Temporarily disconnecting mutation observer');
  6835. }
  6836. $option.remove();
  6837. module.verbose('Removing user addition as an <option>', escapedValue);
  6838. if(selectObserver) {
  6839. selectObserver.observe($input[0], {
  6840. childList : true,
  6841. subtree : true
  6842. });
  6843. }
  6844. },
  6845. message: function() {
  6846. $menu.children(selector.message).remove();
  6847. },
  6848. searchWidth: function() {
  6849. $search.css('width', '');
  6850. },
  6851. searchTerm: function() {
  6852. module.verbose('Cleared search term');
  6853. $search.val('');
  6854. module.set.filtered();
  6855. },
  6856. userAddition: function() {
  6857. $item.filter(selector.addition).remove();
  6858. },
  6859. selected: function(value, $selectedItem) {
  6860. $selectedItem = (settings.allowAdditions)
  6861. ? $selectedItem || module.get.itemWithAdditions(value)
  6862. : $selectedItem || module.get.item(value)
  6863. ;
  6864. if(!$selectedItem) {
  6865. return false;
  6866. }
  6867. $selectedItem
  6868. .each(function() {
  6869. var
  6870. $selected = $(this),
  6871. selectedText = module.get.choiceText($selected),
  6872. selectedValue = module.get.choiceValue($selected, selectedText)
  6873. ;
  6874. if(module.is.multiple()) {
  6875. if(settings.useLabels) {
  6876. module.remove.value(selectedValue, selectedText, $selected);
  6877. module.remove.label(selectedValue);
  6878. }
  6879. else {
  6880. module.remove.value(selectedValue, selectedText, $selected);
  6881. if(module.get.selectionCount() === 0) {
  6882. module.set.placeholderText();
  6883. }
  6884. else {
  6885. module.set.text(module.add.variables(message.count));
  6886. }
  6887. }
  6888. }
  6889. else {
  6890. module.remove.value(selectedValue, selectedText, $selected);
  6891. }
  6892. $selected
  6893. .removeClass(className.filtered)
  6894. .removeClass(className.active)
  6895. ;
  6896. if(settings.useLabels) {
  6897. $selected.removeClass(className.selected);
  6898. }
  6899. })
  6900. ;
  6901. },
  6902. selectedItem: function() {
  6903. $item.removeClass(className.selected);
  6904. },
  6905. value: function(removedValue, removedText, $removedItem) {
  6906. var
  6907. values = module.get.values(),
  6908. newValue
  6909. ;
  6910. if( module.has.selectInput() ) {
  6911. module.verbose('Input is <select> removing selected option', removedValue);
  6912. newValue = module.remove.arrayValue(removedValue, values);
  6913. module.remove.optionValue(removedValue);
  6914. }
  6915. else {
  6916. module.verbose('Removing from delimited values', removedValue);
  6917. newValue = module.remove.arrayValue(removedValue, values);
  6918. newValue = newValue.join(settings.delimiter);
  6919. }
  6920. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6921. module.verbose('No callback on initial load', settings.onRemove);
  6922. }
  6923. else {
  6924. settings.onRemove.call(element, removedValue, removedText, $removedItem);
  6925. }
  6926. module.set.value(newValue, removedText, $removedItem);
  6927. module.check.maxSelections();
  6928. },
  6929. arrayValue: function(removedValue, values) {
  6930. if( !$.isArray(values) ) {
  6931. values = [values];
  6932. }
  6933. values = $.grep(values, function(value){
  6934. return (removedValue != value);
  6935. });
  6936. module.verbose('Removed value from delimited string', removedValue, values);
  6937. return values;
  6938. },
  6939. label: function(value, shouldAnimate) {
  6940. var
  6941. $labels = $module.find(selector.label),
  6942. $removedLabel = $labels.filter('[data-' + metadata.value + '="' + module.escape.string(value) +'"]')
  6943. ;
  6944. module.verbose('Removing label', $removedLabel);
  6945. $removedLabel.remove();
  6946. },
  6947. activeLabels: function($activeLabels) {
  6948. $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
  6949. module.verbose('Removing active label selections', $activeLabels);
  6950. module.remove.labels($activeLabels);
  6951. },
  6952. labels: function($labels) {
  6953. $labels = $labels || $module.find(selector.label);
  6954. module.verbose('Removing labels', $labels);
  6955. $labels
  6956. .each(function(){
  6957. var
  6958. $label = $(this),
  6959. value = $label.data(metadata.value),
  6960. stringValue = (value !== undefined)
  6961. ? String(value)
  6962. : value,
  6963. isUserValue = module.is.userValue(stringValue)
  6964. ;
  6965. if(settings.onLabelRemove.call($label, value) === false) {
  6966. module.debug('Label remove callback cancelled removal');
  6967. return;
  6968. }
  6969. module.remove.message();
  6970. if(isUserValue) {
  6971. module.remove.value(stringValue);
  6972. module.remove.label(stringValue);
  6973. }
  6974. else {
  6975. // selected will also remove label
  6976. module.remove.selected(stringValue);
  6977. }
  6978. })
  6979. ;
  6980. },
  6981. tabbable: function() {
  6982. if( module.is.searchSelection() ) {
  6983. module.debug('Searchable dropdown initialized');
  6984. $search
  6985. .removeAttr('tabindex')
  6986. ;
  6987. $menu
  6988. .removeAttr('tabindex')
  6989. ;
  6990. }
  6991. else {
  6992. module.debug('Simple selection dropdown initialized');
  6993. $module
  6994. .removeAttr('tabindex')
  6995. ;
  6996. $menu
  6997. .removeAttr('tabindex')
  6998. ;
  6999. }
  7000. },
  7001. clearable: function() {
  7002. $icon.removeClass(className.clear);
  7003. }
  7004. },
  7005. has: {
  7006. menuSearch: function() {
  7007. return (module.has.search() && $search.closest($menu).length > 0);
  7008. },
  7009. search: function() {
  7010. return ($search.length > 0);
  7011. },
  7012. sizer: function() {
  7013. return ($sizer.length > 0);
  7014. },
  7015. selectInput: function() {
  7016. return ( $input.is('select') );
  7017. },
  7018. minCharacters: function(searchTerm) {
  7019. if(settings.minCharacters) {
  7020. searchTerm = (searchTerm !== undefined)
  7021. ? String(searchTerm)
  7022. : String(module.get.query())
  7023. ;
  7024. return (searchTerm.length >= settings.minCharacters);
  7025. }
  7026. return true;
  7027. },
  7028. firstLetter: function($item, letter) {
  7029. var
  7030. text,
  7031. firstLetter
  7032. ;
  7033. if(!$item || $item.length === 0 || typeof letter !== 'string') {
  7034. return false;
  7035. }
  7036. text = module.get.choiceText($item, false);
  7037. letter = letter.toLowerCase();
  7038. firstLetter = String(text).charAt(0).toLowerCase();
  7039. return (letter == firstLetter);
  7040. },
  7041. input: function() {
  7042. return ($input.length > 0);
  7043. },
  7044. items: function() {
  7045. return ($item.length > 0);
  7046. },
  7047. menu: function() {
  7048. return ($menu.length > 0);
  7049. },
  7050. message: function() {
  7051. return ($menu.children(selector.message).length !== 0);
  7052. },
  7053. label: function(value) {
  7054. var
  7055. escapedValue = module.escape.value(value),
  7056. $labels = $module.find(selector.label)
  7057. ;
  7058. if(settings.ignoreCase) {
  7059. escapedValue = escapedValue.toLowerCase();
  7060. }
  7061. return ($labels.filter('[data-' + metadata.value + '="' + module.escape.string(escapedValue) +'"]').length > 0);
  7062. },
  7063. maxSelections: function() {
  7064. return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
  7065. },
  7066. allResultsFiltered: function() {
  7067. var
  7068. $normalResults = $item.not(selector.addition)
  7069. ;
  7070. return ($normalResults.filter(selector.unselectable).length === $normalResults.length);
  7071. },
  7072. userSuggestion: function() {
  7073. return ($menu.children(selector.addition).length > 0);
  7074. },
  7075. query: function() {
  7076. return (module.get.query() !== '');
  7077. },
  7078. value: function(value) {
  7079. return (settings.ignoreCase)
  7080. ? module.has.valueIgnoringCase(value)
  7081. : module.has.valueMatchingCase(value)
  7082. ;
  7083. },
  7084. valueMatchingCase: function(value) {
  7085. var
  7086. values = module.get.values(),
  7087. hasValue = $.isArray(values)
  7088. ? values && ($.inArray(value, values) !== -1)
  7089. : (values == value)
  7090. ;
  7091. return (hasValue)
  7092. ? true
  7093. : false
  7094. ;
  7095. },
  7096. valueIgnoringCase: function(value) {
  7097. var
  7098. values = module.get.values(),
  7099. hasValue = false
  7100. ;
  7101. if(!$.isArray(values)) {
  7102. values = [values];
  7103. }
  7104. $.each(values, function(index, existingValue) {
  7105. if(String(value).toLowerCase() == String(existingValue).toLowerCase()) {
  7106. hasValue = true;
  7107. return false;
  7108. }
  7109. });
  7110. return hasValue;
  7111. }
  7112. },
  7113. is: {
  7114. active: function() {
  7115. return $module.hasClass(className.active);
  7116. },
  7117. animatingInward: function() {
  7118. return $menu.transition('is inward');
  7119. },
  7120. animatingOutward: function() {
  7121. return $menu.transition('is outward');
  7122. },
  7123. bubbledLabelClick: function(event) {
  7124. return $(event.target).is('select, input') && $module.closest('label').length > 0;
  7125. },
  7126. bubbledIconClick: function(event) {
  7127. return $(event.target).closest($icon).length > 0;
  7128. },
  7129. alreadySetup: function() {
  7130. return ($module.is('select') && $module.parent(selector.dropdown).data(moduleNamespace) !== undefined && $module.prev().length === 0);
  7131. },
  7132. animating: function($subMenu) {
  7133. return ($subMenu)
  7134. ? $subMenu.transition && $subMenu.transition('is animating')
  7135. : $menu.transition && $menu.transition('is animating')
  7136. ;
  7137. },
  7138. leftward: function($subMenu) {
  7139. var $selectedMenu = $subMenu || $menu;
  7140. return $selectedMenu.hasClass(className.leftward);
  7141. },
  7142. disabled: function() {
  7143. return $module.hasClass(className.disabled);
  7144. },
  7145. focused: function() {
  7146. return (document.activeElement === $module[0]);
  7147. },
  7148. focusedOnSearch: function() {
  7149. return (document.activeElement === $search[0]);
  7150. },
  7151. allFiltered: function() {
  7152. return( (module.is.multiple() || module.has.search()) && !(settings.hideAdditions == false && module.has.userSuggestion()) && !module.has.message() && module.has.allResultsFiltered() );
  7153. },
  7154. hidden: function($subMenu) {
  7155. return !module.is.visible($subMenu);
  7156. },
  7157. initialLoad: function() {
  7158. return initialLoad;
  7159. },
  7160. inObject: function(needle, object) {
  7161. var
  7162. found = false
  7163. ;
  7164. $.each(object, function(index, property) {
  7165. if(property == needle) {
  7166. found = true;
  7167. return true;
  7168. }
  7169. });
  7170. return found;
  7171. },
  7172. multiple: function() {
  7173. return $module.hasClass(className.multiple);
  7174. },
  7175. remote: function() {
  7176. return settings.apiSettings && module.can.useAPI();
  7177. },
  7178. single: function() {
  7179. return !module.is.multiple();
  7180. },
  7181. selectMutation: function(mutations) {
  7182. var
  7183. selectChanged = false
  7184. ;
  7185. $.each(mutations, function(index, mutation) {
  7186. if(mutation.target && $(mutation.target).is('select')) {
  7187. selectChanged = true;
  7188. return true;
  7189. }
  7190. });
  7191. return selectChanged;
  7192. },
  7193. search: function() {
  7194. return $module.hasClass(className.search);
  7195. },
  7196. searchSelection: function() {
  7197. return ( module.has.search() && $search.parent(selector.dropdown).length === 1 );
  7198. },
  7199. selection: function() {
  7200. return $module.hasClass(className.selection);
  7201. },
  7202. userValue: function(value) {
  7203. return ($.inArray(value, module.get.userValues()) !== -1);
  7204. },
  7205. upward: function($menu) {
  7206. var $element = $menu || $module;
  7207. return $element.hasClass(className.upward);
  7208. },
  7209. visible: function($subMenu) {
  7210. return ($subMenu)
  7211. ? $subMenu.hasClass(className.visible)
  7212. : $menu.hasClass(className.visible)
  7213. ;
  7214. },
  7215. verticallyScrollableContext: function() {
  7216. var
  7217. overflowY = ($context.get(0) !== window)
  7218. ? $context.css('overflow-y')
  7219. : false
  7220. ;
  7221. return (overflowY == 'auto' || overflowY == 'scroll');
  7222. },
  7223. horizontallyScrollableContext: function() {
  7224. var
  7225. overflowX = ($context.get(0) !== window)
  7226. ? $context.css('overflow-X')
  7227. : false
  7228. ;
  7229. return (overflowX == 'auto' || overflowX == 'scroll');
  7230. }
  7231. },
  7232. can: {
  7233. activate: function($item) {
  7234. if(settings.useLabels) {
  7235. return true;
  7236. }
  7237. if(!module.has.maxSelections()) {
  7238. return true;
  7239. }
  7240. if(module.has.maxSelections() && $item.hasClass(className.active)) {
  7241. return true;
  7242. }
  7243. return false;
  7244. },
  7245. openDownward: function($subMenu) {
  7246. var
  7247. $currentMenu = $subMenu || $menu,
  7248. canOpenDownward = true,
  7249. onScreen = {},
  7250. calculations
  7251. ;
  7252. $currentMenu
  7253. .addClass(className.loading)
  7254. ;
  7255. calculations = {
  7256. context: {
  7257. offset : ($context.get(0) === window)
  7258. ? { top: 0, left: 0}
  7259. : $context.offset(),
  7260. scrollTop : $context.scrollTop(),
  7261. height : $context.outerHeight()
  7262. },
  7263. menu : {
  7264. offset: $currentMenu.offset(),
  7265. height: $currentMenu.outerHeight()
  7266. }
  7267. };
  7268. if(module.is.verticallyScrollableContext()) {
  7269. calculations.menu.offset.top += calculations.context.scrollTop;
  7270. }
  7271. onScreen = {
  7272. above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.context.offset.top - calculations.menu.height,
  7273. below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top - calculations.context.offset.top + calculations.menu.height
  7274. };
  7275. if(onScreen.below) {
  7276. module.verbose('Dropdown can fit in context downward', onScreen);
  7277. canOpenDownward = true;
  7278. }
  7279. else if(!onScreen.below && !onScreen.above) {
  7280. module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
  7281. canOpenDownward = true;
  7282. }
  7283. else {
  7284. module.verbose('Dropdown cannot fit below, opening upward', onScreen);
  7285. canOpenDownward = false;
  7286. }
  7287. $currentMenu.removeClass(className.loading);
  7288. return canOpenDownward;
  7289. },
  7290. openRightward: function($subMenu) {
  7291. var
  7292. $currentMenu = $subMenu || $menu,
  7293. canOpenRightward = true,
  7294. isOffscreenRight = false,
  7295. calculations
  7296. ;
  7297. $currentMenu
  7298. .addClass(className.loading)
  7299. ;
  7300. calculations = {
  7301. context: {
  7302. offset : ($context.get(0) === window)
  7303. ? { top: 0, left: 0}
  7304. : $context.offset(),
  7305. scrollLeft : $context.scrollLeft(),
  7306. width : $context.outerWidth()
  7307. },
  7308. menu: {
  7309. offset : $currentMenu.offset(),
  7310. width : $currentMenu.outerWidth()
  7311. }
  7312. };
  7313. if(module.is.horizontallyScrollableContext()) {
  7314. calculations.menu.offset.left += calculations.context.scrollLeft;
  7315. }
  7316. isOffscreenRight = (calculations.menu.offset.left - calculations.context.offset.left + calculations.menu.width >= calculations.context.scrollLeft + calculations.context.width);
  7317. if(isOffscreenRight) {
  7318. module.verbose('Dropdown cannot fit in context rightward', isOffscreenRight);
  7319. canOpenRightward = false;
  7320. }
  7321. $currentMenu.removeClass(className.loading);
  7322. return canOpenRightward;
  7323. },
  7324. click: function() {
  7325. return (hasTouch || settings.on == 'click');
  7326. },
  7327. extendSelect: function() {
  7328. return settings.allowAdditions || settings.apiSettings;
  7329. },
  7330. show: function() {
  7331. return !module.is.disabled() && (module.has.items() || module.has.message());
  7332. },
  7333. useAPI: function() {
  7334. return $.fn.api !== undefined;
  7335. }
  7336. },
  7337. animate: {
  7338. show: function(callback, $subMenu) {
  7339. var
  7340. $currentMenu = $subMenu || $menu,
  7341. start = ($subMenu)
  7342. ? function() {}
  7343. : function() {
  7344. module.hideSubMenus();
  7345. module.hideOthers();
  7346. module.set.active();
  7347. },
  7348. transition
  7349. ;
  7350. callback = $.isFunction(callback)
  7351. ? callback
  7352. : function(){}
  7353. ;
  7354. module.verbose('Doing menu show animation', $currentMenu);
  7355. module.set.direction($subMenu);
  7356. transition = module.get.transition($subMenu);
  7357. if( module.is.selection() ) {
  7358. module.set.scrollPosition(module.get.selectedItem(), true);
  7359. }
  7360. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  7361. if(transition == 'none') {
  7362. start();
  7363. $currentMenu.transition('show');
  7364. callback.call(element);
  7365. }
  7366. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  7367. $currentMenu
  7368. .transition({
  7369. animation : transition + ' in',
  7370. debug : settings.debug,
  7371. verbose : settings.verbose,
  7372. duration : settings.duration,
  7373. queue : true,
  7374. onStart : start,
  7375. onComplete : function() {
  7376. callback.call(element);
  7377. }
  7378. })
  7379. ;
  7380. }
  7381. else {
  7382. module.error(error.noTransition, transition);
  7383. }
  7384. }
  7385. },
  7386. hide: function(callback, $subMenu) {
  7387. var
  7388. $currentMenu = $subMenu || $menu,
  7389. duration = ($subMenu)
  7390. ? (settings.duration * 0.9)
  7391. : settings.duration,
  7392. start = ($subMenu)
  7393. ? function() {}
  7394. : function() {
  7395. if( module.can.click() ) {
  7396. module.unbind.intent();
  7397. }
  7398. module.remove.active();
  7399. },
  7400. transition = module.get.transition($subMenu)
  7401. ;
  7402. callback = $.isFunction(callback)
  7403. ? callback
  7404. : function(){}
  7405. ;
  7406. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  7407. module.verbose('Doing menu hide animation', $currentMenu);
  7408. if(transition == 'none') {
  7409. start();
  7410. $currentMenu.transition('hide');
  7411. callback.call(element);
  7412. }
  7413. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  7414. $currentMenu
  7415. .transition({
  7416. animation : transition + ' out',
  7417. duration : settings.duration,
  7418. debug : settings.debug,
  7419. verbose : settings.verbose,
  7420. queue : false,
  7421. onStart : start,
  7422. onComplete : function() {
  7423. callback.call(element);
  7424. }
  7425. })
  7426. ;
  7427. }
  7428. else {
  7429. module.error(error.transition);
  7430. }
  7431. }
  7432. }
  7433. },
  7434. hideAndClear: function() {
  7435. module.remove.searchTerm();
  7436. if( module.has.maxSelections() ) {
  7437. return;
  7438. }
  7439. if(module.has.search()) {
  7440. module.hide(function() {
  7441. module.remove.filteredItem();
  7442. });
  7443. }
  7444. else {
  7445. module.hide();
  7446. }
  7447. },
  7448. delay: {
  7449. show: function() {
  7450. module.verbose('Delaying show event to ensure user intent');
  7451. clearTimeout(module.timer);
  7452. module.timer = setTimeout(module.show, settings.delay.show);
  7453. },
  7454. hide: function() {
  7455. module.verbose('Delaying hide event to ensure user intent');
  7456. clearTimeout(module.timer);
  7457. module.timer = setTimeout(module.hide, settings.delay.hide);
  7458. }
  7459. },
  7460. escape: {
  7461. value: function(value) {
  7462. var
  7463. multipleValues = $.isArray(value),
  7464. stringValue = (typeof value === 'string'),
  7465. isUnparsable = (!stringValue && !multipleValues),
  7466. hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
  7467. values = []
  7468. ;
  7469. if(isUnparsable || !hasQuotes) {
  7470. return value;
  7471. }
  7472. module.debug('Encoding quote values for use in select', value);
  7473. if(multipleValues) {
  7474. $.each(value, function(index, value){
  7475. values.push(value.replace(regExp.quote, '&quot;'));
  7476. });
  7477. return values;
  7478. }
  7479. return value.replace(regExp.quote, '&quot;');
  7480. },
  7481. string: function(text) {
  7482. text = String(text);
  7483. return text.replace(regExp.escape, '\\$&');
  7484. }
  7485. },
  7486. setting: function(name, value) {
  7487. module.debug('Changing setting', name, value);
  7488. if( $.isPlainObject(name) ) {
  7489. $.extend(true, settings, name);
  7490. }
  7491. else if(value !== undefined) {
  7492. if($.isPlainObject(settings[name])) {
  7493. $.extend(true, settings[name], value);
  7494. }
  7495. else {
  7496. settings[name] = value;
  7497. }
  7498. }
  7499. else {
  7500. return settings[name];
  7501. }
  7502. },
  7503. internal: function(name, value) {
  7504. if( $.isPlainObject(name) ) {
  7505. $.extend(true, module, name);
  7506. }
  7507. else if(value !== undefined) {
  7508. module[name] = value;
  7509. }
  7510. else {
  7511. return module[name];
  7512. }
  7513. },
  7514. debug: function() {
  7515. if(!settings.silent && settings.debug) {
  7516. if(settings.performance) {
  7517. module.performance.log(arguments);
  7518. }
  7519. else {
  7520. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7521. module.debug.apply(console, arguments);
  7522. }
  7523. }
  7524. },
  7525. verbose: function() {
  7526. if(!settings.silent && settings.verbose && settings.debug) {
  7527. if(settings.performance) {
  7528. module.performance.log(arguments);
  7529. }
  7530. else {
  7531. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7532. module.verbose.apply(console, arguments);
  7533. }
  7534. }
  7535. },
  7536. error: function() {
  7537. if(!settings.silent) {
  7538. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  7539. module.error.apply(console, arguments);
  7540. }
  7541. },
  7542. performance: {
  7543. log: function(message) {
  7544. var
  7545. currentTime,
  7546. executionTime,
  7547. previousTime
  7548. ;
  7549. if(settings.performance) {
  7550. currentTime = new Date().getTime();
  7551. previousTime = time || currentTime;
  7552. executionTime = currentTime - previousTime;
  7553. time = currentTime;
  7554. performance.push({
  7555. 'Name' : message[0],
  7556. 'Arguments' : [].slice.call(message, 1) || '',
  7557. 'Element' : element,
  7558. 'Execution Time' : executionTime
  7559. });
  7560. }
  7561. clearTimeout(module.performance.timer);
  7562. module.performance.timer = setTimeout(module.performance.display, 500);
  7563. },
  7564. display: function() {
  7565. var
  7566. title = settings.name + ':',
  7567. totalTime = 0
  7568. ;
  7569. time = false;
  7570. clearTimeout(module.performance.timer);
  7571. $.each(performance, function(index, data) {
  7572. totalTime += data['Execution Time'];
  7573. });
  7574. title += ' ' + totalTime + 'ms';
  7575. if(moduleSelector) {
  7576. title += ' \'' + moduleSelector + '\'';
  7577. }
  7578. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  7579. console.groupCollapsed(title);
  7580. if(console.table) {
  7581. console.table(performance);
  7582. }
  7583. else {
  7584. $.each(performance, function(index, data) {
  7585. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  7586. });
  7587. }
  7588. console.groupEnd();
  7589. }
  7590. performance = [];
  7591. }
  7592. },
  7593. invoke: function(query, passedArguments, context) {
  7594. var
  7595. object = instance,
  7596. maxDepth,
  7597. found,
  7598. response
  7599. ;
  7600. passedArguments = passedArguments || queryArguments;
  7601. context = element || context;
  7602. if(typeof query == 'string' && object !== undefined) {
  7603. query = query.split(/[\. ]/);
  7604. maxDepth = query.length - 1;
  7605. $.each(query, function(depth, value) {
  7606. var camelCaseValue = (depth != maxDepth)
  7607. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  7608. : query
  7609. ;
  7610. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  7611. object = object[camelCaseValue];
  7612. }
  7613. else if( object[camelCaseValue] !== undefined ) {
  7614. found = object[camelCaseValue];
  7615. return false;
  7616. }
  7617. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  7618. object = object[value];
  7619. }
  7620. else if( object[value] !== undefined ) {
  7621. found = object[value];
  7622. return false;
  7623. }
  7624. else {
  7625. module.error(error.method, query);
  7626. return false;
  7627. }
  7628. });
  7629. }
  7630. if ( $.isFunction( found ) ) {
  7631. response = found.apply(context, passedArguments);
  7632. }
  7633. else if(found !== undefined) {
  7634. response = found;
  7635. }
  7636. if($.isArray(returnedValue)) {
  7637. returnedValue.push(response);
  7638. }
  7639. else if(returnedValue !== undefined) {
  7640. returnedValue = [returnedValue, response];
  7641. }
  7642. else if(response !== undefined) {
  7643. returnedValue = response;
  7644. }
  7645. return found;
  7646. }
  7647. };
  7648. if(methodInvoked) {
  7649. if(instance === undefined) {
  7650. module.initialize();
  7651. }
  7652. module.invoke(query);
  7653. }
  7654. else {
  7655. if(instance !== undefined) {
  7656. instance.invoke('destroy');
  7657. }
  7658. module.initialize();
  7659. }
  7660. })
  7661. ;
  7662. return (returnedValue !== undefined)
  7663. ? returnedValue
  7664. : $allModules
  7665. ;
  7666. };
  7667. $.fn.dropdown.settings = {
  7668. silent : false,
  7669. debug : false,
  7670. verbose : false,
  7671. performance : true,
  7672. on : 'click', // what event should show menu action on item selection
  7673. action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
  7674. values : false, // specify values to use for dropdown
  7675. clearable : false, // whether the value of the dropdown can be cleared
  7676. apiSettings : false,
  7677. selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
  7678. minCharacters : 0, // Minimum characters required to trigger API call
  7679. filterRemoteData : false, // Whether API results should be filtered after being returned for query term
  7680. saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
  7681. throttle : 200, // How long to wait after last user input to search remotely
  7682. context : window, // Context to use when determining if on screen
  7683. direction : 'auto', // Whether dropdown should always open in one direction
  7684. keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
  7685. match : 'both', // what to match against with search selection (both, text, or label)
  7686. fullTextSearch : false, // search anywhere in value (set to 'exact' to require exact matches)
  7687. placeholder : 'auto', // whether to convert blank <select> values to placeholder text
  7688. preserveHTML : true, // preserve html when selecting value
  7689. sortSelect : false, // sort selection on init
  7690. forceSelection : true, // force a choice on blur with search selection
  7691. allowAdditions : false, // whether multiple select should allow user added values
  7692. ignoreCase : false, // whether to consider values not matching in case to be the same
  7693. hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
  7694. maxSelections : false, // When set to a number limits the number of selections to this count
  7695. useLabels : true, // whether multiple select should filter currently active selections from choices
  7696. delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
  7697. showOnFocus : true, // show menu on focus
  7698. allowReselection : false, // whether current value should trigger callbacks when reselected
  7699. allowTab : true, // add tabindex to element
  7700. allowCategorySelection : false, // allow elements with sub-menus to be selected
  7701. fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
  7702. transition : 'auto', // auto transition will slide down or up based on direction
  7703. duration : 200, // duration of transition
  7704. glyphWidth : 1.037, // widest glyph width in em (W is 1.037 em) used to calculate multiselect input width
  7705. // label settings on multi-select
  7706. label: {
  7707. transition : 'scale',
  7708. duration : 200,
  7709. variation : false
  7710. },
  7711. // delay before event
  7712. delay : {
  7713. hide : 300,
  7714. show : 200,
  7715. search : 20,
  7716. touch : 50
  7717. },
  7718. /* Callbacks */
  7719. onChange : function(value, text, $selected){},
  7720. onAdd : function(value, text, $selected){},
  7721. onRemove : function(value, text, $selected){},
  7722. onLabelSelect : function($selectedLabels){},
  7723. onLabelCreate : function(value, text) { return $(this); },
  7724. onLabelRemove : function(value) { return true; },
  7725. onNoResults : function(searchTerm) { return true; },
  7726. onShow : function(){},
  7727. onHide : function(){},
  7728. /* Component */
  7729. name : 'Dropdown',
  7730. namespace : 'dropdown',
  7731. message: {
  7732. addResult : 'Add <b>{term}</b>',
  7733. count : '{count} selected',
  7734. maxSelections : 'Max {maxCount} selections',
  7735. noResults : 'No results found.',
  7736. serverError : 'There was an error contacting the server'
  7737. },
  7738. error : {
  7739. action : 'You called a dropdown action that was not defined',
  7740. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  7741. labels : 'Allowing user additions currently requires the use of labels.',
  7742. missingMultiple : '<select> requires multiple property to be set to correctly preserve multiple values',
  7743. method : 'The method you called is not defined.',
  7744. noAPI : 'The API module is required to load resources remotely',
  7745. noStorage : 'Saving remote data requires session storage',
  7746. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>'
  7747. },
  7748. regExp : {
  7749. escape : /[-[\]{}()*+?.,\\^$|#\s]/g,
  7750. quote : /"/g
  7751. },
  7752. metadata : {
  7753. defaultText : 'defaultText',
  7754. defaultValue : 'defaultValue',
  7755. placeholderText : 'placeholder',
  7756. text : 'text',
  7757. value : 'value'
  7758. },
  7759. // property names for remote query
  7760. fields: {
  7761. remoteValues : 'results', // grouping for api results
  7762. values : 'values', // grouping for all dropdown values
  7763. disabled : 'disabled', // whether value should be disabled
  7764. name : 'name', // displayed dropdown text
  7765. value : 'value', // actual dropdown value
  7766. text : 'text' // displayed text when selected
  7767. },
  7768. keys : {
  7769. backspace : 8,
  7770. delimiter : 188, // comma
  7771. deleteKey : 46,
  7772. enter : 13,
  7773. escape : 27,
  7774. pageUp : 33,
  7775. pageDown : 34,
  7776. leftArrow : 37,
  7777. upArrow : 38,
  7778. rightArrow : 39,
  7779. downArrow : 40
  7780. },
  7781. selector : {
  7782. addition : '.addition',
  7783. dropdown : '.ui.dropdown',
  7784. hidden : '.hidden',
  7785. icon : '> .dropdown.icon',
  7786. input : '> input[type="hidden"], > select',
  7787. item : '.item',
  7788. label : '> .label',
  7789. remove : '> .label > .delete.icon',
  7790. siblingLabel : '.label',
  7791. menu : '.menu',
  7792. message : '.message',
  7793. menuIcon : '.dropdown.icon',
  7794. search : 'input.search, .menu > .search > input, .menu input.search',
  7795. sizer : '> input.sizer',
  7796. text : '> .text:not(.icon)',
  7797. unselectable : '.disabled, .filtered'
  7798. },
  7799. className : {
  7800. active : 'active',
  7801. addition : 'addition',
  7802. animating : 'animating',
  7803. clear : 'clear',
  7804. disabled : 'disabled',
  7805. empty : 'empty',
  7806. dropdown : 'ui dropdown',
  7807. filtered : 'filtered',
  7808. hidden : 'hidden transition',
  7809. item : 'item',
  7810. label : 'ui label',
  7811. loading : 'loading',
  7812. menu : 'menu',
  7813. message : 'message',
  7814. multiple : 'multiple',
  7815. placeholder : 'default',
  7816. sizer : 'sizer',
  7817. search : 'search',
  7818. selected : 'selected',
  7819. selection : 'selection',
  7820. upward : 'upward',
  7821. leftward : 'left',
  7822. visible : 'visible'
  7823. }
  7824. };
  7825. /* Templates */
  7826. $.fn.dropdown.settings.templates = {
  7827. // generates dropdown from select values
  7828. dropdown: function(select) {
  7829. var
  7830. placeholder = select.placeholder || false,
  7831. values = select.values || {},
  7832. html = ''
  7833. ;
  7834. html += '<i class="dropdown icon"></i>';
  7835. if(select.placeholder) {
  7836. html += '<div class="default text">' + placeholder + '</div>';
  7837. }
  7838. else {
  7839. html += '<div class="text"></div>';
  7840. }
  7841. html += '<div class="menu">';
  7842. $.each(select.values, function(index, option) {
  7843. html += (option.disabled)
  7844. ? '<div class="disabled item" data-value="' + option.value + '">' + option.name + '</div>'
  7845. : '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'
  7846. ;
  7847. });
  7848. html += '</div>';
  7849. return html;
  7850. },
  7851. // generates just menu from select
  7852. menu: function(response, fields) {
  7853. var
  7854. values = response[fields.values] || {},
  7855. html = ''
  7856. ;
  7857. $.each(values, function(index, option) {
  7858. var
  7859. maybeText = (option[fields.text])
  7860. ? 'data-text="' + option[fields.text] + '"'
  7861. : '',
  7862. maybeDisabled = (option[fields.disabled])
  7863. ? 'disabled '
  7864. : ''
  7865. ;
  7866. html += '<div class="'+ maybeDisabled +'item" data-value="' + option[fields.value] + '"' + maybeText + '>';
  7867. html += option[fields.name];
  7868. html += '</div>';
  7869. });
  7870. return html;
  7871. },
  7872. // generates label for multiselect
  7873. label: function(value, text) {
  7874. return text + '<i class="delete icon"></i>';
  7875. },
  7876. // generates messages like "No results"
  7877. message: function(message) {
  7878. return message;
  7879. },
  7880. // generates user addition to selection menu
  7881. addition: function(choice) {
  7882. return choice;
  7883. }
  7884. };
  7885. })( jQuery, window, document );
  7886. /*!
  7887. * # Semantic UI 2.4.1 - Embed
  7888. * http://github.com/semantic-org/semantic-ui/
  7889. *
  7890. *
  7891. * Released under the MIT license
  7892. * http://opensource.org/licenses/MIT
  7893. *
  7894. */
  7895. ;(function ($, window, document, undefined) {
  7896. "use strict";
  7897. window = (typeof window != 'undefined' && window.Math == Math)
  7898. ? window
  7899. : (typeof self != 'undefined' && self.Math == Math)
  7900. ? self
  7901. : Function('return this')()
  7902. ;
  7903. $.fn.embed = function(parameters) {
  7904. var
  7905. $allModules = $(this),
  7906. moduleSelector = $allModules.selector || '',
  7907. time = new Date().getTime(),
  7908. performance = [],
  7909. query = arguments[0],
  7910. methodInvoked = (typeof query == 'string'),
  7911. queryArguments = [].slice.call(arguments, 1),
  7912. returnedValue
  7913. ;
  7914. $allModules
  7915. .each(function() {
  7916. var
  7917. settings = ( $.isPlainObject(parameters) )
  7918. ? $.extend(true, {}, $.fn.embed.settings, parameters)
  7919. : $.extend({}, $.fn.embed.settings),
  7920. selector = settings.selector,
  7921. className = settings.className,
  7922. sources = settings.sources,
  7923. error = settings.error,
  7924. metadata = settings.metadata,
  7925. namespace = settings.namespace,
  7926. templates = settings.templates,
  7927. eventNamespace = '.' + namespace,
  7928. moduleNamespace = 'module-' + namespace,
  7929. $window = $(window),
  7930. $module = $(this),
  7931. $placeholder = $module.find(selector.placeholder),
  7932. $icon = $module.find(selector.icon),
  7933. $embed = $module.find(selector.embed),
  7934. element = this,
  7935. instance = $module.data(moduleNamespace),
  7936. module
  7937. ;
  7938. module = {
  7939. initialize: function() {
  7940. module.debug('Initializing embed');
  7941. module.determine.autoplay();
  7942. module.create();
  7943. module.bind.events();
  7944. module.instantiate();
  7945. },
  7946. instantiate: function() {
  7947. module.verbose('Storing instance of module', module);
  7948. instance = module;
  7949. $module
  7950. .data(moduleNamespace, module)
  7951. ;
  7952. },
  7953. destroy: function() {
  7954. module.verbose('Destroying previous instance of embed');
  7955. module.reset();
  7956. $module
  7957. .removeData(moduleNamespace)
  7958. .off(eventNamespace)
  7959. ;
  7960. },
  7961. refresh: function() {
  7962. module.verbose('Refreshing selector cache');
  7963. $placeholder = $module.find(selector.placeholder);
  7964. $icon = $module.find(selector.icon);
  7965. $embed = $module.find(selector.embed);
  7966. },
  7967. bind: {
  7968. events: function() {
  7969. if( module.has.placeholder() ) {
  7970. module.debug('Adding placeholder events');
  7971. $module
  7972. .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
  7973. .on('click' + eventNamespace, selector.icon, module.createAndShow)
  7974. ;
  7975. }
  7976. }
  7977. },
  7978. create: function() {
  7979. var
  7980. placeholder = module.get.placeholder()
  7981. ;
  7982. if(placeholder) {
  7983. module.createPlaceholder();
  7984. }
  7985. else {
  7986. module.createAndShow();
  7987. }
  7988. },
  7989. createPlaceholder: function(placeholder) {
  7990. var
  7991. icon = module.get.icon(),
  7992. url = module.get.url(),
  7993. embed = module.generate.embed(url)
  7994. ;
  7995. placeholder = placeholder || module.get.placeholder();
  7996. $module.html( templates.placeholder(placeholder, icon) );
  7997. module.debug('Creating placeholder for embed', placeholder, icon);
  7998. },
  7999. createEmbed: function(url) {
  8000. module.refresh();
  8001. url = url || module.get.url();
  8002. $embed = $('<div/>')
  8003. .addClass(className.embed)
  8004. .html( module.generate.embed(url) )
  8005. .appendTo($module)
  8006. ;
  8007. settings.onCreate.call(element, url);
  8008. module.debug('Creating embed object', $embed);
  8009. },
  8010. changeEmbed: function(url) {
  8011. $embed
  8012. .html( module.generate.embed(url) )
  8013. ;
  8014. },
  8015. createAndShow: function() {
  8016. module.createEmbed();
  8017. module.show();
  8018. },
  8019. // sets new embed
  8020. change: function(source, id, url) {
  8021. module.debug('Changing video to ', source, id, url);
  8022. $module
  8023. .data(metadata.source, source)
  8024. .data(metadata.id, id)
  8025. ;
  8026. if(url) {
  8027. $module.data(metadata.url, url);
  8028. }
  8029. else {
  8030. $module.removeData(metadata.url);
  8031. }
  8032. if(module.has.embed()) {
  8033. module.changeEmbed();
  8034. }
  8035. else {
  8036. module.create();
  8037. }
  8038. },
  8039. // clears embed
  8040. reset: function() {
  8041. module.debug('Clearing embed and showing placeholder');
  8042. module.remove.data();
  8043. module.remove.active();
  8044. module.remove.embed();
  8045. module.showPlaceholder();
  8046. settings.onReset.call(element);
  8047. },
  8048. // shows current embed
  8049. show: function() {
  8050. module.debug('Showing embed');
  8051. module.set.active();
  8052. settings.onDisplay.call(element);
  8053. },
  8054. hide: function() {
  8055. module.debug('Hiding embed');
  8056. module.showPlaceholder();
  8057. },
  8058. showPlaceholder: function() {
  8059. module.debug('Showing placeholder image');
  8060. module.remove.active();
  8061. settings.onPlaceholderDisplay.call(element);
  8062. },
  8063. get: {
  8064. id: function() {
  8065. return settings.id || $module.data(metadata.id);
  8066. },
  8067. placeholder: function() {
  8068. return settings.placeholder || $module.data(metadata.placeholder);
  8069. },
  8070. icon: function() {
  8071. return (settings.icon)
  8072. ? settings.icon
  8073. : ($module.data(metadata.icon) !== undefined)
  8074. ? $module.data(metadata.icon)
  8075. : module.determine.icon()
  8076. ;
  8077. },
  8078. source: function(url) {
  8079. return (settings.source)
  8080. ? settings.source
  8081. : ($module.data(metadata.source) !== undefined)
  8082. ? $module.data(metadata.source)
  8083. : module.determine.source()
  8084. ;
  8085. },
  8086. type: function() {
  8087. var source = module.get.source();
  8088. return (sources[source] !== undefined)
  8089. ? sources[source].type
  8090. : false
  8091. ;
  8092. },
  8093. url: function() {
  8094. return (settings.url)
  8095. ? settings.url
  8096. : ($module.data(metadata.url) !== undefined)
  8097. ? $module.data(metadata.url)
  8098. : module.determine.url()
  8099. ;
  8100. }
  8101. },
  8102. determine: {
  8103. autoplay: function() {
  8104. if(module.should.autoplay()) {
  8105. settings.autoplay = true;
  8106. }
  8107. },
  8108. source: function(url) {
  8109. var
  8110. matchedSource = false
  8111. ;
  8112. url = url || module.get.url();
  8113. if(url) {
  8114. $.each(sources, function(name, source) {
  8115. if(url.search(source.domain) !== -1) {
  8116. matchedSource = name;
  8117. return false;
  8118. }
  8119. });
  8120. }
  8121. return matchedSource;
  8122. },
  8123. icon: function() {
  8124. var
  8125. source = module.get.source()
  8126. ;
  8127. return (sources[source] !== undefined)
  8128. ? sources[source].icon
  8129. : false
  8130. ;
  8131. },
  8132. url: function() {
  8133. var
  8134. id = settings.id || $module.data(metadata.id),
  8135. source = settings.source || $module.data(metadata.source),
  8136. url
  8137. ;
  8138. url = (sources[source] !== undefined)
  8139. ? sources[source].url.replace('{id}', id)
  8140. : false
  8141. ;
  8142. if(url) {
  8143. $module.data(metadata.url, url);
  8144. }
  8145. return url;
  8146. }
  8147. },
  8148. set: {
  8149. active: function() {
  8150. $module.addClass(className.active);
  8151. }
  8152. },
  8153. remove: {
  8154. data: function() {
  8155. $module
  8156. .removeData(metadata.id)
  8157. .removeData(metadata.icon)
  8158. .removeData(metadata.placeholder)
  8159. .removeData(metadata.source)
  8160. .removeData(metadata.url)
  8161. ;
  8162. },
  8163. active: function() {
  8164. $module.removeClass(className.active);
  8165. },
  8166. embed: function() {
  8167. $embed.empty();
  8168. }
  8169. },
  8170. encode: {
  8171. parameters: function(parameters) {
  8172. var
  8173. urlString = [],
  8174. index
  8175. ;
  8176. for (index in parameters) {
  8177. urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
  8178. }
  8179. return urlString.join('&amp;');
  8180. }
  8181. },
  8182. generate: {
  8183. embed: function(url) {
  8184. module.debug('Generating embed html');
  8185. var
  8186. source = module.get.source(),
  8187. html,
  8188. parameters
  8189. ;
  8190. url = module.get.url(url);
  8191. if(url) {
  8192. parameters = module.generate.parameters(source);
  8193. html = templates.iframe(url, parameters);
  8194. }
  8195. else {
  8196. module.error(error.noURL, $module);
  8197. }
  8198. return html;
  8199. },
  8200. parameters: function(source, extraParameters) {
  8201. var
  8202. parameters = (sources[source] && sources[source].parameters !== undefined)
  8203. ? sources[source].parameters(settings)
  8204. : {}
  8205. ;
  8206. extraParameters = extraParameters || settings.parameters;
  8207. if(extraParameters) {
  8208. parameters = $.extend({}, parameters, extraParameters);
  8209. }
  8210. parameters = settings.onEmbed(parameters);
  8211. return module.encode.parameters(parameters);
  8212. }
  8213. },
  8214. has: {
  8215. embed: function() {
  8216. return ($embed.length > 0);
  8217. },
  8218. placeholder: function() {
  8219. return settings.placeholder || $module.data(metadata.placeholder);
  8220. }
  8221. },
  8222. should: {
  8223. autoplay: function() {
  8224. return (settings.autoplay === 'auto')
  8225. ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
  8226. : settings.autoplay
  8227. ;
  8228. }
  8229. },
  8230. is: {
  8231. video: function() {
  8232. return module.get.type() == 'video';
  8233. }
  8234. },
  8235. setting: function(name, value) {
  8236. module.debug('Changing setting', name, value);
  8237. if( $.isPlainObject(name) ) {
  8238. $.extend(true, settings, name);
  8239. }
  8240. else if(value !== undefined) {
  8241. if($.isPlainObject(settings[name])) {
  8242. $.extend(true, settings[name], value);
  8243. }
  8244. else {
  8245. settings[name] = value;
  8246. }
  8247. }
  8248. else {
  8249. return settings[name];
  8250. }
  8251. },
  8252. internal: function(name, value) {
  8253. if( $.isPlainObject(name) ) {
  8254. $.extend(true, module, name);
  8255. }
  8256. else if(value !== undefined) {
  8257. module[name] = value;
  8258. }
  8259. else {
  8260. return module[name];
  8261. }
  8262. },
  8263. debug: function() {
  8264. if(!settings.silent && settings.debug) {
  8265. if(settings.performance) {
  8266. module.performance.log(arguments);
  8267. }
  8268. else {
  8269. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8270. module.debug.apply(console, arguments);
  8271. }
  8272. }
  8273. },
  8274. verbose: function() {
  8275. if(!settings.silent && settings.verbose && settings.debug) {
  8276. if(settings.performance) {
  8277. module.performance.log(arguments);
  8278. }
  8279. else {
  8280. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8281. module.verbose.apply(console, arguments);
  8282. }
  8283. }
  8284. },
  8285. error: function() {
  8286. if(!settings.silent) {
  8287. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  8288. module.error.apply(console, arguments);
  8289. }
  8290. },
  8291. performance: {
  8292. log: function(message) {
  8293. var
  8294. currentTime,
  8295. executionTime,
  8296. previousTime
  8297. ;
  8298. if(settings.performance) {
  8299. currentTime = new Date().getTime();
  8300. previousTime = time || currentTime;
  8301. executionTime = currentTime - previousTime;
  8302. time = currentTime;
  8303. performance.push({
  8304. 'Name' : message[0],
  8305. 'Arguments' : [].slice.call(message, 1) || '',
  8306. 'Element' : element,
  8307. 'Execution Time' : executionTime
  8308. });
  8309. }
  8310. clearTimeout(module.performance.timer);
  8311. module.performance.timer = setTimeout(module.performance.display, 500);
  8312. },
  8313. display: function() {
  8314. var
  8315. title = settings.name + ':',
  8316. totalTime = 0
  8317. ;
  8318. time = false;
  8319. clearTimeout(module.performance.timer);
  8320. $.each(performance, function(index, data) {
  8321. totalTime += data['Execution Time'];
  8322. });
  8323. title += ' ' + totalTime + 'ms';
  8324. if(moduleSelector) {
  8325. title += ' \'' + moduleSelector + '\'';
  8326. }
  8327. if($allModules.length > 1) {
  8328. title += ' ' + '(' + $allModules.length + ')';
  8329. }
  8330. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  8331. console.groupCollapsed(title);
  8332. if(console.table) {
  8333. console.table(performance);
  8334. }
  8335. else {
  8336. $.each(performance, function(index, data) {
  8337. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  8338. });
  8339. }
  8340. console.groupEnd();
  8341. }
  8342. performance = [];
  8343. }
  8344. },
  8345. invoke: function(query, passedArguments, context) {
  8346. var
  8347. object = instance,
  8348. maxDepth,
  8349. found,
  8350. response
  8351. ;
  8352. passedArguments = passedArguments || queryArguments;
  8353. context = element || context;
  8354. if(typeof query == 'string' && object !== undefined) {
  8355. query = query.split(/[\. ]/);
  8356. maxDepth = query.length - 1;
  8357. $.each(query, function(depth, value) {
  8358. var camelCaseValue = (depth != maxDepth)
  8359. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  8360. : query
  8361. ;
  8362. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  8363. object = object[camelCaseValue];
  8364. }
  8365. else if( object[camelCaseValue] !== undefined ) {
  8366. found = object[camelCaseValue];
  8367. return false;
  8368. }
  8369. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  8370. object = object[value];
  8371. }
  8372. else if( object[value] !== undefined ) {
  8373. found = object[value];
  8374. return false;
  8375. }
  8376. else {
  8377. module.error(error.method, query);
  8378. return false;
  8379. }
  8380. });
  8381. }
  8382. if ( $.isFunction( found ) ) {
  8383. response = found.apply(context, passedArguments);
  8384. }
  8385. else if(found !== undefined) {
  8386. response = found;
  8387. }
  8388. if($.isArray(returnedValue)) {
  8389. returnedValue.push(response);
  8390. }
  8391. else if(returnedValue !== undefined) {
  8392. returnedValue = [returnedValue, response];
  8393. }
  8394. else if(response !== undefined) {
  8395. returnedValue = response;
  8396. }
  8397. return found;
  8398. }
  8399. };
  8400. if(methodInvoked) {
  8401. if(instance === undefined) {
  8402. module.initialize();
  8403. }
  8404. module.invoke(query);
  8405. }
  8406. else {
  8407. if(instance !== undefined) {
  8408. instance.invoke('destroy');
  8409. }
  8410. module.initialize();
  8411. }
  8412. })
  8413. ;
  8414. return (returnedValue !== undefined)
  8415. ? returnedValue
  8416. : this
  8417. ;
  8418. };
  8419. $.fn.embed.settings = {
  8420. name : 'Embed',
  8421. namespace : 'embed',
  8422. silent : false,
  8423. debug : false,
  8424. verbose : false,
  8425. performance : true,
  8426. icon : false,
  8427. source : false,
  8428. url : false,
  8429. id : false,
  8430. // standard video settings
  8431. autoplay : 'auto',
  8432. color : '#444444',
  8433. hd : true,
  8434. brandedUI : false,
  8435. // additional parameters to include with the embed
  8436. parameters: false,
  8437. onDisplay : function() {},
  8438. onPlaceholderDisplay : function() {},
  8439. onReset : function() {},
  8440. onCreate : function(url) {},
  8441. onEmbed : function(parameters) {
  8442. return parameters;
  8443. },
  8444. metadata : {
  8445. id : 'id',
  8446. icon : 'icon',
  8447. placeholder : 'placeholder',
  8448. source : 'source',
  8449. url : 'url'
  8450. },
  8451. error : {
  8452. noURL : 'No URL specified',
  8453. method : 'The method you called is not defined'
  8454. },
  8455. className : {
  8456. active : 'active',
  8457. embed : 'embed'
  8458. },
  8459. selector : {
  8460. embed : '.embed',
  8461. placeholder : '.placeholder',
  8462. icon : '.icon'
  8463. },
  8464. sources: {
  8465. youtube: {
  8466. name : 'youtube',
  8467. type : 'video',
  8468. icon : 'video play',
  8469. domain : 'youtube.com',
  8470. url : '//www.youtube.com/embed/{id}',
  8471. parameters: function(settings) {
  8472. return {
  8473. autohide : !settings.brandedUI,
  8474. autoplay : settings.autoplay,
  8475. color : settings.color || undefined,
  8476. hq : settings.hd,
  8477. jsapi : settings.api,
  8478. modestbranding : !settings.brandedUI
  8479. };
  8480. }
  8481. },
  8482. vimeo: {
  8483. name : 'vimeo',
  8484. type : 'video',
  8485. icon : 'video play',
  8486. domain : 'vimeo.com',
  8487. url : '//player.vimeo.com/video/{id}',
  8488. parameters: function(settings) {
  8489. return {
  8490. api : settings.api,
  8491. autoplay : settings.autoplay,
  8492. byline : settings.brandedUI,
  8493. color : settings.color || undefined,
  8494. portrait : settings.brandedUI,
  8495. title : settings.brandedUI
  8496. };
  8497. }
  8498. }
  8499. },
  8500. templates: {
  8501. iframe : function(url, parameters) {
  8502. var src = url;
  8503. if (parameters) {
  8504. src += '?' + parameters;
  8505. }
  8506. return ''
  8507. + '<iframe src="' + src + '"'
  8508. + ' width="100%" height="100%"'
  8509. + ' frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  8510. ;
  8511. },
  8512. placeholder : function(image, icon) {
  8513. var
  8514. html = ''
  8515. ;
  8516. if(icon) {
  8517. html += '<i class="' + icon + ' icon"></i>';
  8518. }
  8519. if(image) {
  8520. html += '<img class="placeholder" src="' + image + '">';
  8521. }
  8522. return html;
  8523. }
  8524. },
  8525. // NOT YET IMPLEMENTED
  8526. api : false,
  8527. onPause : function() {},
  8528. onPlay : function() {},
  8529. onStop : function() {}
  8530. };
  8531. })( jQuery, window, document );
  8532. /*!
  8533. * # Semantic UI 2.4.1 - Modal
  8534. * http://github.com/semantic-org/semantic-ui/
  8535. *
  8536. *
  8537. * Released under the MIT license
  8538. * http://opensource.org/licenses/MIT
  8539. *
  8540. */
  8541. ;(function ($, window, document, undefined) {
  8542. 'use strict';
  8543. window = (typeof window != 'undefined' && window.Math == Math)
  8544. ? window
  8545. : (typeof self != 'undefined' && self.Math == Math)
  8546. ? self
  8547. : Function('return this')()
  8548. ;
  8549. $.fn.modal = function(parameters) {
  8550. var
  8551. $allModules = $(this),
  8552. $window = $(window),
  8553. $document = $(document),
  8554. $body = $('body'),
  8555. moduleSelector = $allModules.selector || '',
  8556. time = new Date().getTime(),
  8557. performance = [],
  8558. query = arguments[0],
  8559. methodInvoked = (typeof query == 'string'),
  8560. queryArguments = [].slice.call(arguments, 1),
  8561. requestAnimationFrame = window.requestAnimationFrame
  8562. || window.mozRequestAnimationFrame
  8563. || window.webkitRequestAnimationFrame
  8564. || window.msRequestAnimationFrame
  8565. || function(callback) { setTimeout(callback, 0); },
  8566. returnedValue
  8567. ;
  8568. $allModules
  8569. .each(function() {
  8570. var
  8571. settings = ( $.isPlainObject(parameters) )
  8572. ? $.extend(true, {}, $.fn.modal.settings, parameters)
  8573. : $.extend({}, $.fn.modal.settings),
  8574. selector = settings.selector,
  8575. className = settings.className,
  8576. namespace = settings.namespace,
  8577. error = settings.error,
  8578. eventNamespace = '.' + namespace,
  8579. moduleNamespace = 'module-' + namespace,
  8580. $module = $(this),
  8581. $context = $(settings.context),
  8582. $close = $module.find(selector.close),
  8583. $allModals,
  8584. $otherModals,
  8585. $focusedElement,
  8586. $dimmable,
  8587. $dimmer,
  8588. element = this,
  8589. instance = $module.data(moduleNamespace),
  8590. ignoreRepeatedEvents = false,
  8591. elementEventNamespace,
  8592. id,
  8593. observer,
  8594. module
  8595. ;
  8596. module = {
  8597. initialize: function() {
  8598. module.verbose('Initializing dimmer', $context);
  8599. module.create.id();
  8600. module.create.dimmer();
  8601. module.refreshModals();
  8602. module.bind.events();
  8603. if(settings.observeChanges) {
  8604. module.observeChanges();
  8605. }
  8606. module.instantiate();
  8607. },
  8608. instantiate: function() {
  8609. module.verbose('Storing instance of modal');
  8610. instance = module;
  8611. $module
  8612. .data(moduleNamespace, instance)
  8613. ;
  8614. },
  8615. create: {
  8616. dimmer: function() {
  8617. var
  8618. defaultSettings = {
  8619. debug : settings.debug,
  8620. variation : settings.centered
  8621. ? false
  8622. : 'top aligned',
  8623. dimmerName : 'modals'
  8624. },
  8625. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  8626. ;
  8627. if($.fn.dimmer === undefined) {
  8628. module.error(error.dimmer);
  8629. return;
  8630. }
  8631. module.debug('Creating dimmer');
  8632. $dimmable = $context.dimmer(dimmerSettings);
  8633. if(settings.detachable) {
  8634. module.verbose('Modal is detachable, moving content into dimmer');
  8635. $dimmable.dimmer('add content', $module);
  8636. }
  8637. else {
  8638. module.set.undetached();
  8639. }
  8640. $dimmer = $dimmable.dimmer('get dimmer');
  8641. },
  8642. id: function() {
  8643. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  8644. elementEventNamespace = '.' + id;
  8645. module.verbose('Creating unique id for element', id);
  8646. }
  8647. },
  8648. destroy: function() {
  8649. module.verbose('Destroying previous modal');
  8650. $module
  8651. .removeData(moduleNamespace)
  8652. .off(eventNamespace)
  8653. ;
  8654. $window.off(elementEventNamespace);
  8655. $dimmer.off(elementEventNamespace);
  8656. $close.off(eventNamespace);
  8657. $context.dimmer('destroy');
  8658. },
  8659. observeChanges: function() {
  8660. if('MutationObserver' in window) {
  8661. observer = new MutationObserver(function(mutations) {
  8662. module.debug('DOM tree modified, refreshing');
  8663. module.refresh();
  8664. });
  8665. observer.observe(element, {
  8666. childList : true,
  8667. subtree : true
  8668. });
  8669. module.debug('Setting up mutation observer', observer);
  8670. }
  8671. },
  8672. refresh: function() {
  8673. module.remove.scrolling();
  8674. module.cacheSizes();
  8675. if(!module.can.useFlex()) {
  8676. module.set.modalOffset();
  8677. }
  8678. module.set.screenHeight();
  8679. module.set.type();
  8680. },
  8681. refreshModals: function() {
  8682. $otherModals = $module.siblings(selector.modal);
  8683. $allModals = $otherModals.add($module);
  8684. },
  8685. attachEvents: function(selector, event) {
  8686. var
  8687. $toggle = $(selector)
  8688. ;
  8689. event = $.isFunction(module[event])
  8690. ? module[event]
  8691. : module.toggle
  8692. ;
  8693. if($toggle.length > 0) {
  8694. module.debug('Attaching modal events to element', selector, event);
  8695. $toggle
  8696. .off(eventNamespace)
  8697. .on('click' + eventNamespace, event)
  8698. ;
  8699. }
  8700. else {
  8701. module.error(error.notFound, selector);
  8702. }
  8703. },
  8704. bind: {
  8705. events: function() {
  8706. module.verbose('Attaching events');
  8707. $module
  8708. .on('click' + eventNamespace, selector.close, module.event.close)
  8709. .on('click' + eventNamespace, selector.approve, module.event.approve)
  8710. .on('click' + eventNamespace, selector.deny, module.event.deny)
  8711. ;
  8712. $window
  8713. .on('resize' + elementEventNamespace, module.event.resize)
  8714. ;
  8715. },
  8716. scrollLock: function() {
  8717. // touch events default to passive, due to changes in chrome to optimize mobile perf
  8718. $dimmable.get(0).addEventListener('touchmove', module.event.preventScroll, { passive: false });
  8719. }
  8720. },
  8721. unbind: {
  8722. scrollLock: function() {
  8723. $dimmable.get(0).removeEventListener('touchmove', module.event.preventScroll, { passive: false });
  8724. }
  8725. },
  8726. get: {
  8727. id: function() {
  8728. return (Math.random().toString(16) + '000000000').substr(2, 8);
  8729. }
  8730. },
  8731. event: {
  8732. approve: function() {
  8733. if(ignoreRepeatedEvents || settings.onApprove.call(element, $(this)) === false) {
  8734. module.verbose('Approve callback returned false cancelling hide');
  8735. return;
  8736. }
  8737. ignoreRepeatedEvents = true;
  8738. module.hide(function() {
  8739. ignoreRepeatedEvents = false;
  8740. });
  8741. },
  8742. preventScroll: function(event) {
  8743. event.preventDefault();
  8744. },
  8745. deny: function() {
  8746. if(ignoreRepeatedEvents || settings.onDeny.call(element, $(this)) === false) {
  8747. module.verbose('Deny callback returned false cancelling hide');
  8748. return;
  8749. }
  8750. ignoreRepeatedEvents = true;
  8751. module.hide(function() {
  8752. ignoreRepeatedEvents = false;
  8753. });
  8754. },
  8755. close: function() {
  8756. module.hide();
  8757. },
  8758. click: function(event) {
  8759. if(!settings.closable) {
  8760. module.verbose('Dimmer clicked but closable setting is disabled');
  8761. return;
  8762. }
  8763. var
  8764. $target = $(event.target),
  8765. isInModal = ($target.closest(selector.modal).length > 0),
  8766. isInDOM = $.contains(document.documentElement, event.target)
  8767. ;
  8768. if(!isInModal && isInDOM && module.is.active()) {
  8769. module.debug('Dimmer clicked, hiding all modals');
  8770. module.remove.clickaway();
  8771. if(settings.allowMultiple) {
  8772. module.hide();
  8773. }
  8774. else {
  8775. module.hideAll();
  8776. }
  8777. }
  8778. },
  8779. debounce: function(method, delay) {
  8780. clearTimeout(module.timer);
  8781. module.timer = setTimeout(method, delay);
  8782. },
  8783. keyboard: function(event) {
  8784. var
  8785. keyCode = event.which,
  8786. escapeKey = 27
  8787. ;
  8788. if(keyCode == escapeKey) {
  8789. if(settings.closable) {
  8790. module.debug('Escape key pressed hiding modal');
  8791. module.hide();
  8792. }
  8793. else {
  8794. module.debug('Escape key pressed, but closable is set to false');
  8795. }
  8796. event.preventDefault();
  8797. }
  8798. },
  8799. resize: function() {
  8800. if( $dimmable.dimmer('is active') && ( module.is.animating() || module.is.active() ) ) {
  8801. requestAnimationFrame(module.refresh);
  8802. }
  8803. }
  8804. },
  8805. toggle: function() {
  8806. if( module.is.active() || module.is.animating() ) {
  8807. module.hide();
  8808. }
  8809. else {
  8810. module.show();
  8811. }
  8812. },
  8813. show: function(callback) {
  8814. callback = $.isFunction(callback)
  8815. ? callback
  8816. : function(){}
  8817. ;
  8818. module.refreshModals();
  8819. module.set.dimmerSettings();
  8820. module.set.dimmerStyles();
  8821. module.showModal(callback);
  8822. },
  8823. hide: function(callback) {
  8824. callback = $.isFunction(callback)
  8825. ? callback
  8826. : function(){}
  8827. ;
  8828. module.refreshModals();
  8829. module.hideModal(callback);
  8830. },
  8831. showModal: function(callback) {
  8832. callback = $.isFunction(callback)
  8833. ? callback
  8834. : function(){}
  8835. ;
  8836. if( module.is.animating() || !module.is.active() ) {
  8837. module.showDimmer();
  8838. module.cacheSizes();
  8839. if(module.can.useFlex()) {
  8840. module.remove.legacy();
  8841. }
  8842. else {
  8843. module.set.legacy();
  8844. module.set.modalOffset();
  8845. module.debug('Using non-flex legacy modal positioning.');
  8846. }
  8847. module.set.screenHeight();
  8848. module.set.type();
  8849. module.set.clickaway();
  8850. if( !settings.allowMultiple && module.others.active() ) {
  8851. module.hideOthers(module.showModal);
  8852. }
  8853. else {
  8854. if(settings.allowMultiple && settings.detachable) {
  8855. $module.detach().appendTo($dimmer);
  8856. }
  8857. settings.onShow.call(element);
  8858. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8859. module.debug('Showing modal with css animations');
  8860. $module
  8861. .transition({
  8862. debug : settings.debug,
  8863. animation : settings.transition + ' in',
  8864. queue : settings.queue,
  8865. duration : settings.duration,
  8866. useFailSafe : true,
  8867. onComplete : function() {
  8868. settings.onVisible.apply(element);
  8869. if(settings.keyboardShortcuts) {
  8870. module.add.keyboardShortcuts();
  8871. }
  8872. module.save.focus();
  8873. module.set.active();
  8874. if(settings.autofocus) {
  8875. module.set.autofocus();
  8876. }
  8877. callback();
  8878. }
  8879. })
  8880. ;
  8881. }
  8882. else {
  8883. module.error(error.noTransition);
  8884. }
  8885. }
  8886. }
  8887. else {
  8888. module.debug('Modal is already visible');
  8889. }
  8890. },
  8891. hideModal: function(callback, keepDimmed) {
  8892. callback = $.isFunction(callback)
  8893. ? callback
  8894. : function(){}
  8895. ;
  8896. module.debug('Hiding modal');
  8897. if(settings.onHide.call(element, $(this)) === false) {
  8898. module.verbose('Hide callback returned false cancelling hide');
  8899. return;
  8900. }
  8901. if( module.is.animating() || module.is.active() ) {
  8902. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8903. module.remove.active();
  8904. $module
  8905. .transition({
  8906. debug : settings.debug,
  8907. animation : settings.transition + ' out',
  8908. queue : settings.queue,
  8909. duration : settings.duration,
  8910. useFailSafe : true,
  8911. onStart : function() {
  8912. if(!module.others.active() && !keepDimmed) {
  8913. module.hideDimmer();
  8914. }
  8915. if(settings.keyboardShortcuts) {
  8916. module.remove.keyboardShortcuts();
  8917. }
  8918. },
  8919. onComplete : function() {
  8920. settings.onHidden.call(element);
  8921. module.remove.dimmerStyles();
  8922. module.restore.focus();
  8923. callback();
  8924. }
  8925. })
  8926. ;
  8927. }
  8928. else {
  8929. module.error(error.noTransition);
  8930. }
  8931. }
  8932. },
  8933. showDimmer: function() {
  8934. if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
  8935. module.debug('Showing dimmer');
  8936. $dimmable.dimmer('show');
  8937. }
  8938. else {
  8939. module.debug('Dimmer already visible');
  8940. }
  8941. },
  8942. hideDimmer: function() {
  8943. if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
  8944. module.unbind.scrollLock();
  8945. $dimmable.dimmer('hide', function() {
  8946. module.remove.clickaway();
  8947. module.remove.screenHeight();
  8948. });
  8949. }
  8950. else {
  8951. module.debug('Dimmer is not visible cannot hide');
  8952. return;
  8953. }
  8954. },
  8955. hideAll: function(callback) {
  8956. var
  8957. $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
  8958. ;
  8959. callback = $.isFunction(callback)
  8960. ? callback
  8961. : function(){}
  8962. ;
  8963. if( $visibleModals.length > 0 ) {
  8964. module.debug('Hiding all visible modals');
  8965. module.hideDimmer();
  8966. $visibleModals
  8967. .modal('hide modal', callback)
  8968. ;
  8969. }
  8970. },
  8971. hideOthers: function(callback) {
  8972. var
  8973. $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
  8974. ;
  8975. callback = $.isFunction(callback)
  8976. ? callback
  8977. : function(){}
  8978. ;
  8979. if( $visibleModals.length > 0 ) {
  8980. module.debug('Hiding other modals', $otherModals);
  8981. $visibleModals
  8982. .modal('hide modal', callback, true)
  8983. ;
  8984. }
  8985. },
  8986. others: {
  8987. active: function() {
  8988. return ($otherModals.filter('.' + className.active).length > 0);
  8989. },
  8990. animating: function() {
  8991. return ($otherModals.filter('.' + className.animating).length > 0);
  8992. }
  8993. },
  8994. add: {
  8995. keyboardShortcuts: function() {
  8996. module.verbose('Adding keyboard shortcuts');
  8997. $document
  8998. .on('keyup' + eventNamespace, module.event.keyboard)
  8999. ;
  9000. }
  9001. },
  9002. save: {
  9003. focus: function() {
  9004. var
  9005. $activeElement = $(document.activeElement),
  9006. inCurrentModal = $activeElement.closest($module).length > 0
  9007. ;
  9008. if(!inCurrentModal) {
  9009. $focusedElement = $(document.activeElement).blur();
  9010. }
  9011. }
  9012. },
  9013. restore: {
  9014. focus: function() {
  9015. if($focusedElement && $focusedElement.length > 0) {
  9016. $focusedElement.focus();
  9017. }
  9018. }
  9019. },
  9020. remove: {
  9021. active: function() {
  9022. $module.removeClass(className.active);
  9023. },
  9024. legacy: function() {
  9025. $module.removeClass(className.legacy);
  9026. },
  9027. clickaway: function() {
  9028. $dimmer
  9029. .off('click' + elementEventNamespace)
  9030. ;
  9031. },
  9032. dimmerStyles: function() {
  9033. $dimmer.removeClass(className.inverted);
  9034. $dimmable.removeClass(className.blurring);
  9035. },
  9036. bodyStyle: function() {
  9037. if($body.attr('style') === '') {
  9038. module.verbose('Removing style attribute');
  9039. $body.removeAttr('style');
  9040. }
  9041. },
  9042. screenHeight: function() {
  9043. module.debug('Removing page height');
  9044. $body
  9045. .css('height', '')
  9046. ;
  9047. },
  9048. keyboardShortcuts: function() {
  9049. module.verbose('Removing keyboard shortcuts');
  9050. $document
  9051. .off('keyup' + eventNamespace)
  9052. ;
  9053. },
  9054. scrolling: function() {
  9055. $dimmable.removeClass(className.scrolling);
  9056. $module.removeClass(className.scrolling);
  9057. }
  9058. },
  9059. cacheSizes: function() {
  9060. $module.addClass(className.loading);
  9061. var
  9062. scrollHeight = $module.prop('scrollHeight'),
  9063. modalWidth = $module.outerWidth(),
  9064. modalHeight = $module.outerHeight()
  9065. ;
  9066. if(module.cache === undefined || modalHeight !== 0) {
  9067. module.cache = {
  9068. pageHeight : $(document).outerHeight(),
  9069. width : modalWidth,
  9070. height : modalHeight + settings.offset,
  9071. scrollHeight : scrollHeight + settings.offset,
  9072. contextHeight : (settings.context == 'body')
  9073. ? $(window).height()
  9074. : $dimmable.height(),
  9075. };
  9076. module.cache.topOffset = -(module.cache.height / 2);
  9077. }
  9078. $module.removeClass(className.loading);
  9079. module.debug('Caching modal and container sizes', module.cache);
  9080. },
  9081. can: {
  9082. useFlex: function() {
  9083. return (settings.useFlex == 'auto')
  9084. ? settings.detachable && !module.is.ie()
  9085. : settings.useFlex
  9086. ;
  9087. },
  9088. fit: function() {
  9089. var
  9090. contextHeight = module.cache.contextHeight,
  9091. verticalCenter = module.cache.contextHeight / 2,
  9092. topOffset = module.cache.topOffset,
  9093. scrollHeight = module.cache.scrollHeight,
  9094. height = module.cache.height,
  9095. paddingHeight = settings.padding,
  9096. startPosition = (verticalCenter + topOffset)
  9097. ;
  9098. return (scrollHeight > height)
  9099. ? (startPosition + scrollHeight + paddingHeight < contextHeight)
  9100. : (height + (paddingHeight * 2) < contextHeight)
  9101. ;
  9102. }
  9103. },
  9104. is: {
  9105. active: function() {
  9106. return $module.hasClass(className.active);
  9107. },
  9108. ie: function() {
  9109. var
  9110. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  9111. isIE = ('ActiveXObject' in window)
  9112. ;
  9113. return (isIE11 || isIE);
  9114. },
  9115. animating: function() {
  9116. return $module.transition('is supported')
  9117. ? $module.transition('is animating')
  9118. : $module.is(':visible')
  9119. ;
  9120. },
  9121. scrolling: function() {
  9122. return $dimmable.hasClass(className.scrolling);
  9123. },
  9124. modernBrowser: function() {
  9125. // appName for IE11 reports 'Netscape' can no longer use
  9126. return !(window.ActiveXObject || 'ActiveXObject' in window);
  9127. }
  9128. },
  9129. set: {
  9130. autofocus: function() {
  9131. var
  9132. $inputs = $module.find('[tabindex], :input').filter(':visible'),
  9133. $autofocus = $inputs.filter('[autofocus]'),
  9134. $input = ($autofocus.length > 0)
  9135. ? $autofocus.first()
  9136. : $inputs.first()
  9137. ;
  9138. if($input.length > 0) {
  9139. $input.focus();
  9140. }
  9141. },
  9142. clickaway: function() {
  9143. $dimmer
  9144. .on('click' + elementEventNamespace, module.event.click)
  9145. ;
  9146. },
  9147. dimmerSettings: function() {
  9148. if($.fn.dimmer === undefined) {
  9149. module.error(error.dimmer);
  9150. return;
  9151. }
  9152. var
  9153. defaultSettings = {
  9154. debug : settings.debug,
  9155. dimmerName : 'modals',
  9156. closable : 'auto',
  9157. useFlex : module.can.useFlex(),
  9158. variation : settings.centered
  9159. ? false
  9160. : 'top aligned',
  9161. duration : {
  9162. show : settings.duration,
  9163. hide : settings.duration
  9164. }
  9165. },
  9166. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  9167. ;
  9168. if(settings.inverted) {
  9169. dimmerSettings.variation = (dimmerSettings.variation !== undefined)
  9170. ? dimmerSettings.variation + ' inverted'
  9171. : 'inverted'
  9172. ;
  9173. }
  9174. $context.dimmer('setting', dimmerSettings);
  9175. },
  9176. dimmerStyles: function() {
  9177. if(settings.inverted) {
  9178. $dimmer.addClass(className.inverted);
  9179. }
  9180. else {
  9181. $dimmer.removeClass(className.inverted);
  9182. }
  9183. if(settings.blurring) {
  9184. $dimmable.addClass(className.blurring);
  9185. }
  9186. else {
  9187. $dimmable.removeClass(className.blurring);
  9188. }
  9189. },
  9190. modalOffset: function() {
  9191. var
  9192. width = module.cache.width,
  9193. height = module.cache.height
  9194. ;
  9195. $module
  9196. .css({
  9197. marginTop: (settings.centered && module.can.fit())
  9198. ? -(height / 2)
  9199. : 0,
  9200. marginLeft: -(width / 2)
  9201. })
  9202. ;
  9203. module.verbose('Setting modal offset for legacy mode');
  9204. },
  9205. screenHeight: function() {
  9206. if( module.can.fit() ) {
  9207. $body.css('height', '');
  9208. }
  9209. else {
  9210. module.debug('Modal is taller than page content, resizing page height');
  9211. $body
  9212. .css('height', module.cache.height + (settings.padding * 2) )
  9213. ;
  9214. }
  9215. },
  9216. active: function() {
  9217. $module.addClass(className.active);
  9218. },
  9219. scrolling: function() {
  9220. $dimmable.addClass(className.scrolling);
  9221. $module.addClass(className.scrolling);
  9222. module.unbind.scrollLock();
  9223. },
  9224. legacy: function() {
  9225. $module.addClass(className.legacy);
  9226. },
  9227. type: function() {
  9228. if(module.can.fit()) {
  9229. module.verbose('Modal fits on screen');
  9230. if(!module.others.active() && !module.others.animating()) {
  9231. module.remove.scrolling();
  9232. module.bind.scrollLock();
  9233. }
  9234. }
  9235. else {
  9236. module.verbose('Modal cannot fit on screen setting to scrolling');
  9237. module.set.scrolling();
  9238. }
  9239. },
  9240. undetached: function() {
  9241. $dimmable.addClass(className.undetached);
  9242. }
  9243. },
  9244. setting: function(name, value) {
  9245. module.debug('Changing setting', name, value);
  9246. if( $.isPlainObject(name) ) {
  9247. $.extend(true, settings, name);
  9248. }
  9249. else if(value !== undefined) {
  9250. if($.isPlainObject(settings[name])) {
  9251. $.extend(true, settings[name], value);
  9252. }
  9253. else {
  9254. settings[name] = value;
  9255. }
  9256. }
  9257. else {
  9258. return settings[name];
  9259. }
  9260. },
  9261. internal: function(name, value) {
  9262. if( $.isPlainObject(name) ) {
  9263. $.extend(true, module, name);
  9264. }
  9265. else if(value !== undefined) {
  9266. module[name] = value;
  9267. }
  9268. else {
  9269. return module[name];
  9270. }
  9271. },
  9272. debug: function() {
  9273. if(!settings.silent && settings.debug) {
  9274. if(settings.performance) {
  9275. module.performance.log(arguments);
  9276. }
  9277. else {
  9278. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9279. module.debug.apply(console, arguments);
  9280. }
  9281. }
  9282. },
  9283. verbose: function() {
  9284. if(!settings.silent && settings.verbose && settings.debug) {
  9285. if(settings.performance) {
  9286. module.performance.log(arguments);
  9287. }
  9288. else {
  9289. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9290. module.verbose.apply(console, arguments);
  9291. }
  9292. }
  9293. },
  9294. error: function() {
  9295. if(!settings.silent) {
  9296. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9297. module.error.apply(console, arguments);
  9298. }
  9299. },
  9300. performance: {
  9301. log: function(message) {
  9302. var
  9303. currentTime,
  9304. executionTime,
  9305. previousTime
  9306. ;
  9307. if(settings.performance) {
  9308. currentTime = new Date().getTime();
  9309. previousTime = time || currentTime;
  9310. executionTime = currentTime - previousTime;
  9311. time = currentTime;
  9312. performance.push({
  9313. 'Name' : message[0],
  9314. 'Arguments' : [].slice.call(message, 1) || '',
  9315. 'Element' : element,
  9316. 'Execution Time' : executionTime
  9317. });
  9318. }
  9319. clearTimeout(module.performance.timer);
  9320. module.performance.timer = setTimeout(module.performance.display, 500);
  9321. },
  9322. display: function() {
  9323. var
  9324. title = settings.name + ':',
  9325. totalTime = 0
  9326. ;
  9327. time = false;
  9328. clearTimeout(module.performance.timer);
  9329. $.each(performance, function(index, data) {
  9330. totalTime += data['Execution Time'];
  9331. });
  9332. title += ' ' + totalTime + 'ms';
  9333. if(moduleSelector) {
  9334. title += ' \'' + moduleSelector + '\'';
  9335. }
  9336. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9337. console.groupCollapsed(title);
  9338. if(console.table) {
  9339. console.table(performance);
  9340. }
  9341. else {
  9342. $.each(performance, function(index, data) {
  9343. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9344. });
  9345. }
  9346. console.groupEnd();
  9347. }
  9348. performance = [];
  9349. }
  9350. },
  9351. invoke: function(query, passedArguments, context) {
  9352. var
  9353. object = instance,
  9354. maxDepth,
  9355. found,
  9356. response
  9357. ;
  9358. passedArguments = passedArguments || queryArguments;
  9359. context = element || context;
  9360. if(typeof query == 'string' && object !== undefined) {
  9361. query = query.split(/[\. ]/);
  9362. maxDepth = query.length - 1;
  9363. $.each(query, function(depth, value) {
  9364. var camelCaseValue = (depth != maxDepth)
  9365. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9366. : query
  9367. ;
  9368. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9369. object = object[camelCaseValue];
  9370. }
  9371. else if( object[camelCaseValue] !== undefined ) {
  9372. found = object[camelCaseValue];
  9373. return false;
  9374. }
  9375. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9376. object = object[value];
  9377. }
  9378. else if( object[value] !== undefined ) {
  9379. found = object[value];
  9380. return false;
  9381. }
  9382. else {
  9383. return false;
  9384. }
  9385. });
  9386. }
  9387. if ( $.isFunction( found ) ) {
  9388. response = found.apply(context, passedArguments);
  9389. }
  9390. else if(found !== undefined) {
  9391. response = found;
  9392. }
  9393. if($.isArray(returnedValue)) {
  9394. returnedValue.push(response);
  9395. }
  9396. else if(returnedValue !== undefined) {
  9397. returnedValue = [returnedValue, response];
  9398. }
  9399. else if(response !== undefined) {
  9400. returnedValue = response;
  9401. }
  9402. return found;
  9403. }
  9404. };
  9405. if(methodInvoked) {
  9406. if(instance === undefined) {
  9407. module.initialize();
  9408. }
  9409. module.invoke(query);
  9410. }
  9411. else {
  9412. if(instance !== undefined) {
  9413. instance.invoke('destroy');
  9414. }
  9415. module.initialize();
  9416. }
  9417. })
  9418. ;
  9419. return (returnedValue !== undefined)
  9420. ? returnedValue
  9421. : this
  9422. ;
  9423. };
  9424. $.fn.modal.settings = {
  9425. name : 'Modal',
  9426. namespace : 'modal',
  9427. useFlex : 'auto',
  9428. offset : 0,
  9429. silent : false,
  9430. debug : false,
  9431. verbose : false,
  9432. performance : true,
  9433. observeChanges : false,
  9434. allowMultiple : false,
  9435. detachable : true,
  9436. closable : true,
  9437. autofocus : true,
  9438. inverted : false,
  9439. blurring : false,
  9440. centered : true,
  9441. dimmerSettings : {
  9442. closable : false,
  9443. useCSS : true
  9444. },
  9445. // whether to use keyboard shortcuts
  9446. keyboardShortcuts: true,
  9447. context : 'body',
  9448. queue : false,
  9449. duration : 500,
  9450. transition : 'scale',
  9451. // padding with edge of page
  9452. padding : 50,
  9453. // called before show animation
  9454. onShow : function(){},
  9455. // called after show animation
  9456. onVisible : function(){},
  9457. // called before hide animation
  9458. onHide : function(){ return true; },
  9459. // called after hide animation
  9460. onHidden : function(){},
  9461. // called after approve selector match
  9462. onApprove : function(){ return true; },
  9463. // called after deny selector match
  9464. onDeny : function(){ return true; },
  9465. selector : {
  9466. close : '> .close',
  9467. approve : '.actions .positive, .actions .approve, .actions .ok',
  9468. deny : '.actions .negative, .actions .deny, .actions .cancel',
  9469. modal : '.ui.modal'
  9470. },
  9471. error : {
  9472. dimmer : 'UI Dimmer, a required component is not included in this page',
  9473. method : 'The method you called is not defined.',
  9474. notFound : 'The element you specified could not be found'
  9475. },
  9476. className : {
  9477. active : 'active',
  9478. animating : 'animating',
  9479. blurring : 'blurring',
  9480. inverted : 'inverted',
  9481. legacy : 'legacy',
  9482. loading : 'loading',
  9483. scrolling : 'scrolling',
  9484. undetached : 'undetached'
  9485. }
  9486. };
  9487. })( jQuery, window, document );
  9488. /*!
  9489. * # Semantic UI 2.4.1 - Nag
  9490. * http://github.com/semantic-org/semantic-ui/
  9491. *
  9492. *
  9493. * Released under the MIT license
  9494. * http://opensource.org/licenses/MIT
  9495. *
  9496. */
  9497. ;(function ($, window, document, undefined) {
  9498. 'use strict';
  9499. window = (typeof window != 'undefined' && window.Math == Math)
  9500. ? window
  9501. : (typeof self != 'undefined' && self.Math == Math)
  9502. ? self
  9503. : Function('return this')()
  9504. ;
  9505. $.fn.nag = function(parameters) {
  9506. var
  9507. $allModules = $(this),
  9508. moduleSelector = $allModules.selector || '',
  9509. time = new Date().getTime(),
  9510. performance = [],
  9511. query = arguments[0],
  9512. methodInvoked = (typeof query == 'string'),
  9513. queryArguments = [].slice.call(arguments, 1),
  9514. returnedValue
  9515. ;
  9516. $allModules
  9517. .each(function() {
  9518. var
  9519. settings = ( $.isPlainObject(parameters) )
  9520. ? $.extend(true, {}, $.fn.nag.settings, parameters)
  9521. : $.extend({}, $.fn.nag.settings),
  9522. className = settings.className,
  9523. selector = settings.selector,
  9524. error = settings.error,
  9525. namespace = settings.namespace,
  9526. eventNamespace = '.' + namespace,
  9527. moduleNamespace = namespace + '-module',
  9528. $module = $(this),
  9529. $close = $module.find(selector.close),
  9530. $context = (settings.context)
  9531. ? $(settings.context)
  9532. : $('body'),
  9533. element = this,
  9534. instance = $module.data(moduleNamespace),
  9535. moduleOffset,
  9536. moduleHeight,
  9537. contextWidth,
  9538. contextHeight,
  9539. contextOffset,
  9540. yOffset,
  9541. yPosition,
  9542. timer,
  9543. module,
  9544. requestAnimationFrame = window.requestAnimationFrame
  9545. || window.mozRequestAnimationFrame
  9546. || window.webkitRequestAnimationFrame
  9547. || window.msRequestAnimationFrame
  9548. || function(callback) { setTimeout(callback, 0); }
  9549. ;
  9550. module = {
  9551. initialize: function() {
  9552. module.verbose('Initializing element');
  9553. $module
  9554. .on('click' + eventNamespace, selector.close, module.dismiss)
  9555. .data(moduleNamespace, module)
  9556. ;
  9557. if(settings.detachable && $module.parent()[0] !== $context[0]) {
  9558. $module
  9559. .detach()
  9560. .prependTo($context)
  9561. ;
  9562. }
  9563. if(settings.displayTime > 0) {
  9564. setTimeout(module.hide, settings.displayTime);
  9565. }
  9566. module.show();
  9567. },
  9568. destroy: function() {
  9569. module.verbose('Destroying instance');
  9570. $module
  9571. .removeData(moduleNamespace)
  9572. .off(eventNamespace)
  9573. ;
  9574. },
  9575. show: function() {
  9576. if( module.should.show() && !$module.is(':visible') ) {
  9577. module.debug('Showing nag', settings.animation.show);
  9578. if(settings.animation.show == 'fade') {
  9579. $module
  9580. .fadeIn(settings.duration, settings.easing)
  9581. ;
  9582. }
  9583. else {
  9584. $module
  9585. .slideDown(settings.duration, settings.easing)
  9586. ;
  9587. }
  9588. }
  9589. },
  9590. hide: function() {
  9591. module.debug('Showing nag', settings.animation.hide);
  9592. if(settings.animation.show == 'fade') {
  9593. $module
  9594. .fadeIn(settings.duration, settings.easing)
  9595. ;
  9596. }
  9597. else {
  9598. $module
  9599. .slideUp(settings.duration, settings.easing)
  9600. ;
  9601. }
  9602. },
  9603. onHide: function() {
  9604. module.debug('Removing nag', settings.animation.hide);
  9605. $module.remove();
  9606. if (settings.onHide) {
  9607. settings.onHide();
  9608. }
  9609. },
  9610. dismiss: function(event) {
  9611. if(settings.storageMethod) {
  9612. module.storage.set(settings.key, settings.value);
  9613. }
  9614. module.hide();
  9615. event.stopImmediatePropagation();
  9616. event.preventDefault();
  9617. },
  9618. should: {
  9619. show: function() {
  9620. if(settings.persist) {
  9621. module.debug('Persistent nag is set, can show nag');
  9622. return true;
  9623. }
  9624. if( module.storage.get(settings.key) != settings.value.toString() ) {
  9625. module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
  9626. return true;
  9627. }
  9628. module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
  9629. return false;
  9630. }
  9631. },
  9632. get: {
  9633. storageOptions: function() {
  9634. var
  9635. options = {}
  9636. ;
  9637. if(settings.expires) {
  9638. options.expires = settings.expires;
  9639. }
  9640. if(settings.domain) {
  9641. options.domain = settings.domain;
  9642. }
  9643. if(settings.path) {
  9644. options.path = settings.path;
  9645. }
  9646. return options;
  9647. }
  9648. },
  9649. clear: function() {
  9650. module.storage.remove(settings.key);
  9651. },
  9652. storage: {
  9653. set: function(key, value) {
  9654. var
  9655. options = module.get.storageOptions()
  9656. ;
  9657. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9658. window.localStorage.setItem(key, value);
  9659. module.debug('Value stored using local storage', key, value);
  9660. }
  9661. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9662. window.sessionStorage.setItem(key, value);
  9663. module.debug('Value stored using session storage', key, value);
  9664. }
  9665. else if($.cookie !== undefined) {
  9666. $.cookie(key, value, options);
  9667. module.debug('Value stored using cookie', key, value, options);
  9668. }
  9669. else {
  9670. module.error(error.noCookieStorage);
  9671. return;
  9672. }
  9673. },
  9674. get: function(key, value) {
  9675. var
  9676. storedValue
  9677. ;
  9678. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9679. storedValue = window.localStorage.getItem(key);
  9680. }
  9681. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9682. storedValue = window.sessionStorage.getItem(key);
  9683. }
  9684. // get by cookie
  9685. else if($.cookie !== undefined) {
  9686. storedValue = $.cookie(key);
  9687. }
  9688. else {
  9689. module.error(error.noCookieStorage);
  9690. }
  9691. if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
  9692. storedValue = undefined;
  9693. }
  9694. return storedValue;
  9695. },
  9696. remove: function(key) {
  9697. var
  9698. options = module.get.storageOptions()
  9699. ;
  9700. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  9701. window.localStorage.removeItem(key);
  9702. }
  9703. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  9704. window.sessionStorage.removeItem(key);
  9705. }
  9706. // store by cookie
  9707. else if($.cookie !== undefined) {
  9708. $.removeCookie(key, options);
  9709. }
  9710. else {
  9711. module.error(error.noStorage);
  9712. }
  9713. }
  9714. },
  9715. setting: function(name, value) {
  9716. module.debug('Changing setting', name, value);
  9717. if( $.isPlainObject(name) ) {
  9718. $.extend(true, settings, name);
  9719. }
  9720. else if(value !== undefined) {
  9721. if($.isPlainObject(settings[name])) {
  9722. $.extend(true, settings[name], value);
  9723. }
  9724. else {
  9725. settings[name] = value;
  9726. }
  9727. }
  9728. else {
  9729. return settings[name];
  9730. }
  9731. },
  9732. internal: function(name, value) {
  9733. if( $.isPlainObject(name) ) {
  9734. $.extend(true, module, name);
  9735. }
  9736. else if(value !== undefined) {
  9737. module[name] = value;
  9738. }
  9739. else {
  9740. return module[name];
  9741. }
  9742. },
  9743. debug: function() {
  9744. if(!settings.silent && settings.debug) {
  9745. if(settings.performance) {
  9746. module.performance.log(arguments);
  9747. }
  9748. else {
  9749. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9750. module.debug.apply(console, arguments);
  9751. }
  9752. }
  9753. },
  9754. verbose: function() {
  9755. if(!settings.silent && settings.verbose && settings.debug) {
  9756. if(settings.performance) {
  9757. module.performance.log(arguments);
  9758. }
  9759. else {
  9760. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9761. module.verbose.apply(console, arguments);
  9762. }
  9763. }
  9764. },
  9765. error: function() {
  9766. if(!settings.silent) {
  9767. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9768. module.error.apply(console, arguments);
  9769. }
  9770. },
  9771. performance: {
  9772. log: function(message) {
  9773. var
  9774. currentTime,
  9775. executionTime,
  9776. previousTime
  9777. ;
  9778. if(settings.performance) {
  9779. currentTime = new Date().getTime();
  9780. previousTime = time || currentTime;
  9781. executionTime = currentTime - previousTime;
  9782. time = currentTime;
  9783. performance.push({
  9784. 'Name' : message[0],
  9785. 'Arguments' : [].slice.call(message, 1) || '',
  9786. 'Element' : element,
  9787. 'Execution Time' : executionTime
  9788. });
  9789. }
  9790. clearTimeout(module.performance.timer);
  9791. module.performance.timer = setTimeout(module.performance.display, 500);
  9792. },
  9793. display: function() {
  9794. var
  9795. title = settings.name + ':',
  9796. totalTime = 0
  9797. ;
  9798. time = false;
  9799. clearTimeout(module.performance.timer);
  9800. $.each(performance, function(index, data) {
  9801. totalTime += data['Execution Time'];
  9802. });
  9803. title += ' ' + totalTime + 'ms';
  9804. if(moduleSelector) {
  9805. title += ' \'' + moduleSelector + '\'';
  9806. }
  9807. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9808. console.groupCollapsed(title);
  9809. if(console.table) {
  9810. console.table(performance);
  9811. }
  9812. else {
  9813. $.each(performance, function(index, data) {
  9814. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9815. });
  9816. }
  9817. console.groupEnd();
  9818. }
  9819. performance = [];
  9820. }
  9821. },
  9822. invoke: function(query, passedArguments, context) {
  9823. var
  9824. object = instance,
  9825. maxDepth,
  9826. found,
  9827. response
  9828. ;
  9829. passedArguments = passedArguments || queryArguments;
  9830. context = element || context;
  9831. if(typeof query == 'string' && object !== undefined) {
  9832. query = query.split(/[\. ]/);
  9833. maxDepth = query.length - 1;
  9834. $.each(query, function(depth, value) {
  9835. var camelCaseValue = (depth != maxDepth)
  9836. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9837. : query
  9838. ;
  9839. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9840. object = object[camelCaseValue];
  9841. }
  9842. else if( object[camelCaseValue] !== undefined ) {
  9843. found = object[camelCaseValue];
  9844. return false;
  9845. }
  9846. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9847. object = object[value];
  9848. }
  9849. else if( object[value] !== undefined ) {
  9850. found = object[value];
  9851. return false;
  9852. }
  9853. else {
  9854. module.error(error.method, query);
  9855. return false;
  9856. }
  9857. });
  9858. }
  9859. if ( $.isFunction( found ) ) {
  9860. response = found.apply(context, passedArguments);
  9861. }
  9862. else if(found !== undefined) {
  9863. response = found;
  9864. }
  9865. if($.isArray(returnedValue)) {
  9866. returnedValue.push(response);
  9867. }
  9868. else if(returnedValue !== undefined) {
  9869. returnedValue = [returnedValue, response];
  9870. }
  9871. else if(response !== undefined) {
  9872. returnedValue = response;
  9873. }
  9874. return found;
  9875. }
  9876. };
  9877. if(methodInvoked) {
  9878. if(instance === undefined) {
  9879. module.initialize();
  9880. }
  9881. module.invoke(query);
  9882. }
  9883. else {
  9884. if(instance !== undefined) {
  9885. instance.invoke('destroy');
  9886. }
  9887. module.initialize();
  9888. }
  9889. })
  9890. ;
  9891. return (returnedValue !== undefined)
  9892. ? returnedValue
  9893. : this
  9894. ;
  9895. };
  9896. $.fn.nag.settings = {
  9897. name : 'Nag',
  9898. silent : false,
  9899. debug : false,
  9900. verbose : false,
  9901. performance : true,
  9902. namespace : 'Nag',
  9903. // allows cookie to be overridden
  9904. persist : false,
  9905. // set to zero to require manually dismissal, otherwise hides on its own
  9906. displayTime : 0,
  9907. animation : {
  9908. show : 'slide',
  9909. hide : 'slide'
  9910. },
  9911. context : false,
  9912. detachable : false,
  9913. expires : 30,
  9914. domain : false,
  9915. path : '/',
  9916. // type of storage to use
  9917. storageMethod : 'cookie',
  9918. // value to store in dismissed localstorage/cookie
  9919. key : 'nag',
  9920. value : 'dismiss',
  9921. error: {
  9922. noCookieStorage : '$.cookie is not included. A storage solution is required.',
  9923. noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
  9924. method : 'The method you called is not defined.'
  9925. },
  9926. className : {
  9927. bottom : 'bottom',
  9928. fixed : 'fixed'
  9929. },
  9930. selector : {
  9931. close : '.close.icon'
  9932. },
  9933. speed : 500,
  9934. easing : 'easeOutQuad',
  9935. onHide: function() {}
  9936. };
  9937. // Adds easing
  9938. $.extend( $.easing, {
  9939. easeOutQuad: function (x, t, b, c, d) {
  9940. return -c *(t/=d)*(t-2) + b;
  9941. }
  9942. });
  9943. })( jQuery, window, document );
  9944. /*!
  9945. * # Semantic UI 2.4.1 - Popup
  9946. * http://github.com/semantic-org/semantic-ui/
  9947. *
  9948. *
  9949. * Released under the MIT license
  9950. * http://opensource.org/licenses/MIT
  9951. *
  9952. */
  9953. ;(function ($, window, document, undefined) {
  9954. 'use strict';
  9955. window = (typeof window != 'undefined' && window.Math == Math)
  9956. ? window
  9957. : (typeof self != 'undefined' && self.Math == Math)
  9958. ? self
  9959. : Function('return this')()
  9960. ;
  9961. $.fn.popup = function(parameters) {
  9962. var
  9963. $allModules = $(this),
  9964. $document = $(document),
  9965. $window = $(window),
  9966. $body = $('body'),
  9967. moduleSelector = $allModules.selector || '',
  9968. hasTouch = (true),
  9969. time = new Date().getTime(),
  9970. performance = [],
  9971. query = arguments[0],
  9972. methodInvoked = (typeof query == 'string'),
  9973. queryArguments = [].slice.call(arguments, 1),
  9974. returnedValue
  9975. ;
  9976. $allModules
  9977. .each(function() {
  9978. var
  9979. settings = ( $.isPlainObject(parameters) )
  9980. ? $.extend(true, {}, $.fn.popup.settings, parameters)
  9981. : $.extend({}, $.fn.popup.settings),
  9982. selector = settings.selector,
  9983. className = settings.className,
  9984. error = settings.error,
  9985. metadata = settings.metadata,
  9986. namespace = settings.namespace,
  9987. eventNamespace = '.' + settings.namespace,
  9988. moduleNamespace = 'module-' + namespace,
  9989. $module = $(this),
  9990. $context = $(settings.context),
  9991. $scrollContext = $(settings.scrollContext),
  9992. $boundary = $(settings.boundary),
  9993. $target = (settings.target)
  9994. ? $(settings.target)
  9995. : $module,
  9996. $popup,
  9997. $offsetParent,
  9998. searchDepth = 0,
  9999. triedPositions = false,
  10000. openedWithTouch = false,
  10001. element = this,
  10002. instance = $module.data(moduleNamespace),
  10003. documentObserver,
  10004. elementNamespace,
  10005. id,
  10006. module
  10007. ;
  10008. module = {
  10009. // binds events
  10010. initialize: function() {
  10011. module.debug('Initializing', $module);
  10012. module.createID();
  10013. module.bind.events();
  10014. if(!module.exists() && settings.preserve) {
  10015. module.create();
  10016. }
  10017. if(settings.observeChanges) {
  10018. module.observeChanges();
  10019. }
  10020. module.instantiate();
  10021. },
  10022. instantiate: function() {
  10023. module.verbose('Storing instance', module);
  10024. instance = module;
  10025. $module
  10026. .data(moduleNamespace, instance)
  10027. ;
  10028. },
  10029. observeChanges: function() {
  10030. if('MutationObserver' in window) {
  10031. documentObserver = new MutationObserver(module.event.documentChanged);
  10032. documentObserver.observe(document, {
  10033. childList : true,
  10034. subtree : true
  10035. });
  10036. module.debug('Setting up mutation observer', documentObserver);
  10037. }
  10038. },
  10039. refresh: function() {
  10040. if(settings.popup) {
  10041. $popup = $(settings.popup).eq(0);
  10042. }
  10043. else {
  10044. if(settings.inline) {
  10045. $popup = $target.nextAll(selector.popup).eq(0);
  10046. settings.popup = $popup;
  10047. }
  10048. }
  10049. if(settings.popup) {
  10050. $popup.addClass(className.loading);
  10051. $offsetParent = module.get.offsetParent();
  10052. $popup.removeClass(className.loading);
  10053. if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
  10054. module.debug('Moving popup to the same offset parent as target');
  10055. $popup
  10056. .detach()
  10057. .appendTo($offsetParent)
  10058. ;
  10059. }
  10060. }
  10061. else {
  10062. $offsetParent = (settings.inline)
  10063. ? module.get.offsetParent($target)
  10064. : module.has.popup()
  10065. ? module.get.offsetParent($popup)
  10066. : $body
  10067. ;
  10068. }
  10069. if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
  10070. module.debug('Setting page as offset parent');
  10071. $offsetParent = $body;
  10072. }
  10073. if( module.get.variation() ) {
  10074. module.set.variation();
  10075. }
  10076. },
  10077. reposition: function() {
  10078. module.refresh();
  10079. module.set.position();
  10080. },
  10081. destroy: function() {
  10082. module.debug('Destroying previous module');
  10083. if(documentObserver) {
  10084. documentObserver.disconnect();
  10085. }
  10086. // remove element only if was created dynamically
  10087. if($popup && !settings.preserve) {
  10088. module.removePopup();
  10089. }
  10090. // clear all timeouts
  10091. clearTimeout(module.hideTimer);
  10092. clearTimeout(module.showTimer);
  10093. // remove events
  10094. module.unbind.close();
  10095. module.unbind.events();
  10096. $module
  10097. .removeData(moduleNamespace)
  10098. ;
  10099. },
  10100. event: {
  10101. start: function(event) {
  10102. var
  10103. delay = ($.isPlainObject(settings.delay))
  10104. ? settings.delay.show
  10105. : settings.delay
  10106. ;
  10107. clearTimeout(module.hideTimer);
  10108. if(!openedWithTouch) {
  10109. module.showTimer = setTimeout(module.show, delay);
  10110. }
  10111. },
  10112. end: function() {
  10113. var
  10114. delay = ($.isPlainObject(settings.delay))
  10115. ? settings.delay.hide
  10116. : settings.delay
  10117. ;
  10118. clearTimeout(module.showTimer);
  10119. module.hideTimer = setTimeout(module.hide, delay);
  10120. },
  10121. touchstart: function(event) {
  10122. openedWithTouch = true;
  10123. module.show();
  10124. },
  10125. resize: function() {
  10126. if( module.is.visible() ) {
  10127. module.set.position();
  10128. }
  10129. },
  10130. documentChanged: function(mutations) {
  10131. [].forEach.call(mutations, function(mutation) {
  10132. if(mutation.removedNodes) {
  10133. [].forEach.call(mutation.removedNodes, function(node) {
  10134. if(node == element || $(node).find(element).length > 0) {
  10135. module.debug('Element removed from DOM, tearing down events');
  10136. module.destroy();
  10137. }
  10138. });
  10139. }
  10140. });
  10141. },
  10142. hideGracefully: function(event) {
  10143. var
  10144. $target = $(event.target),
  10145. isInDOM = $.contains(document.documentElement, event.target),
  10146. inPopup = ($target.closest(selector.popup).length > 0)
  10147. ;
  10148. // don't close on clicks inside popup
  10149. if(event && !inPopup && isInDOM) {
  10150. module.debug('Click occurred outside popup hiding popup');
  10151. module.hide();
  10152. }
  10153. else {
  10154. module.debug('Click was inside popup, keeping popup open');
  10155. }
  10156. }
  10157. },
  10158. // generates popup html from metadata
  10159. create: function() {
  10160. var
  10161. html = module.get.html(),
  10162. title = module.get.title(),
  10163. content = module.get.content()
  10164. ;
  10165. if(html || content || title) {
  10166. module.debug('Creating pop-up html');
  10167. if(!html) {
  10168. html = settings.templates.popup({
  10169. title : title,
  10170. content : content
  10171. });
  10172. }
  10173. $popup = $('<div/>')
  10174. .addClass(className.popup)
  10175. .data(metadata.activator, $module)
  10176. .html(html)
  10177. ;
  10178. if(settings.inline) {
  10179. module.verbose('Inserting popup element inline', $popup);
  10180. $popup
  10181. .insertAfter($module)
  10182. ;
  10183. }
  10184. else {
  10185. module.verbose('Appending popup element to body', $popup);
  10186. $popup
  10187. .appendTo( $context )
  10188. ;
  10189. }
  10190. module.refresh();
  10191. module.set.variation();
  10192. if(settings.hoverable) {
  10193. module.bind.popup();
  10194. }
  10195. settings.onCreate.call($popup, element);
  10196. }
  10197. else if($target.next(selector.popup).length !== 0) {
  10198. module.verbose('Pre-existing popup found');
  10199. settings.inline = true;
  10200. settings.popup = $target.next(selector.popup).data(metadata.activator, $module);
  10201. module.refresh();
  10202. if(settings.hoverable) {
  10203. module.bind.popup();
  10204. }
  10205. }
  10206. else if(settings.popup) {
  10207. $(settings.popup).data(metadata.activator, $module);
  10208. module.verbose('Used popup specified in settings');
  10209. module.refresh();
  10210. if(settings.hoverable) {
  10211. module.bind.popup();
  10212. }
  10213. }
  10214. else {
  10215. module.debug('No content specified skipping display', element);
  10216. }
  10217. },
  10218. createID: function() {
  10219. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  10220. elementNamespace = '.' + id;
  10221. module.verbose('Creating unique id for element', id);
  10222. },
  10223. // determines popup state
  10224. toggle: function() {
  10225. module.debug('Toggling pop-up');
  10226. if( module.is.hidden() ) {
  10227. module.debug('Popup is hidden, showing pop-up');
  10228. module.unbind.close();
  10229. module.show();
  10230. }
  10231. else {
  10232. module.debug('Popup is visible, hiding pop-up');
  10233. module.hide();
  10234. }
  10235. },
  10236. show: function(callback) {
  10237. callback = callback || function(){};
  10238. module.debug('Showing pop-up', settings.transition);
  10239. if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
  10240. if( !module.exists() ) {
  10241. module.create();
  10242. }
  10243. if(settings.onShow.call($popup, element) === false) {
  10244. module.debug('onShow callback returned false, cancelling popup animation');
  10245. return;
  10246. }
  10247. else if(!settings.preserve && !settings.popup) {
  10248. module.refresh();
  10249. }
  10250. if( $popup && module.set.position() ) {
  10251. module.save.conditions();
  10252. if(settings.exclusive) {
  10253. module.hideAll();
  10254. }
  10255. module.animate.show(callback);
  10256. }
  10257. }
  10258. },
  10259. hide: function(callback) {
  10260. callback = callback || function(){};
  10261. if( module.is.visible() || module.is.animating() ) {
  10262. if(settings.onHide.call($popup, element) === false) {
  10263. module.debug('onHide callback returned false, cancelling popup animation');
  10264. return;
  10265. }
  10266. module.remove.visible();
  10267. module.unbind.close();
  10268. module.restore.conditions();
  10269. module.animate.hide(callback);
  10270. }
  10271. },
  10272. hideAll: function() {
  10273. $(selector.popup)
  10274. .filter('.' + className.popupVisible)
  10275. .each(function() {
  10276. $(this)
  10277. .data(metadata.activator)
  10278. .popup('hide')
  10279. ;
  10280. })
  10281. ;
  10282. },
  10283. exists: function() {
  10284. if(!$popup) {
  10285. return false;
  10286. }
  10287. if(settings.inline || settings.popup) {
  10288. return ( module.has.popup() );
  10289. }
  10290. else {
  10291. return ( $popup.closest($context).length >= 1 )
  10292. ? true
  10293. : false
  10294. ;
  10295. }
  10296. },
  10297. removePopup: function() {
  10298. if( module.has.popup() && !settings.popup) {
  10299. module.debug('Removing popup', $popup);
  10300. $popup.remove();
  10301. $popup = undefined;
  10302. settings.onRemove.call($popup, element);
  10303. }
  10304. },
  10305. save: {
  10306. conditions: function() {
  10307. module.cache = {
  10308. title: $module.attr('title')
  10309. };
  10310. if (module.cache.title) {
  10311. $module.removeAttr('title');
  10312. }
  10313. module.verbose('Saving original attributes', module.cache.title);
  10314. }
  10315. },
  10316. restore: {
  10317. conditions: function() {
  10318. if(module.cache && module.cache.title) {
  10319. $module.attr('title', module.cache.title);
  10320. module.verbose('Restoring original attributes', module.cache.title);
  10321. }
  10322. return true;
  10323. }
  10324. },
  10325. supports: {
  10326. svg: function() {
  10327. return (typeof SVGGraphicsElement === 'undefined');
  10328. }
  10329. },
  10330. animate: {
  10331. show: function(callback) {
  10332. callback = $.isFunction(callback) ? callback : function(){};
  10333. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  10334. module.set.visible();
  10335. $popup
  10336. .transition({
  10337. animation : settings.transition + ' in',
  10338. queue : false,
  10339. debug : settings.debug,
  10340. verbose : settings.verbose,
  10341. duration : settings.duration,
  10342. onComplete : function() {
  10343. module.bind.close();
  10344. callback.call($popup, element);
  10345. settings.onVisible.call($popup, element);
  10346. }
  10347. })
  10348. ;
  10349. }
  10350. else {
  10351. module.error(error.noTransition);
  10352. }
  10353. },
  10354. hide: function(callback) {
  10355. callback = $.isFunction(callback) ? callback : function(){};
  10356. module.debug('Hiding pop-up');
  10357. if(settings.onHide.call($popup, element) === false) {
  10358. module.debug('onHide callback returned false, cancelling popup animation');
  10359. return;
  10360. }
  10361. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  10362. $popup
  10363. .transition({
  10364. animation : settings.transition + ' out',
  10365. queue : false,
  10366. duration : settings.duration,
  10367. debug : settings.debug,
  10368. verbose : settings.verbose,
  10369. onComplete : function() {
  10370. module.reset();
  10371. callback.call($popup, element);
  10372. settings.onHidden.call($popup, element);
  10373. }
  10374. })
  10375. ;
  10376. }
  10377. else {
  10378. module.error(error.noTransition);
  10379. }
  10380. }
  10381. },
  10382. change: {
  10383. content: function(html) {
  10384. $popup.html(html);
  10385. }
  10386. },
  10387. get: {
  10388. html: function() {
  10389. $module.removeData(metadata.html);
  10390. return $module.data(metadata.html) || settings.html;
  10391. },
  10392. title: function() {
  10393. $module.removeData(metadata.title);
  10394. return $module.data(metadata.title) || settings.title;
  10395. },
  10396. content: function() {
  10397. $module.removeData(metadata.content);
  10398. return $module.data(metadata.content) || settings.content || $module.attr('title');
  10399. },
  10400. variation: function() {
  10401. $module.removeData(metadata.variation);
  10402. return $module.data(metadata.variation) || settings.variation;
  10403. },
  10404. popup: function() {
  10405. return $popup;
  10406. },
  10407. popupOffset: function() {
  10408. return $popup.offset();
  10409. },
  10410. calculations: function() {
  10411. var
  10412. $popupOffsetParent = module.get.offsetParent($popup),
  10413. targetElement = $target[0],
  10414. isWindow = ($boundary[0] == window),
  10415. targetPosition = (settings.inline || (settings.popup && settings.movePopup))
  10416. ? $target.position()
  10417. : $target.offset(),
  10418. screenPosition = (isWindow)
  10419. ? { top: 0, left: 0 }
  10420. : $boundary.offset(),
  10421. calculations = {},
  10422. scroll = (isWindow)
  10423. ? { top: $window.scrollTop(), left: $window.scrollLeft() }
  10424. : { top: 0, left: 0},
  10425. screen
  10426. ;
  10427. calculations = {
  10428. // element which is launching popup
  10429. target : {
  10430. element : $target[0],
  10431. width : $target.outerWidth(),
  10432. height : $target.outerHeight(),
  10433. top : targetPosition.top,
  10434. left : targetPosition.left,
  10435. margin : {}
  10436. },
  10437. // popup itself
  10438. popup : {
  10439. width : $popup.outerWidth(),
  10440. height : $popup.outerHeight()
  10441. },
  10442. // offset container (or 3d context)
  10443. parent : {
  10444. width : $offsetParent.outerWidth(),
  10445. height : $offsetParent.outerHeight()
  10446. },
  10447. // screen boundaries
  10448. screen : {
  10449. top : screenPosition.top,
  10450. left : screenPosition.left,
  10451. scroll: {
  10452. top : scroll.top,
  10453. left : scroll.left
  10454. },
  10455. width : $boundary.width(),
  10456. height : $boundary.height()
  10457. }
  10458. };
  10459. // if popup offset context is not same as target, then adjust calculations
  10460. if($popupOffsetParent.get(0) !== $offsetParent.get(0)) {
  10461. var
  10462. popupOffset = $popupOffsetParent.offset()
  10463. ;
  10464. calculations.target.top -= popupOffset.top;
  10465. calculations.target.left -= popupOffset.left;
  10466. calculations.parent.width = $popupOffsetParent.outerWidth();
  10467. calculations.parent.height = $popupOffsetParent.outerHeight();
  10468. }
  10469. // add in container calcs if fluid
  10470. if( settings.setFluidWidth && module.is.fluid() ) {
  10471. calculations.container = {
  10472. width: $popup.parent().outerWidth()
  10473. };
  10474. calculations.popup.width = calculations.container.width;
  10475. }
  10476. // add in margins if inline
  10477. calculations.target.margin.top = (settings.inline)
  10478. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
  10479. : 0
  10480. ;
  10481. calculations.target.margin.left = (settings.inline)
  10482. ? module.is.rtl()
  10483. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
  10484. : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
  10485. : 0
  10486. ;
  10487. // calculate screen boundaries
  10488. screen = calculations.screen;
  10489. calculations.boundary = {
  10490. top : screen.top + screen.scroll.top,
  10491. bottom : screen.top + screen.scroll.top + screen.height,
  10492. left : screen.left + screen.scroll.left,
  10493. right : screen.left + screen.scroll.left + screen.width
  10494. };
  10495. return calculations;
  10496. },
  10497. id: function() {
  10498. return id;
  10499. },
  10500. startEvent: function() {
  10501. if(settings.on == 'hover') {
  10502. return 'mouseenter';
  10503. }
  10504. else if(settings.on == 'focus') {
  10505. return 'focus';
  10506. }
  10507. return false;
  10508. },
  10509. scrollEvent: function() {
  10510. return 'scroll';
  10511. },
  10512. endEvent: function() {
  10513. if(settings.on == 'hover') {
  10514. return 'mouseleave';
  10515. }
  10516. else if(settings.on == 'focus') {
  10517. return 'blur';
  10518. }
  10519. return false;
  10520. },
  10521. distanceFromBoundary: function(offset, calculations) {
  10522. var
  10523. distanceFromBoundary = {},
  10524. popup,
  10525. boundary
  10526. ;
  10527. calculations = calculations || module.get.calculations();
  10528. // shorthand
  10529. popup = calculations.popup;
  10530. boundary = calculations.boundary;
  10531. if(offset) {
  10532. distanceFromBoundary = {
  10533. top : (offset.top - boundary.top),
  10534. left : (offset.left - boundary.left),
  10535. right : (boundary.right - (offset.left + popup.width) ),
  10536. bottom : (boundary.bottom - (offset.top + popup.height) )
  10537. };
  10538. module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
  10539. }
  10540. return distanceFromBoundary;
  10541. },
  10542. offsetParent: function($element) {
  10543. var
  10544. element = ($element !== undefined)
  10545. ? $element[0]
  10546. : $target[0],
  10547. parentNode = element.parentNode,
  10548. $node = $(parentNode)
  10549. ;
  10550. if(parentNode) {
  10551. var
  10552. is2D = ($node.css('transform') === 'none'),
  10553. isStatic = ($node.css('position') === 'static'),
  10554. isBody = $node.is('body')
  10555. ;
  10556. while(parentNode && !isBody && isStatic && is2D) {
  10557. parentNode = parentNode.parentNode;
  10558. $node = $(parentNode);
  10559. is2D = ($node.css('transform') === 'none');
  10560. isStatic = ($node.css('position') === 'static');
  10561. isBody = $node.is('body');
  10562. }
  10563. }
  10564. return ($node && $node.length > 0)
  10565. ? $node
  10566. : $()
  10567. ;
  10568. },
  10569. positions: function() {
  10570. return {
  10571. 'top left' : false,
  10572. 'top center' : false,
  10573. 'top right' : false,
  10574. 'bottom left' : false,
  10575. 'bottom center' : false,
  10576. 'bottom right' : false,
  10577. 'left center' : false,
  10578. 'right center' : false
  10579. };
  10580. },
  10581. nextPosition: function(position) {
  10582. var
  10583. positions = position.split(' '),
  10584. verticalPosition = positions[0],
  10585. horizontalPosition = positions[1],
  10586. opposite = {
  10587. top : 'bottom',
  10588. bottom : 'top',
  10589. left : 'right',
  10590. right : 'left'
  10591. },
  10592. adjacent = {
  10593. left : 'center',
  10594. center : 'right',
  10595. right : 'left'
  10596. },
  10597. backup = {
  10598. 'top left' : 'top center',
  10599. 'top center' : 'top right',
  10600. 'top right' : 'right center',
  10601. 'right center' : 'bottom right',
  10602. 'bottom right' : 'bottom center',
  10603. 'bottom center' : 'bottom left',
  10604. 'bottom left' : 'left center',
  10605. 'left center' : 'top left'
  10606. },
  10607. adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
  10608. oppositeTried = false,
  10609. adjacentTried = false,
  10610. nextPosition = false
  10611. ;
  10612. if(!triedPositions) {
  10613. module.verbose('All available positions available');
  10614. triedPositions = module.get.positions();
  10615. }
  10616. module.debug('Recording last position tried', position);
  10617. triedPositions[position] = true;
  10618. if(settings.prefer === 'opposite') {
  10619. nextPosition = [opposite[verticalPosition], horizontalPosition];
  10620. nextPosition = nextPosition.join(' ');
  10621. oppositeTried = (triedPositions[nextPosition] === true);
  10622. module.debug('Trying opposite strategy', nextPosition);
  10623. }
  10624. if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
  10625. nextPosition = [verticalPosition, adjacent[horizontalPosition]];
  10626. nextPosition = nextPosition.join(' ');
  10627. adjacentTried = (triedPositions[nextPosition] === true);
  10628. module.debug('Trying adjacent strategy', nextPosition);
  10629. }
  10630. if(adjacentTried || oppositeTried) {
  10631. module.debug('Using backup position', nextPosition);
  10632. nextPosition = backup[position];
  10633. }
  10634. return nextPosition;
  10635. }
  10636. },
  10637. set: {
  10638. position: function(position, calculations) {
  10639. // exit conditions
  10640. if($target.length === 0 || $popup.length === 0) {
  10641. module.error(error.notFound);
  10642. return;
  10643. }
  10644. var
  10645. offset,
  10646. distanceAway,
  10647. target,
  10648. popup,
  10649. parent,
  10650. positioning,
  10651. popupOffset,
  10652. distanceFromBoundary
  10653. ;
  10654. calculations = calculations || module.get.calculations();
  10655. position = position || $module.data(metadata.position) || settings.position;
  10656. offset = $module.data(metadata.offset) || settings.offset;
  10657. distanceAway = settings.distanceAway;
  10658. // shorthand
  10659. target = calculations.target;
  10660. popup = calculations.popup;
  10661. parent = calculations.parent;
  10662. if(module.should.centerArrow(calculations)) {
  10663. module.verbose('Adjusting offset to center arrow on small target element');
  10664. if(position == 'top left' || position == 'bottom left') {
  10665. offset += (target.width / 2)
  10666. offset -= settings.arrowPixelsFromEdge;
  10667. }
  10668. if(position == 'top right' || position == 'bottom right') {
  10669. offset -= (target.width / 2)
  10670. offset += settings.arrowPixelsFromEdge;
  10671. }
  10672. }
  10673. if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) {
  10674. module.debug('Popup target is hidden, no action taken');
  10675. return false;
  10676. }
  10677. if(settings.inline) {
  10678. module.debug('Adding margin to calculation', target.margin);
  10679. if(position == 'left center' || position == 'right center') {
  10680. offset += target.margin.top;
  10681. distanceAway += -target.margin.left;
  10682. }
  10683. else if (position == 'top left' || position == 'top center' || position == 'top right') {
  10684. offset += target.margin.left;
  10685. distanceAway -= target.margin.top;
  10686. }
  10687. else {
  10688. offset += target.margin.left;
  10689. distanceAway += target.margin.top;
  10690. }
  10691. }
  10692. module.debug('Determining popup position from calculations', position, calculations);
  10693. if (module.is.rtl()) {
  10694. position = position.replace(/left|right/g, function (match) {
  10695. return (match == 'left')
  10696. ? 'right'
  10697. : 'left'
  10698. ;
  10699. });
  10700. module.debug('RTL: Popup position updated', position);
  10701. }
  10702. // if last attempt use specified last resort position
  10703. if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
  10704. position = settings.lastResort;
  10705. }
  10706. switch (position) {
  10707. case 'top left':
  10708. positioning = {
  10709. top : 'auto',
  10710. bottom : parent.height - target.top + distanceAway,
  10711. left : target.left + offset,
  10712. right : 'auto'
  10713. };
  10714. break;
  10715. case 'top center':
  10716. positioning = {
  10717. bottom : parent.height - target.top + distanceAway,
  10718. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  10719. top : 'auto',
  10720. right : 'auto'
  10721. };
  10722. break;
  10723. case 'top right':
  10724. positioning = {
  10725. bottom : parent.height - target.top + distanceAway,
  10726. right : parent.width - target.left - target.width - offset,
  10727. top : 'auto',
  10728. left : 'auto'
  10729. };
  10730. break;
  10731. case 'left center':
  10732. positioning = {
  10733. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  10734. right : parent.width - target.left + distanceAway,
  10735. left : 'auto',
  10736. bottom : 'auto'
  10737. };
  10738. break;
  10739. case 'right center':
  10740. positioning = {
  10741. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  10742. left : target.left + target.width + distanceAway,
  10743. bottom : 'auto',
  10744. right : 'auto'
  10745. };
  10746. break;
  10747. case 'bottom left':
  10748. positioning = {
  10749. top : target.top + target.height + distanceAway,
  10750. left : target.left + offset,
  10751. bottom : 'auto',
  10752. right : 'auto'
  10753. };
  10754. break;
  10755. case 'bottom center':
  10756. positioning = {
  10757. top : target.top + target.height + distanceAway,
  10758. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  10759. bottom : 'auto',
  10760. right : 'auto'
  10761. };
  10762. break;
  10763. case 'bottom right':
  10764. positioning = {
  10765. top : target.top + target.height + distanceAway,
  10766. right : parent.width - target.left - target.width - offset,
  10767. left : 'auto',
  10768. bottom : 'auto'
  10769. };
  10770. break;
  10771. }
  10772. if(positioning === undefined) {
  10773. module.error(error.invalidPosition, position);
  10774. }
  10775. module.debug('Calculated popup positioning values', positioning);
  10776. // tentatively place on stage
  10777. $popup
  10778. .css(positioning)
  10779. .removeClass(className.position)
  10780. .addClass(position)
  10781. .addClass(className.loading)
  10782. ;
  10783. popupOffset = module.get.popupOffset();
  10784. // see if any boundaries are surpassed with this tentative position
  10785. distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
  10786. if( module.is.offstage(distanceFromBoundary, position) ) {
  10787. module.debug('Position is outside viewport', position);
  10788. if(searchDepth < settings.maxSearchDepth) {
  10789. searchDepth++;
  10790. position = module.get.nextPosition(position);
  10791. module.debug('Trying new position', position);
  10792. return ($popup)
  10793. ? module.set.position(position, calculations)
  10794. : false
  10795. ;
  10796. }
  10797. else {
  10798. if(settings.lastResort) {
  10799. module.debug('No position found, showing with last position');
  10800. }
  10801. else {
  10802. module.debug('Popup could not find a position to display', $popup);
  10803. module.error(error.cannotPlace, element);
  10804. module.remove.attempts();
  10805. module.remove.loading();
  10806. module.reset();
  10807. settings.onUnplaceable.call($popup, element);
  10808. return false;
  10809. }
  10810. }
  10811. }
  10812. module.debug('Position is on stage', position);
  10813. module.remove.attempts();
  10814. module.remove.loading();
  10815. if( settings.setFluidWidth && module.is.fluid() ) {
  10816. module.set.fluidWidth(calculations);
  10817. }
  10818. return true;
  10819. },
  10820. fluidWidth: function(calculations) {
  10821. calculations = calculations || module.get.calculations();
  10822. module.debug('Automatically setting element width to parent width', calculations.parent.width);
  10823. $popup.css('width', calculations.container.width);
  10824. },
  10825. variation: function(variation) {
  10826. variation = variation || module.get.variation();
  10827. if(variation && module.has.popup() ) {
  10828. module.verbose('Adding variation to popup', variation);
  10829. $popup.addClass(variation);
  10830. }
  10831. },
  10832. visible: function() {
  10833. $module.addClass(className.visible);
  10834. }
  10835. },
  10836. remove: {
  10837. loading: function() {
  10838. $popup.removeClass(className.loading);
  10839. },
  10840. variation: function(variation) {
  10841. variation = variation || module.get.variation();
  10842. if(variation) {
  10843. module.verbose('Removing variation', variation);
  10844. $popup.removeClass(variation);
  10845. }
  10846. },
  10847. visible: function() {
  10848. $module.removeClass(className.visible);
  10849. },
  10850. attempts: function() {
  10851. module.verbose('Resetting all searched positions');
  10852. searchDepth = 0;
  10853. triedPositions = false;
  10854. }
  10855. },
  10856. bind: {
  10857. events: function() {
  10858. module.debug('Binding popup events to module');
  10859. if(settings.on == 'click') {
  10860. $module
  10861. .on('click' + eventNamespace, module.toggle)
  10862. ;
  10863. }
  10864. if(settings.on == 'hover' && hasTouch) {
  10865. $module
  10866. .on('touchstart' + eventNamespace, module.event.touchstart)
  10867. ;
  10868. }
  10869. if( module.get.startEvent() ) {
  10870. $module
  10871. .on(module.get.startEvent() + eventNamespace, module.event.start)
  10872. .on(module.get.endEvent() + eventNamespace, module.event.end)
  10873. ;
  10874. }
  10875. if(settings.target) {
  10876. module.debug('Target set to element', $target);
  10877. }
  10878. $window.on('resize' + elementNamespace, module.event.resize);
  10879. },
  10880. popup: function() {
  10881. module.verbose('Allowing hover events on popup to prevent closing');
  10882. if( $popup && module.has.popup() ) {
  10883. $popup
  10884. .on('mouseenter' + eventNamespace, module.event.start)
  10885. .on('mouseleave' + eventNamespace, module.event.end)
  10886. ;
  10887. }
  10888. },
  10889. close: function() {
  10890. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  10891. module.bind.closeOnScroll();
  10892. }
  10893. if(module.is.closable()) {
  10894. module.bind.clickaway();
  10895. }
  10896. else if(settings.on == 'hover' && openedWithTouch) {
  10897. module.bind.touchClose();
  10898. }
  10899. },
  10900. closeOnScroll: function() {
  10901. module.verbose('Binding scroll close event to document');
  10902. $scrollContext
  10903. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  10904. ;
  10905. },
  10906. touchClose: function() {
  10907. module.verbose('Binding popup touchclose event to document');
  10908. $document
  10909. .on('touchstart' + elementNamespace, function(event) {
  10910. module.verbose('Touched away from popup');
  10911. module.event.hideGracefully.call(element, event);
  10912. })
  10913. ;
  10914. },
  10915. clickaway: function() {
  10916. module.verbose('Binding popup close event to document');
  10917. $document
  10918. .on('click' + elementNamespace, function(event) {
  10919. module.verbose('Clicked away from popup');
  10920. module.event.hideGracefully.call(element, event);
  10921. })
  10922. ;
  10923. }
  10924. },
  10925. unbind: {
  10926. events: function() {
  10927. $window
  10928. .off(elementNamespace)
  10929. ;
  10930. $module
  10931. .off(eventNamespace)
  10932. ;
  10933. },
  10934. close: function() {
  10935. $document
  10936. .off(elementNamespace)
  10937. ;
  10938. $scrollContext
  10939. .off(elementNamespace)
  10940. ;
  10941. },
  10942. },
  10943. has: {
  10944. popup: function() {
  10945. return ($popup && $popup.length > 0);
  10946. }
  10947. },
  10948. should: {
  10949. centerArrow: function(calculations) {
  10950. return !module.is.basic() && calculations.target.width <= (settings.arrowPixelsFromEdge * 2);
  10951. },
  10952. },
  10953. is: {
  10954. closable: function() {
  10955. if(settings.closable == 'auto') {
  10956. if(settings.on == 'hover') {
  10957. return false;
  10958. }
  10959. return true;
  10960. }
  10961. return settings.closable;
  10962. },
  10963. offstage: function(distanceFromBoundary, position) {
  10964. var
  10965. offstage = []
  10966. ;
  10967. // return boundaries that have been surpassed
  10968. $.each(distanceFromBoundary, function(direction, distance) {
  10969. if(distance < -settings.jitter) {
  10970. module.debug('Position exceeds allowable distance from edge', direction, distance, position);
  10971. offstage.push(direction);
  10972. }
  10973. });
  10974. if(offstage.length > 0) {
  10975. return true;
  10976. }
  10977. else {
  10978. return false;
  10979. }
  10980. },
  10981. svg: function(element) {
  10982. return module.supports.svg() && (element instanceof SVGGraphicsElement);
  10983. },
  10984. basic: function() {
  10985. return $module.hasClass(className.basic);
  10986. },
  10987. active: function() {
  10988. return $module.hasClass(className.active);
  10989. },
  10990. animating: function() {
  10991. return ($popup !== undefined && $popup.hasClass(className.animating) );
  10992. },
  10993. fluid: function() {
  10994. return ($popup !== undefined && $popup.hasClass(className.fluid));
  10995. },
  10996. visible: function() {
  10997. return ($popup !== undefined && $popup.hasClass(className.popupVisible));
  10998. },
  10999. dropdown: function() {
  11000. return $module.hasClass(className.dropdown);
  11001. },
  11002. hidden: function() {
  11003. return !module.is.visible();
  11004. },
  11005. rtl: function () {
  11006. return $module.css('direction') == 'rtl';
  11007. }
  11008. },
  11009. reset: function() {
  11010. module.remove.visible();
  11011. if(settings.preserve) {
  11012. if($.fn.transition !== undefined) {
  11013. $popup
  11014. .transition('remove transition')
  11015. ;
  11016. }
  11017. }
  11018. else {
  11019. module.removePopup();
  11020. }
  11021. },
  11022. setting: function(name, value) {
  11023. if( $.isPlainObject(name) ) {
  11024. $.extend(true, settings, name);
  11025. }
  11026. else if(value !== undefined) {
  11027. settings[name] = value;
  11028. }
  11029. else {
  11030. return settings[name];
  11031. }
  11032. },
  11033. internal: function(name, value) {
  11034. if( $.isPlainObject(name) ) {
  11035. $.extend(true, module, name);
  11036. }
  11037. else if(value !== undefined) {
  11038. module[name] = value;
  11039. }
  11040. else {
  11041. return module[name];
  11042. }
  11043. },
  11044. debug: function() {
  11045. if(!settings.silent && settings.debug) {
  11046. if(settings.performance) {
  11047. module.performance.log(arguments);
  11048. }
  11049. else {
  11050. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11051. module.debug.apply(console, arguments);
  11052. }
  11053. }
  11054. },
  11055. verbose: function() {
  11056. if(!settings.silent && settings.verbose && settings.debug) {
  11057. if(settings.performance) {
  11058. module.performance.log(arguments);
  11059. }
  11060. else {
  11061. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11062. module.verbose.apply(console, arguments);
  11063. }
  11064. }
  11065. },
  11066. error: function() {
  11067. if(!settings.silent) {
  11068. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  11069. module.error.apply(console, arguments);
  11070. }
  11071. },
  11072. performance: {
  11073. log: function(message) {
  11074. var
  11075. currentTime,
  11076. executionTime,
  11077. previousTime
  11078. ;
  11079. if(settings.performance) {
  11080. currentTime = new Date().getTime();
  11081. previousTime = time || currentTime;
  11082. executionTime = currentTime - previousTime;
  11083. time = currentTime;
  11084. performance.push({
  11085. 'Name' : message[0],
  11086. 'Arguments' : [].slice.call(message, 1) || '',
  11087. 'Element' : element,
  11088. 'Execution Time' : executionTime
  11089. });
  11090. }
  11091. clearTimeout(module.performance.timer);
  11092. module.performance.timer = setTimeout(module.performance.display, 500);
  11093. },
  11094. display: function() {
  11095. var
  11096. title = settings.name + ':',
  11097. totalTime = 0
  11098. ;
  11099. time = false;
  11100. clearTimeout(module.performance.timer);
  11101. $.each(performance, function(index, data) {
  11102. totalTime += data['Execution Time'];
  11103. });
  11104. title += ' ' + totalTime + 'ms';
  11105. if(moduleSelector) {
  11106. title += ' \'' + moduleSelector + '\'';
  11107. }
  11108. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  11109. console.groupCollapsed(title);
  11110. if(console.table) {
  11111. console.table(performance);
  11112. }
  11113. else {
  11114. $.each(performance, function(index, data) {
  11115. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  11116. });
  11117. }
  11118. console.groupEnd();
  11119. }
  11120. performance = [];
  11121. }
  11122. },
  11123. invoke: function(query, passedArguments, context) {
  11124. var
  11125. object = instance,
  11126. maxDepth,
  11127. found,
  11128. response
  11129. ;
  11130. passedArguments = passedArguments || queryArguments;
  11131. context = element || context;
  11132. if(typeof query == 'string' && object !== undefined) {
  11133. query = query.split(/[\. ]/);
  11134. maxDepth = query.length - 1;
  11135. $.each(query, function(depth, value) {
  11136. var camelCaseValue = (depth != maxDepth)
  11137. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  11138. : query
  11139. ;
  11140. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  11141. object = object[camelCaseValue];
  11142. }
  11143. else if( object[camelCaseValue] !== undefined ) {
  11144. found = object[camelCaseValue];
  11145. return false;
  11146. }
  11147. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  11148. object = object[value];
  11149. }
  11150. else if( object[value] !== undefined ) {
  11151. found = object[value];
  11152. return false;
  11153. }
  11154. else {
  11155. return false;
  11156. }
  11157. });
  11158. }
  11159. if ( $.isFunction( found ) ) {
  11160. response = found.apply(context, passedArguments);
  11161. }
  11162. else if(found !== undefined) {
  11163. response = found;
  11164. }
  11165. if($.isArray(returnedValue)) {
  11166. returnedValue.push(response);
  11167. }
  11168. else if(returnedValue !== undefined) {
  11169. returnedValue = [returnedValue, response];
  11170. }
  11171. else if(response !== undefined) {
  11172. returnedValue = response;
  11173. }
  11174. return found;
  11175. }
  11176. };
  11177. if(methodInvoked) {
  11178. if(instance === undefined) {
  11179. module.initialize();
  11180. }
  11181. module.invoke(query);
  11182. }
  11183. else {
  11184. if(instance !== undefined) {
  11185. instance.invoke('destroy');
  11186. }
  11187. module.initialize();
  11188. }
  11189. })
  11190. ;
  11191. return (returnedValue !== undefined)
  11192. ? returnedValue
  11193. : this
  11194. ;
  11195. };
  11196. $.fn.popup.settings = {
  11197. name : 'Popup',
  11198. // module settings
  11199. silent : false,
  11200. debug : false,
  11201. verbose : false,
  11202. performance : true,
  11203. namespace : 'popup',
  11204. // whether it should use dom mutation observers
  11205. observeChanges : true,
  11206. // callback only when element added to dom
  11207. onCreate : function(){},
  11208. // callback before element removed from dom
  11209. onRemove : function(){},
  11210. // callback before show animation
  11211. onShow : function(){},
  11212. // callback after show animation
  11213. onVisible : function(){},
  11214. // callback before hide animation
  11215. onHide : function(){},
  11216. // callback when popup cannot be positioned in visible screen
  11217. onUnplaceable : function(){},
  11218. // callback after hide animation
  11219. onHidden : function(){},
  11220. // when to show popup
  11221. on : 'hover',
  11222. // element to use to determine if popup is out of boundary
  11223. boundary : window,
  11224. // whether to add touchstart events when using hover
  11225. addTouchEvents : true,
  11226. // default position relative to element
  11227. position : 'top left',
  11228. // name of variation to use
  11229. variation : '',
  11230. // whether popup should be moved to context
  11231. movePopup : true,
  11232. // element which popup should be relative to
  11233. target : false,
  11234. // jq selector or element that should be used as popup
  11235. popup : false,
  11236. // popup should remain inline next to activator
  11237. inline : false,
  11238. // popup should be removed from page on hide
  11239. preserve : false,
  11240. // popup should not close when being hovered on
  11241. hoverable : false,
  11242. // explicitly set content
  11243. content : false,
  11244. // explicitly set html
  11245. html : false,
  11246. // explicitly set title
  11247. title : false,
  11248. // whether automatically close on clickaway when on click
  11249. closable : true,
  11250. // automatically hide on scroll
  11251. hideOnScroll : 'auto',
  11252. // hide other popups on show
  11253. exclusive : false,
  11254. // context to attach popups
  11255. context : 'body',
  11256. // context for binding scroll events
  11257. scrollContext : window,
  11258. // position to prefer when calculating new position
  11259. prefer : 'opposite',
  11260. // specify position to appear even if it doesn't fit
  11261. lastResort : false,
  11262. // number of pixels from edge of popup to pointing arrow center (used from centering)
  11263. arrowPixelsFromEdge: 20,
  11264. // delay used to prevent accidental refiring of animations due to user error
  11265. delay : {
  11266. show : 50,
  11267. hide : 70
  11268. },
  11269. // whether fluid variation should assign width explicitly
  11270. setFluidWidth : true,
  11271. // transition settings
  11272. duration : 200,
  11273. transition : 'scale',
  11274. // distance away from activating element in px
  11275. distanceAway : 0,
  11276. // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
  11277. jitter : 2,
  11278. // offset on aligning axis from calculated position
  11279. offset : 0,
  11280. // maximum times to look for a position before failing (9 positions total)
  11281. maxSearchDepth : 15,
  11282. error: {
  11283. invalidPosition : 'The position you specified is not a valid position',
  11284. cannotPlace : 'Popup does not fit within the boundaries of the viewport',
  11285. method : 'The method you called is not defined.',
  11286. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  11287. notFound : 'The target or popup you specified does not exist on the page'
  11288. },
  11289. metadata: {
  11290. activator : 'activator',
  11291. content : 'content',
  11292. html : 'html',
  11293. offset : 'offset',
  11294. position : 'position',
  11295. title : 'title',
  11296. variation : 'variation'
  11297. },
  11298. className : {
  11299. active : 'active',
  11300. basic : 'basic',
  11301. animating : 'animating',
  11302. dropdown : 'dropdown',
  11303. fluid : 'fluid',
  11304. loading : 'loading',
  11305. popup : 'ui popup',
  11306. position : 'top left center bottom right',
  11307. visible : 'visible',
  11308. popupVisible : 'visible'
  11309. },
  11310. selector : {
  11311. popup : '.ui.popup'
  11312. },
  11313. templates: {
  11314. escape: function(string) {
  11315. var
  11316. badChars = /[&<>"'`]/g,
  11317. shouldEscape = /[&<>"'`]/,
  11318. escape = {
  11319. "&": "&amp;",
  11320. "<": "&lt;",
  11321. ">": "&gt;",
  11322. '"': "&quot;",
  11323. "'": "&#x27;",
  11324. "`": "&#x60;"
  11325. },
  11326. escapedChar = function(chr) {
  11327. return escape[chr];
  11328. }
  11329. ;
  11330. if(shouldEscape.test(string)) {
  11331. return string.replace(badChars, escapedChar);
  11332. }
  11333. return string;
  11334. },
  11335. popup: function(text) {
  11336. var
  11337. html = '',
  11338. escape = $.fn.popup.settings.templates.escape
  11339. ;
  11340. if(typeof text !== undefined) {
  11341. if(typeof text.title !== undefined && text.title) {
  11342. text.title = escape(text.title);
  11343. html += '<div class="header">' + text.title + '</div>';
  11344. }
  11345. if(typeof text.content !== undefined && text.content) {
  11346. text.content = escape(text.content);
  11347. html += '<div class="content">' + text.content + '</div>';
  11348. }
  11349. }
  11350. return html;
  11351. }
  11352. }
  11353. };
  11354. })( jQuery, window, document );
  11355. /*!
  11356. * # Semantic UI 2.4.1 - Progress
  11357. * http://github.com/semantic-org/semantic-ui/
  11358. *
  11359. *
  11360. * Released under the MIT license
  11361. * http://opensource.org/licenses/MIT
  11362. *
  11363. */
  11364. ;(function ($, window, document, undefined) {
  11365. 'use strict';
  11366. window = (typeof window != 'undefined' && window.Math == Math)
  11367. ? window
  11368. : (typeof self != 'undefined' && self.Math == Math)
  11369. ? self
  11370. : Function('return this')()
  11371. ;
  11372. var
  11373. global = (typeof window != 'undefined' && window.Math == Math)
  11374. ? window
  11375. : (typeof self != 'undefined' && self.Math == Math)
  11376. ? self
  11377. : Function('return this')()
  11378. ;
  11379. $.fn.progress = function(parameters) {
  11380. var
  11381. $allModules = $(this),
  11382. moduleSelector = $allModules.selector || '',
  11383. time = new Date().getTime(),
  11384. performance = [],
  11385. query = arguments[0],
  11386. methodInvoked = (typeof query == 'string'),
  11387. queryArguments = [].slice.call(arguments, 1),
  11388. returnedValue
  11389. ;
  11390. $allModules
  11391. .each(function() {
  11392. var
  11393. settings = ( $.isPlainObject(parameters) )
  11394. ? $.extend(true, {}, $.fn.progress.settings, parameters)
  11395. : $.extend({}, $.fn.progress.settings),
  11396. className = settings.className,
  11397. metadata = settings.metadata,
  11398. namespace = settings.namespace,
  11399. selector = settings.selector,
  11400. error = settings.error,
  11401. eventNamespace = '.' + namespace,
  11402. moduleNamespace = 'module-' + namespace,
  11403. $module = $(this),
  11404. $bar = $(this).find(selector.bar),
  11405. $progress = $(this).find(selector.progress),
  11406. $label = $(this).find(selector.label),
  11407. element = this,
  11408. instance = $module.data(moduleNamespace),
  11409. animating = false,
  11410. transitionEnd,
  11411. module
  11412. ;
  11413. module = {
  11414. initialize: function() {
  11415. module.debug('Initializing progress bar', settings);
  11416. module.set.duration();
  11417. module.set.transitionEvent();
  11418. module.read.metadata();
  11419. module.read.settings();
  11420. module.instantiate();
  11421. },
  11422. instantiate: function() {
  11423. module.verbose('Storing instance of progress', module);
  11424. instance = module;
  11425. $module
  11426. .data(moduleNamespace, module)
  11427. ;
  11428. },
  11429. destroy: function() {
  11430. module.verbose('Destroying previous progress for', $module);
  11431. clearInterval(instance.interval);
  11432. module.remove.state();
  11433. $module.removeData(moduleNamespace);
  11434. instance = undefined;
  11435. },
  11436. reset: function() {
  11437. module.remove.nextValue();
  11438. module.update.progress(0);
  11439. },
  11440. complete: function() {
  11441. if(module.percent === undefined || module.percent < 100) {
  11442. module.remove.progressPoll();
  11443. module.set.percent(100);
  11444. }
  11445. },
  11446. read: {
  11447. metadata: function() {
  11448. var
  11449. data = {
  11450. percent : $module.data(metadata.percent),
  11451. total : $module.data(metadata.total),
  11452. value : $module.data(metadata.value)
  11453. }
  11454. ;
  11455. if(data.percent) {
  11456. module.debug('Current percent value set from metadata', data.percent);
  11457. module.set.percent(data.percent);
  11458. }
  11459. if(data.total) {
  11460. module.debug('Total value set from metadata', data.total);
  11461. module.set.total(data.total);
  11462. }
  11463. if(data.value) {
  11464. module.debug('Current value set from metadata', data.value);
  11465. module.set.value(data.value);
  11466. module.set.progress(data.value);
  11467. }
  11468. },
  11469. settings: function() {
  11470. if(settings.total !== false) {
  11471. module.debug('Current total set in settings', settings.total);
  11472. module.set.total(settings.total);
  11473. }
  11474. if(settings.value !== false) {
  11475. module.debug('Current value set in settings', settings.value);
  11476. module.set.value(settings.value);
  11477. module.set.progress(module.value);
  11478. }
  11479. if(settings.percent !== false) {
  11480. module.debug('Current percent set in settings', settings.percent);
  11481. module.set.percent(settings.percent);
  11482. }
  11483. }
  11484. },
  11485. bind: {
  11486. transitionEnd: function(callback) {
  11487. var
  11488. transitionEnd = module.get.transitionEnd()
  11489. ;
  11490. $bar
  11491. .one(transitionEnd + eventNamespace, function(event) {
  11492. clearTimeout(module.failSafeTimer);
  11493. callback.call(this, event);
  11494. })
  11495. ;
  11496. module.failSafeTimer = setTimeout(function() {
  11497. $bar.triggerHandler(transitionEnd);
  11498. }, settings.duration + settings.failSafeDelay);
  11499. module.verbose('Adding fail safe timer', module.timer);
  11500. }
  11501. },
  11502. increment: function(incrementValue) {
  11503. var
  11504. maxValue,
  11505. startValue,
  11506. newValue
  11507. ;
  11508. if( module.has.total() ) {
  11509. startValue = module.get.value();
  11510. incrementValue = incrementValue || 1;
  11511. newValue = startValue + incrementValue;
  11512. }
  11513. else {
  11514. startValue = module.get.percent();
  11515. incrementValue = incrementValue || module.get.randomValue();
  11516. newValue = startValue + incrementValue;
  11517. maxValue = 100;
  11518. module.debug('Incrementing percentage by', startValue, newValue);
  11519. }
  11520. newValue = module.get.normalizedValue(newValue);
  11521. module.set.progress(newValue);
  11522. },
  11523. decrement: function(decrementValue) {
  11524. var
  11525. total = module.get.total(),
  11526. startValue,
  11527. newValue
  11528. ;
  11529. if(total) {
  11530. startValue = module.get.value();
  11531. decrementValue = decrementValue || 1;
  11532. newValue = startValue - decrementValue;
  11533. module.debug('Decrementing value by', decrementValue, startValue);
  11534. }
  11535. else {
  11536. startValue = module.get.percent();
  11537. decrementValue = decrementValue || module.get.randomValue();
  11538. newValue = startValue - decrementValue;
  11539. module.debug('Decrementing percentage by', decrementValue, startValue);
  11540. }
  11541. newValue = module.get.normalizedValue(newValue);
  11542. module.set.progress(newValue);
  11543. },
  11544. has: {
  11545. progressPoll: function() {
  11546. return module.progressPoll;
  11547. },
  11548. total: function() {
  11549. return (module.get.total() !== false);
  11550. }
  11551. },
  11552. get: {
  11553. text: function(templateText) {
  11554. var
  11555. value = module.value || 0,
  11556. total = module.total || 0,
  11557. percent = (animating)
  11558. ? module.get.displayPercent()
  11559. : module.percent || 0,
  11560. left = (module.total > 0)
  11561. ? (total - value)
  11562. : (100 - percent)
  11563. ;
  11564. templateText = templateText || '';
  11565. templateText = templateText
  11566. .replace('{value}', value)
  11567. .replace('{total}', total)
  11568. .replace('{left}', left)
  11569. .replace('{percent}', percent)
  11570. ;
  11571. module.verbose('Adding variables to progress bar text', templateText);
  11572. return templateText;
  11573. },
  11574. normalizedValue: function(value) {
  11575. if(value < 0) {
  11576. module.debug('Value cannot decrement below 0');
  11577. return 0;
  11578. }
  11579. if(module.has.total()) {
  11580. if(value > module.total) {
  11581. module.debug('Value cannot increment above total', module.total);
  11582. return module.total;
  11583. }
  11584. }
  11585. else if(value > 100 ) {
  11586. module.debug('Value cannot increment above 100 percent');
  11587. return 100;
  11588. }
  11589. return value;
  11590. },
  11591. updateInterval: function() {
  11592. if(settings.updateInterval == 'auto') {
  11593. return settings.duration;
  11594. }
  11595. return settings.updateInterval;
  11596. },
  11597. randomValue: function() {
  11598. module.debug('Generating random increment percentage');
  11599. return Math.floor((Math.random() * settings.random.max) + settings.random.min);
  11600. },
  11601. numericValue: function(value) {
  11602. return (typeof value === 'string')
  11603. ? (value.replace(/[^\d.]/g, '') !== '')
  11604. ? +(value.replace(/[^\d.]/g, ''))
  11605. : false
  11606. : value
  11607. ;
  11608. },
  11609. transitionEnd: function() {
  11610. var
  11611. element = document.createElement('element'),
  11612. transitions = {
  11613. 'transition' :'transitionend',
  11614. 'OTransition' :'oTransitionEnd',
  11615. 'MozTransition' :'transitionend',
  11616. 'WebkitTransition' :'webkitTransitionEnd'
  11617. },
  11618. transition
  11619. ;
  11620. for(transition in transitions){
  11621. if( element.style[transition] !== undefined ){
  11622. return transitions[transition];
  11623. }
  11624. }
  11625. },
  11626. // gets current displayed percentage (if animating values this is the intermediary value)
  11627. displayPercent: function() {
  11628. var
  11629. barWidth = $bar.width(),
  11630. totalWidth = $module.width(),
  11631. minDisplay = parseInt($bar.css('min-width'), 10),
  11632. displayPercent = (barWidth > minDisplay)
  11633. ? (barWidth / totalWidth * 100)
  11634. : module.percent
  11635. ;
  11636. return (settings.precision > 0)
  11637. ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
  11638. : Math.round(displayPercent)
  11639. ;
  11640. },
  11641. percent: function() {
  11642. return module.percent || 0;
  11643. },
  11644. value: function() {
  11645. return module.nextValue || module.value || 0;
  11646. },
  11647. total: function() {
  11648. return module.total || false;
  11649. }
  11650. },
  11651. create: {
  11652. progressPoll: function() {
  11653. module.progressPoll = setTimeout(function() {
  11654. module.update.toNextValue();
  11655. module.remove.progressPoll();
  11656. }, module.get.updateInterval());
  11657. },
  11658. },
  11659. is: {
  11660. complete: function() {
  11661. return module.is.success() || module.is.warning() || module.is.error();
  11662. },
  11663. success: function() {
  11664. return $module.hasClass(className.success);
  11665. },
  11666. warning: function() {
  11667. return $module.hasClass(className.warning);
  11668. },
  11669. error: function() {
  11670. return $module.hasClass(className.error);
  11671. },
  11672. active: function() {
  11673. return $module.hasClass(className.active);
  11674. },
  11675. visible: function() {
  11676. return $module.is(':visible');
  11677. }
  11678. },
  11679. remove: {
  11680. progressPoll: function() {
  11681. module.verbose('Removing progress poll timer');
  11682. if(module.progressPoll) {
  11683. clearTimeout(module.progressPoll);
  11684. delete module.progressPoll;
  11685. }
  11686. },
  11687. nextValue: function() {
  11688. module.verbose('Removing progress value stored for next update');
  11689. delete module.nextValue;
  11690. },
  11691. state: function() {
  11692. module.verbose('Removing stored state');
  11693. delete module.total;
  11694. delete module.percent;
  11695. delete module.value;
  11696. },
  11697. active: function() {
  11698. module.verbose('Removing active state');
  11699. $module.removeClass(className.active);
  11700. },
  11701. success: function() {
  11702. module.verbose('Removing success state');
  11703. $module.removeClass(className.success);
  11704. },
  11705. warning: function() {
  11706. module.verbose('Removing warning state');
  11707. $module.removeClass(className.warning);
  11708. },
  11709. error: function() {
  11710. module.verbose('Removing error state');
  11711. $module.removeClass(className.error);
  11712. }
  11713. },
  11714. set: {
  11715. barWidth: function(value) {
  11716. if(value > 100) {
  11717. module.error(error.tooHigh, value);
  11718. }
  11719. else if (value < 0) {
  11720. module.error(error.tooLow, value);
  11721. }
  11722. else {
  11723. $bar
  11724. .css('width', value + '%')
  11725. ;
  11726. $module
  11727. .attr('data-percent', parseInt(value, 10))
  11728. ;
  11729. }
  11730. },
  11731. duration: function(duration) {
  11732. duration = duration || settings.duration;
  11733. duration = (typeof duration == 'number')
  11734. ? duration + 'ms'
  11735. : duration
  11736. ;
  11737. module.verbose('Setting progress bar transition duration', duration);
  11738. $bar
  11739. .css({
  11740. 'transition-duration': duration
  11741. })
  11742. ;
  11743. },
  11744. percent: function(percent) {
  11745. percent = (typeof percent == 'string')
  11746. ? +(percent.replace('%', ''))
  11747. : percent
  11748. ;
  11749. // round display percentage
  11750. percent = (settings.precision > 0)
  11751. ? Math.round(percent * (10 * settings.precision)) / (10 * settings.precision)
  11752. : Math.round(percent)
  11753. ;
  11754. module.percent = percent;
  11755. if( !module.has.total() ) {
  11756. module.value = (settings.precision > 0)
  11757. ? Math.round( (percent / 100) * module.total * (10 * settings.precision)) / (10 * settings.precision)
  11758. : Math.round( (percent / 100) * module.total * 10) / 10
  11759. ;
  11760. if(settings.limitValues) {
  11761. module.value = (module.value > 100)
  11762. ? 100
  11763. : (module.value < 0)
  11764. ? 0
  11765. : module.value
  11766. ;
  11767. }
  11768. }
  11769. module.set.barWidth(percent);
  11770. module.set.labelInterval();
  11771. module.set.labels();
  11772. settings.onChange.call(element, percent, module.value, module.total);
  11773. },
  11774. labelInterval: function() {
  11775. var
  11776. animationCallback = function() {
  11777. module.verbose('Bar finished animating, removing continuous label updates');
  11778. clearInterval(module.interval);
  11779. animating = false;
  11780. module.set.labels();
  11781. }
  11782. ;
  11783. clearInterval(module.interval);
  11784. module.bind.transitionEnd(animationCallback);
  11785. animating = true;
  11786. module.interval = setInterval(function() {
  11787. var
  11788. isInDOM = $.contains(document.documentElement, element)
  11789. ;
  11790. if(!isInDOM) {
  11791. clearInterval(module.interval);
  11792. animating = false;
  11793. }
  11794. module.set.labels();
  11795. }, settings.framerate);
  11796. },
  11797. labels: function() {
  11798. module.verbose('Setting both bar progress and outer label text');
  11799. module.set.barLabel();
  11800. module.set.state();
  11801. },
  11802. label: function(text) {
  11803. text = text || '';
  11804. if(text) {
  11805. text = module.get.text(text);
  11806. module.verbose('Setting label to text', text);
  11807. $label.text(text);
  11808. }
  11809. },
  11810. state: function(percent) {
  11811. percent = (percent !== undefined)
  11812. ? percent
  11813. : module.percent
  11814. ;
  11815. if(percent === 100) {
  11816. if(settings.autoSuccess && !(module.is.warning() || module.is.error() || module.is.success())) {
  11817. module.set.success();
  11818. module.debug('Automatically triggering success at 100%');
  11819. }
  11820. else {
  11821. module.verbose('Reached 100% removing active state');
  11822. module.remove.active();
  11823. module.remove.progressPoll();
  11824. }
  11825. }
  11826. else if(percent > 0) {
  11827. module.verbose('Adjusting active progress bar label', percent);
  11828. module.set.active();
  11829. }
  11830. else {
  11831. module.remove.active();
  11832. module.set.label(settings.text.active);
  11833. }
  11834. },
  11835. barLabel: function(text) {
  11836. if(text !== undefined) {
  11837. $progress.text( module.get.text(text) );
  11838. }
  11839. else if(settings.label == 'ratio' && module.total) {
  11840. module.verbose('Adding ratio to bar label');
  11841. $progress.text( module.get.text(settings.text.ratio) );
  11842. }
  11843. else if(settings.label == 'percent') {
  11844. module.verbose('Adding percentage to bar label');
  11845. $progress.text( module.get.text(settings.text.percent) );
  11846. }
  11847. },
  11848. active: function(text) {
  11849. text = text || settings.text.active;
  11850. module.debug('Setting active state');
  11851. if(settings.showActivity && !module.is.active() ) {
  11852. $module.addClass(className.active);
  11853. }
  11854. module.remove.warning();
  11855. module.remove.error();
  11856. module.remove.success();
  11857. text = settings.onLabelUpdate('active', text, module.value, module.total);
  11858. if(text) {
  11859. module.set.label(text);
  11860. }
  11861. module.bind.transitionEnd(function() {
  11862. settings.onActive.call(element, module.value, module.total);
  11863. });
  11864. },
  11865. success : function(text) {
  11866. text = text || settings.text.success || settings.text.active;
  11867. module.debug('Setting success state');
  11868. $module.addClass(className.success);
  11869. module.remove.active();
  11870. module.remove.warning();
  11871. module.remove.error();
  11872. module.complete();
  11873. if(settings.text.success) {
  11874. text = settings.onLabelUpdate('success', text, module.value, module.total);
  11875. module.set.label(text);
  11876. }
  11877. else {
  11878. text = settings.onLabelUpdate('active', text, module.value, module.total);
  11879. module.set.label(text);
  11880. }
  11881. module.bind.transitionEnd(function() {
  11882. settings.onSuccess.call(element, module.total);
  11883. });
  11884. },
  11885. warning : function(text) {
  11886. text = text || settings.text.warning;
  11887. module.debug('Setting warning state');
  11888. $module.addClass(className.warning);
  11889. module.remove.active();
  11890. module.remove.success();
  11891. module.remove.error();
  11892. module.complete();
  11893. text = settings.onLabelUpdate('warning', text, module.value, module.total);
  11894. if(text) {
  11895. module.set.label(text);
  11896. }
  11897. module.bind.transitionEnd(function() {
  11898. settings.onWarning.call(element, module.value, module.total);
  11899. });
  11900. },
  11901. error : function(text) {
  11902. text = text || settings.text.error;
  11903. module.debug('Setting error state');
  11904. $module.addClass(className.error);
  11905. module.remove.active();
  11906. module.remove.success();
  11907. module.remove.warning();
  11908. module.complete();
  11909. text = settings.onLabelUpdate('error', text, module.value, module.total);
  11910. if(text) {
  11911. module.set.label(text);
  11912. }
  11913. module.bind.transitionEnd(function() {
  11914. settings.onError.call(element, module.value, module.total);
  11915. });
  11916. },
  11917. transitionEvent: function() {
  11918. transitionEnd = module.get.transitionEnd();
  11919. },
  11920. total: function(totalValue) {
  11921. module.total = totalValue;
  11922. },
  11923. value: function(value) {
  11924. module.value = value;
  11925. },
  11926. progress: function(value) {
  11927. if(!module.has.progressPoll()) {
  11928. module.debug('First update in progress update interval, immediately updating', value);
  11929. module.update.progress(value);
  11930. module.create.progressPoll();
  11931. }
  11932. else {
  11933. module.debug('Updated within interval, setting next update to use new value', value);
  11934. module.set.nextValue(value);
  11935. }
  11936. },
  11937. nextValue: function(value) {
  11938. module.nextValue = value;
  11939. }
  11940. },
  11941. update: {
  11942. toNextValue: function() {
  11943. var
  11944. nextValue = module.nextValue
  11945. ;
  11946. if(nextValue) {
  11947. module.debug('Update interval complete using last updated value', nextValue);
  11948. module.update.progress(nextValue);
  11949. module.remove.nextValue();
  11950. }
  11951. },
  11952. progress: function(value) {
  11953. var
  11954. percentComplete
  11955. ;
  11956. value = module.get.numericValue(value);
  11957. if(value === false) {
  11958. module.error(error.nonNumeric, value);
  11959. }
  11960. value = module.get.normalizedValue(value);
  11961. if( module.has.total() ) {
  11962. module.set.value(value);
  11963. percentComplete = (value / module.total) * 100;
  11964. module.debug('Calculating percent complete from total', percentComplete);
  11965. module.set.percent( percentComplete );
  11966. }
  11967. else {
  11968. percentComplete = value;
  11969. module.debug('Setting value to exact percentage value', percentComplete);
  11970. module.set.percent( percentComplete );
  11971. }
  11972. }
  11973. },
  11974. setting: function(name, value) {
  11975. module.debug('Changing setting', name, value);
  11976. if( $.isPlainObject(name) ) {
  11977. $.extend(true, settings, name);
  11978. }
  11979. else if(value !== undefined) {
  11980. if($.isPlainObject(settings[name])) {
  11981. $.extend(true, settings[name], value);
  11982. }
  11983. else {
  11984. settings[name] = value;
  11985. }
  11986. }
  11987. else {
  11988. return settings[name];
  11989. }
  11990. },
  11991. internal: function(name, value) {
  11992. if( $.isPlainObject(name) ) {
  11993. $.extend(true, module, name);
  11994. }
  11995. else if(value !== undefined) {
  11996. module[name] = value;
  11997. }
  11998. else {
  11999. return module[name];
  12000. }
  12001. },
  12002. debug: function() {
  12003. if(!settings.silent && settings.debug) {
  12004. if(settings.performance) {
  12005. module.performance.log(arguments);
  12006. }
  12007. else {
  12008. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12009. module.debug.apply(console, arguments);
  12010. }
  12011. }
  12012. },
  12013. verbose: function() {
  12014. if(!settings.silent && settings.verbose && settings.debug) {
  12015. if(settings.performance) {
  12016. module.performance.log(arguments);
  12017. }
  12018. else {
  12019. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12020. module.verbose.apply(console, arguments);
  12021. }
  12022. }
  12023. },
  12024. error: function() {
  12025. if(!settings.silent) {
  12026. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  12027. module.error.apply(console, arguments);
  12028. }
  12029. },
  12030. performance: {
  12031. log: function(message) {
  12032. var
  12033. currentTime,
  12034. executionTime,
  12035. previousTime
  12036. ;
  12037. if(settings.performance) {
  12038. currentTime = new Date().getTime();
  12039. previousTime = time || currentTime;
  12040. executionTime = currentTime - previousTime;
  12041. time = currentTime;
  12042. performance.push({
  12043. 'Name' : message[0],
  12044. 'Arguments' : [].slice.call(message, 1) || '',
  12045. 'Element' : element,
  12046. 'Execution Time' : executionTime
  12047. });
  12048. }
  12049. clearTimeout(module.performance.timer);
  12050. module.performance.timer = setTimeout(module.performance.display, 500);
  12051. },
  12052. display: function() {
  12053. var
  12054. title = settings.name + ':',
  12055. totalTime = 0
  12056. ;
  12057. time = false;
  12058. clearTimeout(module.performance.timer);
  12059. $.each(performance, function(index, data) {
  12060. totalTime += data['Execution Time'];
  12061. });
  12062. title += ' ' + totalTime + 'ms';
  12063. if(moduleSelector) {
  12064. title += ' \'' + moduleSelector + '\'';
  12065. }
  12066. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  12067. console.groupCollapsed(title);
  12068. if(console.table) {
  12069. console.table(performance);
  12070. }
  12071. else {
  12072. $.each(performance, function(index, data) {
  12073. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  12074. });
  12075. }
  12076. console.groupEnd();
  12077. }
  12078. performance = [];
  12079. }
  12080. },
  12081. invoke: function(query, passedArguments, context) {
  12082. var
  12083. object = instance,
  12084. maxDepth,
  12085. found,
  12086. response
  12087. ;
  12088. passedArguments = passedArguments || queryArguments;
  12089. context = element || context;
  12090. if(typeof query == 'string' && object !== undefined) {
  12091. query = query.split(/[\. ]/);
  12092. maxDepth = query.length - 1;
  12093. $.each(query, function(depth, value) {
  12094. var camelCaseValue = (depth != maxDepth)
  12095. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  12096. : query
  12097. ;
  12098. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  12099. object = object[camelCaseValue];
  12100. }
  12101. else if( object[camelCaseValue] !== undefined ) {
  12102. found = object[camelCaseValue];
  12103. return false;
  12104. }
  12105. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  12106. object = object[value];
  12107. }
  12108. else if( object[value] !== undefined ) {
  12109. found = object[value];
  12110. return false;
  12111. }
  12112. else {
  12113. module.error(error.method, query);
  12114. return false;
  12115. }
  12116. });
  12117. }
  12118. if ( $.isFunction( found ) ) {
  12119. response = found.apply(context, passedArguments);
  12120. }
  12121. else if(found !== undefined) {
  12122. response = found;
  12123. }
  12124. if($.isArray(returnedValue)) {
  12125. returnedValue.push(response);
  12126. }
  12127. else if(returnedValue !== undefined) {
  12128. returnedValue = [returnedValue, response];
  12129. }
  12130. else if(response !== undefined) {
  12131. returnedValue = response;
  12132. }
  12133. return found;
  12134. }
  12135. };
  12136. if(methodInvoked) {
  12137. if(instance === undefined) {
  12138. module.initialize();
  12139. }
  12140. module.invoke(query);
  12141. }
  12142. else {
  12143. if(instance !== undefined) {
  12144. instance.invoke('destroy');
  12145. }
  12146. module.initialize();
  12147. }
  12148. })
  12149. ;
  12150. return (returnedValue !== undefined)
  12151. ? returnedValue
  12152. : this
  12153. ;
  12154. };
  12155. $.fn.progress.settings = {
  12156. name : 'Progress',
  12157. namespace : 'progress',
  12158. silent : false,
  12159. debug : false,
  12160. verbose : false,
  12161. performance : true,
  12162. random : {
  12163. min : 2,
  12164. max : 5
  12165. },
  12166. duration : 300,
  12167. updateInterval : 'auto',
  12168. autoSuccess : true,
  12169. showActivity : true,
  12170. limitValues : true,
  12171. label : 'percent',
  12172. precision : 0,
  12173. framerate : (1000 / 30), /// 30 fps
  12174. percent : false,
  12175. total : false,
  12176. value : false,
  12177. // delay in ms for fail safe animation callback
  12178. failSafeDelay : 100,
  12179. onLabelUpdate : function(state, text, value, total){
  12180. return text;
  12181. },
  12182. onChange : function(percent, value, total){},
  12183. onSuccess : function(total){},
  12184. onActive : function(value, total){},
  12185. onError : function(value, total){},
  12186. onWarning : function(value, total){},
  12187. error : {
  12188. method : 'The method you called is not defined.',
  12189. nonNumeric : 'Progress value is non numeric',
  12190. tooHigh : 'Value specified is above 100%',
  12191. tooLow : 'Value specified is below 0%'
  12192. },
  12193. regExp: {
  12194. variable: /\{\$*[A-z0-9]+\}/g
  12195. },
  12196. metadata: {
  12197. percent : 'percent',
  12198. total : 'total',
  12199. value : 'value'
  12200. },
  12201. selector : {
  12202. bar : '> .bar',
  12203. label : '> .label',
  12204. progress : '.bar > .progress'
  12205. },
  12206. text : {
  12207. active : false,
  12208. error : false,
  12209. success : false,
  12210. warning : false,
  12211. percent : '{percent}%',
  12212. ratio : '{value} of {total}'
  12213. },
  12214. className : {
  12215. active : 'active',
  12216. error : 'error',
  12217. success : 'success',
  12218. warning : 'warning'
  12219. }
  12220. };
  12221. })( jQuery, window, document );
  12222. /*!
  12223. * # Semantic UI 2.4.1 - Rating
  12224. * http://github.com/semantic-org/semantic-ui/
  12225. *
  12226. *
  12227. * Released under the MIT license
  12228. * http://opensource.org/licenses/MIT
  12229. *
  12230. */
  12231. ;(function ($, window, document, undefined) {
  12232. 'use strict';
  12233. window = (typeof window != 'undefined' && window.Math == Math)
  12234. ? window
  12235. : (typeof self != 'undefined' && self.Math == Math)
  12236. ? self
  12237. : Function('return this')()
  12238. ;
  12239. $.fn.rating = function(parameters) {
  12240. var
  12241. $allModules = $(this),
  12242. moduleSelector = $allModules.selector || '',
  12243. time = new Date().getTime(),
  12244. performance = [],
  12245. query = arguments[0],
  12246. methodInvoked = (typeof query == 'string'),
  12247. queryArguments = [].slice.call(arguments, 1),
  12248. returnedValue
  12249. ;
  12250. $allModules
  12251. .each(function() {
  12252. var
  12253. settings = ( $.isPlainObject(parameters) )
  12254. ? $.extend(true, {}, $.fn.rating.settings, parameters)
  12255. : $.extend({}, $.fn.rating.settings),
  12256. namespace = settings.namespace,
  12257. className = settings.className,
  12258. metadata = settings.metadata,
  12259. selector = settings.selector,
  12260. error = settings.error,
  12261. eventNamespace = '.' + namespace,
  12262. moduleNamespace = 'module-' + namespace,
  12263. element = this,
  12264. instance = $(this).data(moduleNamespace),
  12265. $module = $(this),
  12266. $icon = $module.find(selector.icon),
  12267. initialLoad,
  12268. module
  12269. ;
  12270. module = {
  12271. initialize: function() {
  12272. module.verbose('Initializing rating module', settings);
  12273. if($icon.length === 0) {
  12274. module.setup.layout();
  12275. }
  12276. if(settings.interactive) {
  12277. module.enable();
  12278. }
  12279. else {
  12280. module.disable();
  12281. }
  12282. module.set.initialLoad();
  12283. module.set.rating( module.get.initialRating() );
  12284. module.remove.initialLoad();
  12285. module.instantiate();
  12286. },
  12287. instantiate: function() {
  12288. module.verbose('Instantiating module', settings);
  12289. instance = module;
  12290. $module
  12291. .data(moduleNamespace, module)
  12292. ;
  12293. },
  12294. destroy: function() {
  12295. module.verbose('Destroying previous instance', instance);
  12296. module.remove.events();
  12297. $module
  12298. .removeData(moduleNamespace)
  12299. ;
  12300. },
  12301. refresh: function() {
  12302. $icon = $module.find(selector.icon);
  12303. },
  12304. setup: {
  12305. layout: function() {
  12306. var
  12307. maxRating = module.get.maxRating(),
  12308. html = $.fn.rating.settings.templates.icon(maxRating)
  12309. ;
  12310. module.debug('Generating icon html dynamically');
  12311. $module
  12312. .html(html)
  12313. ;
  12314. module.refresh();
  12315. }
  12316. },
  12317. event: {
  12318. mouseenter: function() {
  12319. var
  12320. $activeIcon = $(this)
  12321. ;
  12322. $activeIcon
  12323. .nextAll()
  12324. .removeClass(className.selected)
  12325. ;
  12326. $module
  12327. .addClass(className.selected)
  12328. ;
  12329. $activeIcon
  12330. .addClass(className.selected)
  12331. .prevAll()
  12332. .addClass(className.selected)
  12333. ;
  12334. },
  12335. mouseleave: function() {
  12336. $module
  12337. .removeClass(className.selected)
  12338. ;
  12339. $icon
  12340. .removeClass(className.selected)
  12341. ;
  12342. },
  12343. click: function() {
  12344. var
  12345. $activeIcon = $(this),
  12346. currentRating = module.get.rating(),
  12347. rating = $icon.index($activeIcon) + 1,
  12348. canClear = (settings.clearable == 'auto')
  12349. ? ($icon.length === 1)
  12350. : settings.clearable
  12351. ;
  12352. if(canClear && currentRating == rating) {
  12353. module.clearRating();
  12354. }
  12355. else {
  12356. module.set.rating( rating );
  12357. }
  12358. }
  12359. },
  12360. clearRating: function() {
  12361. module.debug('Clearing current rating');
  12362. module.set.rating(0);
  12363. },
  12364. bind: {
  12365. events: function() {
  12366. module.verbose('Binding events');
  12367. $module
  12368. .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
  12369. .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
  12370. .on('click' + eventNamespace, selector.icon, module.event.click)
  12371. ;
  12372. }
  12373. },
  12374. remove: {
  12375. events: function() {
  12376. module.verbose('Removing events');
  12377. $module
  12378. .off(eventNamespace)
  12379. ;
  12380. },
  12381. initialLoad: function() {
  12382. initialLoad = false;
  12383. }
  12384. },
  12385. enable: function() {
  12386. module.debug('Setting rating to interactive mode');
  12387. module.bind.events();
  12388. $module
  12389. .removeClass(className.disabled)
  12390. ;
  12391. },
  12392. disable: function() {
  12393. module.debug('Setting rating to read-only mode');
  12394. module.remove.events();
  12395. $module
  12396. .addClass(className.disabled)
  12397. ;
  12398. },
  12399. is: {
  12400. initialLoad: function() {
  12401. return initialLoad;
  12402. }
  12403. },
  12404. get: {
  12405. initialRating: function() {
  12406. if($module.data(metadata.rating) !== undefined) {
  12407. $module.removeData(metadata.rating);
  12408. return $module.data(metadata.rating);
  12409. }
  12410. return settings.initialRating;
  12411. },
  12412. maxRating: function() {
  12413. if($module.data(metadata.maxRating) !== undefined) {
  12414. $module.removeData(metadata.maxRating);
  12415. return $module.data(metadata.maxRating);
  12416. }
  12417. return settings.maxRating;
  12418. },
  12419. rating: function() {
  12420. var
  12421. currentRating = $icon.filter('.' + className.active).length
  12422. ;
  12423. module.verbose('Current rating retrieved', currentRating);
  12424. return currentRating;
  12425. }
  12426. },
  12427. set: {
  12428. rating: function(rating) {
  12429. var
  12430. ratingIndex = (rating - 1 >= 0)
  12431. ? (rating - 1)
  12432. : 0,
  12433. $activeIcon = $icon.eq(ratingIndex)
  12434. ;
  12435. $module
  12436. .removeClass(className.selected)
  12437. ;
  12438. $icon
  12439. .removeClass(className.selected)
  12440. .removeClass(className.active)
  12441. ;
  12442. if(rating > 0) {
  12443. module.verbose('Setting current rating to', rating);
  12444. $activeIcon
  12445. .prevAll()
  12446. .addBack()
  12447. .addClass(className.active)
  12448. ;
  12449. }
  12450. if(!module.is.initialLoad()) {
  12451. settings.onRate.call(element, rating);
  12452. }
  12453. },
  12454. initialLoad: function() {
  12455. initialLoad = true;
  12456. }
  12457. },
  12458. setting: function(name, value) {
  12459. module.debug('Changing setting', name, value);
  12460. if( $.isPlainObject(name) ) {
  12461. $.extend(true, settings, name);
  12462. }
  12463. else if(value !== undefined) {
  12464. if($.isPlainObject(settings[name])) {
  12465. $.extend(true, settings[name], value);
  12466. }
  12467. else {
  12468. settings[name] = value;
  12469. }
  12470. }
  12471. else {
  12472. return settings[name];
  12473. }
  12474. },
  12475. internal: function(name, value) {
  12476. if( $.isPlainObject(name) ) {
  12477. $.extend(true, module, name);
  12478. }
  12479. else if(value !== undefined) {
  12480. module[name] = value;
  12481. }
  12482. else {
  12483. return module[name];
  12484. }
  12485. },
  12486. debug: function() {
  12487. if(!settings.silent && settings.debug) {
  12488. if(settings.performance) {
  12489. module.performance.log(arguments);
  12490. }
  12491. else {
  12492. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12493. module.debug.apply(console, arguments);
  12494. }
  12495. }
  12496. },
  12497. verbose: function() {
  12498. if(!settings.silent && settings.verbose && settings.debug) {
  12499. if(settings.performance) {
  12500. module.performance.log(arguments);
  12501. }
  12502. else {
  12503. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12504. module.verbose.apply(console, arguments);
  12505. }
  12506. }
  12507. },
  12508. error: function() {
  12509. if(!settings.silent) {
  12510. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  12511. module.error.apply(console, arguments);
  12512. }
  12513. },
  12514. performance: {
  12515. log: function(message) {
  12516. var
  12517. currentTime,
  12518. executionTime,
  12519. previousTime
  12520. ;
  12521. if(settings.performance) {
  12522. currentTime = new Date().getTime();
  12523. previousTime = time || currentTime;
  12524. executionTime = currentTime - previousTime;
  12525. time = currentTime;
  12526. performance.push({
  12527. 'Name' : message[0],
  12528. 'Arguments' : [].slice.call(message, 1) || '',
  12529. 'Element' : element,
  12530. 'Execution Time' : executionTime
  12531. });
  12532. }
  12533. clearTimeout(module.performance.timer);
  12534. module.performance.timer = setTimeout(module.performance.display, 500);
  12535. },
  12536. display: function() {
  12537. var
  12538. title = settings.name + ':',
  12539. totalTime = 0
  12540. ;
  12541. time = false;
  12542. clearTimeout(module.performance.timer);
  12543. $.each(performance, function(index, data) {
  12544. totalTime += data['Execution Time'];
  12545. });
  12546. title += ' ' + totalTime + 'ms';
  12547. if(moduleSelector) {
  12548. title += ' \'' + moduleSelector + '\'';
  12549. }
  12550. if($allModules.length > 1) {
  12551. title += ' ' + '(' + $allModules.length + ')';
  12552. }
  12553. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  12554. console.groupCollapsed(title);
  12555. if(console.table) {
  12556. console.table(performance);
  12557. }
  12558. else {
  12559. $.each(performance, function(index, data) {
  12560. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  12561. });
  12562. }
  12563. console.groupEnd();
  12564. }
  12565. performance = [];
  12566. }
  12567. },
  12568. invoke: function(query, passedArguments, context) {
  12569. var
  12570. object = instance,
  12571. maxDepth,
  12572. found,
  12573. response
  12574. ;
  12575. passedArguments = passedArguments || queryArguments;
  12576. context = element || context;
  12577. if(typeof query == 'string' && object !== undefined) {
  12578. query = query.split(/[\. ]/);
  12579. maxDepth = query.length - 1;
  12580. $.each(query, function(depth, value) {
  12581. var camelCaseValue = (depth != maxDepth)
  12582. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  12583. : query
  12584. ;
  12585. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  12586. object = object[camelCaseValue];
  12587. }
  12588. else if( object[camelCaseValue] !== undefined ) {
  12589. found = object[camelCaseValue];
  12590. return false;
  12591. }
  12592. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  12593. object = object[value];
  12594. }
  12595. else if( object[value] !== undefined ) {
  12596. found = object[value];
  12597. return false;
  12598. }
  12599. else {
  12600. return false;
  12601. }
  12602. });
  12603. }
  12604. if ( $.isFunction( found ) ) {
  12605. response = found.apply(context, passedArguments);
  12606. }
  12607. else if(found !== undefined) {
  12608. response = found;
  12609. }
  12610. if($.isArray(returnedValue)) {
  12611. returnedValue.push(response);
  12612. }
  12613. else if(returnedValue !== undefined) {
  12614. returnedValue = [returnedValue, response];
  12615. }
  12616. else if(response !== undefined) {
  12617. returnedValue = response;
  12618. }
  12619. return found;
  12620. }
  12621. };
  12622. if(methodInvoked) {
  12623. if(instance === undefined) {
  12624. module.initialize();
  12625. }
  12626. module.invoke(query);
  12627. }
  12628. else {
  12629. if(instance !== undefined) {
  12630. instance.invoke('destroy');
  12631. }
  12632. module.initialize();
  12633. }
  12634. })
  12635. ;
  12636. return (returnedValue !== undefined)
  12637. ? returnedValue
  12638. : this
  12639. ;
  12640. };
  12641. $.fn.rating.settings = {
  12642. name : 'Rating',
  12643. namespace : 'rating',
  12644. slent : false,
  12645. debug : false,
  12646. verbose : false,
  12647. performance : true,
  12648. initialRating : 0,
  12649. interactive : true,
  12650. maxRating : 4,
  12651. clearable : 'auto',
  12652. fireOnInit : false,
  12653. onRate : function(rating){},
  12654. error : {
  12655. method : 'The method you called is not defined',
  12656. noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
  12657. },
  12658. metadata: {
  12659. rating : 'rating',
  12660. maxRating : 'maxRating'
  12661. },
  12662. className : {
  12663. active : 'active',
  12664. disabled : 'disabled',
  12665. selected : 'selected',
  12666. loading : 'loading'
  12667. },
  12668. selector : {
  12669. icon : '.icon'
  12670. },
  12671. templates: {
  12672. icon: function(maxRating) {
  12673. var
  12674. icon = 1,
  12675. html = ''
  12676. ;
  12677. while(icon <= maxRating) {
  12678. html += '<i class="icon"></i>';
  12679. icon++;
  12680. }
  12681. return html;
  12682. }
  12683. }
  12684. };
  12685. })( jQuery, window, document );
  12686. /*!
  12687. * # Semantic UI 2.4.1 - Search
  12688. * http://github.com/semantic-org/semantic-ui/
  12689. *
  12690. *
  12691. * Released under the MIT license
  12692. * http://opensource.org/licenses/MIT
  12693. *
  12694. */
  12695. ;(function ($, window, document, undefined) {
  12696. 'use strict';
  12697. window = (typeof window != 'undefined' && window.Math == Math)
  12698. ? window
  12699. : (typeof self != 'undefined' && self.Math == Math)
  12700. ? self
  12701. : Function('return this')()
  12702. ;
  12703. $.fn.search = function(parameters) {
  12704. var
  12705. $allModules = $(this),
  12706. moduleSelector = $allModules.selector || '',
  12707. time = new Date().getTime(),
  12708. performance = [],
  12709. query = arguments[0],
  12710. methodInvoked = (typeof query == 'string'),
  12711. queryArguments = [].slice.call(arguments, 1),
  12712. returnedValue
  12713. ;
  12714. $(this)
  12715. .each(function() {
  12716. var
  12717. settings = ( $.isPlainObject(parameters) )
  12718. ? $.extend(true, {}, $.fn.search.settings, parameters)
  12719. : $.extend({}, $.fn.search.settings),
  12720. className = settings.className,
  12721. metadata = settings.metadata,
  12722. regExp = settings.regExp,
  12723. fields = settings.fields,
  12724. selector = settings.selector,
  12725. error = settings.error,
  12726. namespace = settings.namespace,
  12727. eventNamespace = '.' + namespace,
  12728. moduleNamespace = namespace + '-module',
  12729. $module = $(this),
  12730. $prompt = $module.find(selector.prompt),
  12731. $searchButton = $module.find(selector.searchButton),
  12732. $results = $module.find(selector.results),
  12733. $result = $module.find(selector.result),
  12734. $category = $module.find(selector.category),
  12735. element = this,
  12736. instance = $module.data(moduleNamespace),
  12737. disabledBubbled = false,
  12738. resultsDismissed = false,
  12739. module
  12740. ;
  12741. module = {
  12742. initialize: function() {
  12743. module.verbose('Initializing module');
  12744. module.get.settings();
  12745. module.determine.searchFields();
  12746. module.bind.events();
  12747. module.set.type();
  12748. module.create.results();
  12749. module.instantiate();
  12750. },
  12751. instantiate: function() {
  12752. module.verbose('Storing instance of module', module);
  12753. instance = module;
  12754. $module
  12755. .data(moduleNamespace, module)
  12756. ;
  12757. },
  12758. destroy: function() {
  12759. module.verbose('Destroying instance');
  12760. $module
  12761. .off(eventNamespace)
  12762. .removeData(moduleNamespace)
  12763. ;
  12764. },
  12765. refresh: function() {
  12766. module.debug('Refreshing selector cache');
  12767. $prompt = $module.find(selector.prompt);
  12768. $searchButton = $module.find(selector.searchButton);
  12769. $category = $module.find(selector.category);
  12770. $results = $module.find(selector.results);
  12771. $result = $module.find(selector.result);
  12772. },
  12773. refreshResults: function() {
  12774. $results = $module.find(selector.results);
  12775. $result = $module.find(selector.result);
  12776. },
  12777. bind: {
  12778. events: function() {
  12779. module.verbose('Binding events to search');
  12780. if(settings.automatic) {
  12781. $module
  12782. .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
  12783. ;
  12784. $prompt
  12785. .attr('autocomplete', 'off')
  12786. ;
  12787. }
  12788. $module
  12789. // prompt
  12790. .on('focus' + eventNamespace, selector.prompt, module.event.focus)
  12791. .on('blur' + eventNamespace, selector.prompt, module.event.blur)
  12792. .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
  12793. // search button
  12794. .on('click' + eventNamespace, selector.searchButton, module.query)
  12795. // results
  12796. .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
  12797. .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
  12798. .on('click' + eventNamespace, selector.result, module.event.result.click)
  12799. ;
  12800. }
  12801. },
  12802. determine: {
  12803. searchFields: function() {
  12804. // this makes sure $.extend does not add specified search fields to default fields
  12805. // this is the only setting which should not extend defaults
  12806. if(parameters && parameters.searchFields !== undefined) {
  12807. settings.searchFields = parameters.searchFields;
  12808. }
  12809. }
  12810. },
  12811. event: {
  12812. input: function() {
  12813. if(settings.searchDelay) {
  12814. clearTimeout(module.timer);
  12815. module.timer = setTimeout(function() {
  12816. if(module.is.focused()) {
  12817. module.query();
  12818. }
  12819. }, settings.searchDelay);
  12820. }
  12821. else {
  12822. module.query();
  12823. }
  12824. },
  12825. focus: function() {
  12826. module.set.focus();
  12827. if(settings.searchOnFocus && module.has.minimumCharacters() ) {
  12828. module.query(function() {
  12829. if(module.can.show() ) {
  12830. module.showResults();
  12831. }
  12832. });
  12833. }
  12834. },
  12835. blur: function(event) {
  12836. var
  12837. pageLostFocus = (document.activeElement === this),
  12838. callback = function() {
  12839. module.cancel.query();
  12840. module.remove.focus();
  12841. module.timer = setTimeout(module.hideResults, settings.hideDelay);
  12842. }
  12843. ;
  12844. if(pageLostFocus) {
  12845. return;
  12846. }
  12847. resultsDismissed = false;
  12848. if(module.resultsClicked) {
  12849. module.debug('Determining if user action caused search to close');
  12850. $module
  12851. .one('click.close' + eventNamespace, selector.results, function(event) {
  12852. if(module.is.inMessage(event) || disabledBubbled) {
  12853. $prompt.focus();
  12854. return;
  12855. }
  12856. disabledBubbled = false;
  12857. if( !module.is.animating() && !module.is.hidden()) {
  12858. callback();
  12859. }
  12860. })
  12861. ;
  12862. }
  12863. else {
  12864. module.debug('Input blurred without user action, closing results');
  12865. callback();
  12866. }
  12867. },
  12868. result: {
  12869. mousedown: function() {
  12870. module.resultsClicked = true;
  12871. },
  12872. mouseup: function() {
  12873. module.resultsClicked = false;
  12874. },
  12875. click: function(event) {
  12876. module.debug('Search result selected');
  12877. var
  12878. $result = $(this),
  12879. $title = $result.find(selector.title).eq(0),
  12880. $link = $result.is('a[href]')
  12881. ? $result
  12882. : $result.find('a[href]').eq(0),
  12883. href = $link.attr('href') || false,
  12884. target = $link.attr('target') || false,
  12885. title = $title.html(),
  12886. // title is used for result lookup
  12887. value = ($title.length > 0)
  12888. ? $title.text()
  12889. : false,
  12890. results = module.get.results(),
  12891. result = $result.data(metadata.result) || module.get.result(value, results),
  12892. returnedValue
  12893. ;
  12894. if( $.isFunction(settings.onSelect) ) {
  12895. if(settings.onSelect.call(element, result, results) === false) {
  12896. module.debug('Custom onSelect callback cancelled default select action');
  12897. disabledBubbled = true;
  12898. return;
  12899. }
  12900. }
  12901. module.hideResults();
  12902. if(value) {
  12903. module.set.value(value);
  12904. }
  12905. if(href) {
  12906. module.verbose('Opening search link found in result', $link);
  12907. if(target == '_blank' || event.ctrlKey) {
  12908. window.open(href);
  12909. }
  12910. else {
  12911. window.location.href = (href);
  12912. }
  12913. }
  12914. }
  12915. }
  12916. },
  12917. handleKeyboard: function(event) {
  12918. var
  12919. // force selector refresh
  12920. $result = $module.find(selector.result),
  12921. $category = $module.find(selector.category),
  12922. $activeResult = $result.filter('.' + className.active),
  12923. currentIndex = $result.index( $activeResult ),
  12924. resultSize = $result.length,
  12925. hasActiveResult = $activeResult.length > 0,
  12926. keyCode = event.which,
  12927. keys = {
  12928. backspace : 8,
  12929. enter : 13,
  12930. escape : 27,
  12931. upArrow : 38,
  12932. downArrow : 40
  12933. },
  12934. newIndex
  12935. ;
  12936. // search shortcuts
  12937. if(keyCode == keys.escape) {
  12938. module.verbose('Escape key pressed, blurring search field');
  12939. module.hideResults();
  12940. resultsDismissed = true;
  12941. }
  12942. if( module.is.visible() ) {
  12943. if(keyCode == keys.enter) {
  12944. module.verbose('Enter key pressed, selecting active result');
  12945. if( $result.filter('.' + className.active).length > 0 ) {
  12946. module.event.result.click.call($result.filter('.' + className.active), event);
  12947. event.preventDefault();
  12948. return false;
  12949. }
  12950. }
  12951. else if(keyCode == keys.upArrow && hasActiveResult) {
  12952. module.verbose('Up key pressed, changing active result');
  12953. newIndex = (currentIndex - 1 < 0)
  12954. ? currentIndex
  12955. : currentIndex - 1
  12956. ;
  12957. $category
  12958. .removeClass(className.active)
  12959. ;
  12960. $result
  12961. .removeClass(className.active)
  12962. .eq(newIndex)
  12963. .addClass(className.active)
  12964. .closest($category)
  12965. .addClass(className.active)
  12966. ;
  12967. event.preventDefault();
  12968. }
  12969. else if(keyCode == keys.downArrow) {
  12970. module.verbose('Down key pressed, changing active result');
  12971. newIndex = (currentIndex + 1 >= resultSize)
  12972. ? currentIndex
  12973. : currentIndex + 1
  12974. ;
  12975. $category
  12976. .removeClass(className.active)
  12977. ;
  12978. $result
  12979. .removeClass(className.active)
  12980. .eq(newIndex)
  12981. .addClass(className.active)
  12982. .closest($category)
  12983. .addClass(className.active)
  12984. ;
  12985. event.preventDefault();
  12986. }
  12987. }
  12988. else {
  12989. // query shortcuts
  12990. if(keyCode == keys.enter) {
  12991. module.verbose('Enter key pressed, executing query');
  12992. module.query();
  12993. module.set.buttonPressed();
  12994. $prompt.one('keyup', module.remove.buttonFocus);
  12995. }
  12996. }
  12997. },
  12998. setup: {
  12999. api: function(searchTerm, callback) {
  13000. var
  13001. apiSettings = {
  13002. debug : settings.debug,
  13003. on : false,
  13004. cache : settings.cache,
  13005. action : 'search',
  13006. urlData : {
  13007. query : searchTerm
  13008. },
  13009. onSuccess : function(response) {
  13010. module.parse.response.call(element, response, searchTerm);
  13011. callback();
  13012. },
  13013. onFailure : function() {
  13014. module.displayMessage(error.serverError);
  13015. callback();
  13016. },
  13017. onAbort : function(response) {
  13018. },
  13019. onError : module.error
  13020. },
  13021. searchHTML
  13022. ;
  13023. $.extend(true, apiSettings, settings.apiSettings);
  13024. module.verbose('Setting up API request', apiSettings);
  13025. $module.api(apiSettings);
  13026. }
  13027. },
  13028. can: {
  13029. useAPI: function() {
  13030. return $.fn.api !== undefined;
  13031. },
  13032. show: function() {
  13033. return module.is.focused() && !module.is.visible() && !module.is.empty();
  13034. },
  13035. transition: function() {
  13036. return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
  13037. }
  13038. },
  13039. is: {
  13040. animating: function() {
  13041. return $results.hasClass(className.animating);
  13042. },
  13043. hidden: function() {
  13044. return $results.hasClass(className.hidden);
  13045. },
  13046. inMessage: function(event) {
  13047. if(!event.target) {
  13048. return;
  13049. }
  13050. var
  13051. $target = $(event.target),
  13052. isInDOM = $.contains(document.documentElement, event.target)
  13053. ;
  13054. return (isInDOM && $target.closest(selector.message).length > 0);
  13055. },
  13056. empty: function() {
  13057. return ($results.html() === '');
  13058. },
  13059. visible: function() {
  13060. return ($results.filter(':visible').length > 0);
  13061. },
  13062. focused: function() {
  13063. return ($prompt.filter(':focus').length > 0);
  13064. }
  13065. },
  13066. get: {
  13067. settings: function() {
  13068. if($.isPlainObject(parameters) && parameters.searchFullText) {
  13069. settings.fullTextSearch = parameters.searchFullText;
  13070. module.error(settings.error.oldSearchSyntax, element);
  13071. }
  13072. },
  13073. inputEvent: function() {
  13074. var
  13075. prompt = $prompt[0],
  13076. inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
  13077. ? 'input'
  13078. : (prompt !== undefined && prompt.onpropertychange !== undefined)
  13079. ? 'propertychange'
  13080. : 'keyup'
  13081. ;
  13082. return inputEvent;
  13083. },
  13084. value: function() {
  13085. return $prompt.val();
  13086. },
  13087. results: function() {
  13088. var
  13089. results = $module.data(metadata.results)
  13090. ;
  13091. return results;
  13092. },
  13093. result: function(value, results) {
  13094. var
  13095. lookupFields = ['title', 'id'],
  13096. result = false
  13097. ;
  13098. value = (value !== undefined)
  13099. ? value
  13100. : module.get.value()
  13101. ;
  13102. results = (results !== undefined)
  13103. ? results
  13104. : module.get.results()
  13105. ;
  13106. if(settings.type === 'category') {
  13107. module.debug('Finding result that matches', value);
  13108. $.each(results, function(index, category) {
  13109. if($.isArray(category.results)) {
  13110. result = module.search.object(value, category.results, lookupFields)[0];
  13111. // don't continue searching if a result is found
  13112. if(result) {
  13113. return false;
  13114. }
  13115. }
  13116. });
  13117. }
  13118. else {
  13119. module.debug('Finding result in results object', value);
  13120. result = module.search.object(value, results, lookupFields)[0];
  13121. }
  13122. return result || false;
  13123. },
  13124. },
  13125. select: {
  13126. firstResult: function() {
  13127. module.verbose('Selecting first result');
  13128. $result.first().addClass(className.active);
  13129. }
  13130. },
  13131. set: {
  13132. focus: function() {
  13133. $module.addClass(className.focus);
  13134. },
  13135. loading: function() {
  13136. $module.addClass(className.loading);
  13137. },
  13138. value: function(value) {
  13139. module.verbose('Setting search input value', value);
  13140. $prompt
  13141. .val(value)
  13142. ;
  13143. },
  13144. type: function(type) {
  13145. type = type || settings.type;
  13146. if(settings.type == 'category') {
  13147. $module.addClass(settings.type);
  13148. }
  13149. },
  13150. buttonPressed: function() {
  13151. $searchButton.addClass(className.pressed);
  13152. }
  13153. },
  13154. remove: {
  13155. loading: function() {
  13156. $module.removeClass(className.loading);
  13157. },
  13158. focus: function() {
  13159. $module.removeClass(className.focus);
  13160. },
  13161. buttonPressed: function() {
  13162. $searchButton.removeClass(className.pressed);
  13163. }
  13164. },
  13165. query: function(callback) {
  13166. callback = $.isFunction(callback)
  13167. ? callback
  13168. : function(){}
  13169. ;
  13170. var
  13171. searchTerm = module.get.value(),
  13172. cache = module.read.cache(searchTerm)
  13173. ;
  13174. callback = callback || function() {};
  13175. if( module.has.minimumCharacters() ) {
  13176. if(cache) {
  13177. module.debug('Reading result from cache', searchTerm);
  13178. module.save.results(cache.results);
  13179. module.addResults(cache.html);
  13180. module.inject.id(cache.results);
  13181. callback();
  13182. }
  13183. else {
  13184. module.debug('Querying for', searchTerm);
  13185. if($.isPlainObject(settings.source) || $.isArray(settings.source)) {
  13186. module.search.local(searchTerm);
  13187. callback();
  13188. }
  13189. else if( module.can.useAPI() ) {
  13190. module.search.remote(searchTerm, callback);
  13191. }
  13192. else {
  13193. module.error(error.source);
  13194. callback();
  13195. }
  13196. }
  13197. settings.onSearchQuery.call(element, searchTerm);
  13198. }
  13199. else {
  13200. module.hideResults();
  13201. }
  13202. },
  13203. search: {
  13204. local: function(searchTerm) {
  13205. var
  13206. results = module.search.object(searchTerm, settings.content),
  13207. searchHTML
  13208. ;
  13209. module.set.loading();
  13210. module.save.results(results);
  13211. module.debug('Returned full local search results', results);
  13212. if(settings.maxResults > 0) {
  13213. module.debug('Using specified max results', results);
  13214. results = results.slice(0, settings.maxResults);
  13215. }
  13216. if(settings.type == 'category') {
  13217. results = module.create.categoryResults(results);
  13218. }
  13219. searchHTML = module.generateResults({
  13220. results: results
  13221. });
  13222. module.remove.loading();
  13223. module.addResults(searchHTML);
  13224. module.inject.id(results);
  13225. module.write.cache(searchTerm, {
  13226. html : searchHTML,
  13227. results : results
  13228. });
  13229. },
  13230. remote: function(searchTerm, callback) {
  13231. callback = $.isFunction(callback)
  13232. ? callback
  13233. : function(){}
  13234. ;
  13235. if($module.api('is loading')) {
  13236. $module.api('abort');
  13237. }
  13238. module.setup.api(searchTerm, callback);
  13239. $module
  13240. .api('query')
  13241. ;
  13242. },
  13243. object: function(searchTerm, source, searchFields) {
  13244. var
  13245. results = [],
  13246. exactResults = [],
  13247. fuzzyResults = [],
  13248. searchExp = searchTerm.toString().replace(regExp.escape, '\\$&'),
  13249. matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
  13250. // avoid duplicates when pushing results
  13251. addResult = function(array, result) {
  13252. var
  13253. notResult = ($.inArray(result, results) == -1),
  13254. notFuzzyResult = ($.inArray(result, fuzzyResults) == -1),
  13255. notExactResults = ($.inArray(result, exactResults) == -1)
  13256. ;
  13257. if(notResult && notFuzzyResult && notExactResults) {
  13258. array.push(result);
  13259. }
  13260. }
  13261. ;
  13262. source = source || settings.source;
  13263. searchFields = (searchFields !== undefined)
  13264. ? searchFields
  13265. : settings.searchFields
  13266. ;
  13267. // search fields should be array to loop correctly
  13268. if(!$.isArray(searchFields)) {
  13269. searchFields = [searchFields];
  13270. }
  13271. // exit conditions if no source
  13272. if(source === undefined || source === false) {
  13273. module.error(error.source);
  13274. return [];
  13275. }
  13276. // iterate through search fields looking for matches
  13277. $.each(searchFields, function(index, field) {
  13278. $.each(source, function(label, content) {
  13279. var
  13280. fieldExists = (typeof content[field] == 'string')
  13281. ;
  13282. if(fieldExists) {
  13283. if( content[field].search(matchRegExp) !== -1) {
  13284. // content starts with value (first in results)
  13285. addResult(results, content);
  13286. }
  13287. else if(settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, content[field]) ) {
  13288. // content fuzzy matches (last in results)
  13289. addResult(exactResults, content);
  13290. }
  13291. else if(settings.fullTextSearch == true && module.fuzzySearch(searchTerm, content[field]) ) {
  13292. // content fuzzy matches (last in results)
  13293. addResult(fuzzyResults, content);
  13294. }
  13295. }
  13296. });
  13297. });
  13298. $.merge(exactResults, fuzzyResults)
  13299. $.merge(results, exactResults);
  13300. return results;
  13301. }
  13302. },
  13303. exactSearch: function (query, term) {
  13304. query = query.toLowerCase();
  13305. term = term.toLowerCase();
  13306. if(term.indexOf(query) > -1) {
  13307. return true;
  13308. }
  13309. return false;
  13310. },
  13311. fuzzySearch: function(query, term) {
  13312. var
  13313. termLength = term.length,
  13314. queryLength = query.length
  13315. ;
  13316. if(typeof query !== 'string') {
  13317. return false;
  13318. }
  13319. query = query.toLowerCase();
  13320. term = term.toLowerCase();
  13321. if(queryLength > termLength) {
  13322. return false;
  13323. }
  13324. if(queryLength === termLength) {
  13325. return (query === term);
  13326. }
  13327. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  13328. var
  13329. queryCharacter = query.charCodeAt(characterIndex)
  13330. ;
  13331. while(nextCharacterIndex < termLength) {
  13332. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  13333. continue search;
  13334. }
  13335. }
  13336. return false;
  13337. }
  13338. return true;
  13339. },
  13340. parse: {
  13341. response: function(response, searchTerm) {
  13342. var
  13343. searchHTML = module.generateResults(response)
  13344. ;
  13345. module.verbose('Parsing server response', response);
  13346. if(response !== undefined) {
  13347. if(searchTerm !== undefined && response[fields.results] !== undefined) {
  13348. module.addResults(searchHTML);
  13349. module.inject.id(response[fields.results]);
  13350. module.write.cache(searchTerm, {
  13351. html : searchHTML,
  13352. results : response[fields.results]
  13353. });
  13354. module.save.results(response[fields.results]);
  13355. }
  13356. }
  13357. }
  13358. },
  13359. cancel: {
  13360. query: function() {
  13361. if( module.can.useAPI() ) {
  13362. $module.api('abort');
  13363. }
  13364. }
  13365. },
  13366. has: {
  13367. minimumCharacters: function() {
  13368. var
  13369. searchTerm = module.get.value(),
  13370. numCharacters = searchTerm.length
  13371. ;
  13372. return (numCharacters >= settings.minCharacters);
  13373. },
  13374. results: function() {
  13375. if($results.length === 0) {
  13376. return false;
  13377. }
  13378. var
  13379. html = $results.html()
  13380. ;
  13381. return html != '';
  13382. }
  13383. },
  13384. clear: {
  13385. cache: function(value) {
  13386. var
  13387. cache = $module.data(metadata.cache)
  13388. ;
  13389. if(!value) {
  13390. module.debug('Clearing cache', value);
  13391. $module.removeData(metadata.cache);
  13392. }
  13393. else if(value && cache && cache[value]) {
  13394. module.debug('Removing value from cache', value);
  13395. delete cache[value];
  13396. $module.data(metadata.cache, cache);
  13397. }
  13398. }
  13399. },
  13400. read: {
  13401. cache: function(name) {
  13402. var
  13403. cache = $module.data(metadata.cache)
  13404. ;
  13405. if(settings.cache) {
  13406. module.verbose('Checking cache for generated html for query', name);
  13407. return (typeof cache == 'object') && (cache[name] !== undefined)
  13408. ? cache[name]
  13409. : false
  13410. ;
  13411. }
  13412. return false;
  13413. }
  13414. },
  13415. create: {
  13416. categoryResults: function(results) {
  13417. var
  13418. categoryResults = {}
  13419. ;
  13420. $.each(results, function(index, result) {
  13421. if(!result.category) {
  13422. return;
  13423. }
  13424. if(categoryResults[result.category] === undefined) {
  13425. module.verbose('Creating new category of results', result.category);
  13426. categoryResults[result.category] = {
  13427. name : result.category,
  13428. results : [result]
  13429. }
  13430. }
  13431. else {
  13432. categoryResults[result.category].results.push(result);
  13433. }
  13434. });
  13435. return categoryResults;
  13436. },
  13437. id: function(resultIndex, categoryIndex) {
  13438. var
  13439. resultID = (resultIndex + 1), // not zero indexed
  13440. categoryID = (categoryIndex + 1),
  13441. firstCharCode,
  13442. letterID,
  13443. id
  13444. ;
  13445. if(categoryIndex !== undefined) {
  13446. // start char code for "A"
  13447. letterID = String.fromCharCode(97 + categoryIndex);
  13448. id = letterID + resultID;
  13449. module.verbose('Creating category result id', id);
  13450. }
  13451. else {
  13452. id = resultID;
  13453. module.verbose('Creating result id', id);
  13454. }
  13455. return id;
  13456. },
  13457. results: function() {
  13458. if($results.length === 0) {
  13459. $results = $('<div />')
  13460. .addClass(className.results)
  13461. .appendTo($module)
  13462. ;
  13463. }
  13464. }
  13465. },
  13466. inject: {
  13467. result: function(result, resultIndex, categoryIndex) {
  13468. module.verbose('Injecting result into results');
  13469. var
  13470. $selectedResult = (categoryIndex !== undefined)
  13471. ? $results
  13472. .children().eq(categoryIndex)
  13473. .children(selector.results)
  13474. .first()
  13475. .children(selector.result)
  13476. .eq(resultIndex)
  13477. : $results
  13478. .children(selector.result).eq(resultIndex)
  13479. ;
  13480. module.verbose('Injecting results metadata', $selectedResult);
  13481. $selectedResult
  13482. .data(metadata.result, result)
  13483. ;
  13484. },
  13485. id: function(results) {
  13486. module.debug('Injecting unique ids into results');
  13487. var
  13488. // since results may be object, we must use counters
  13489. categoryIndex = 0,
  13490. resultIndex = 0
  13491. ;
  13492. if(settings.type === 'category') {
  13493. // iterate through each category result
  13494. $.each(results, function(index, category) {
  13495. resultIndex = 0;
  13496. $.each(category.results, function(index, value) {
  13497. var
  13498. result = category.results[index]
  13499. ;
  13500. if(result.id === undefined) {
  13501. result.id = module.create.id(resultIndex, categoryIndex);
  13502. }
  13503. module.inject.result(result, resultIndex, categoryIndex);
  13504. resultIndex++;
  13505. });
  13506. categoryIndex++;
  13507. });
  13508. }
  13509. else {
  13510. // top level
  13511. $.each(results, function(index, value) {
  13512. var
  13513. result = results[index]
  13514. ;
  13515. if(result.id === undefined) {
  13516. result.id = module.create.id(resultIndex);
  13517. }
  13518. module.inject.result(result, resultIndex);
  13519. resultIndex++;
  13520. });
  13521. }
  13522. return results;
  13523. }
  13524. },
  13525. save: {
  13526. results: function(results) {
  13527. module.verbose('Saving current search results to metadata', results);
  13528. $module.data(metadata.results, results);
  13529. }
  13530. },
  13531. write: {
  13532. cache: function(name, value) {
  13533. var
  13534. cache = ($module.data(metadata.cache) !== undefined)
  13535. ? $module.data(metadata.cache)
  13536. : {}
  13537. ;
  13538. if(settings.cache) {
  13539. module.verbose('Writing generated html to cache', name, value);
  13540. cache[name] = value;
  13541. $module
  13542. .data(metadata.cache, cache)
  13543. ;
  13544. }
  13545. }
  13546. },
  13547. addResults: function(html) {
  13548. if( $.isFunction(settings.onResultsAdd) ) {
  13549. if( settings.onResultsAdd.call($results, html) === false ) {
  13550. module.debug('onResultsAdd callback cancelled default action');
  13551. return false;
  13552. }
  13553. }
  13554. if(html) {
  13555. $results
  13556. .html(html)
  13557. ;
  13558. module.refreshResults();
  13559. if(settings.selectFirstResult) {
  13560. module.select.firstResult();
  13561. }
  13562. module.showResults();
  13563. }
  13564. else {
  13565. module.hideResults(function() {
  13566. $results.empty();
  13567. });
  13568. }
  13569. },
  13570. showResults: function(callback) {
  13571. callback = $.isFunction(callback)
  13572. ? callback
  13573. : function(){}
  13574. ;
  13575. if(resultsDismissed) {
  13576. return;
  13577. }
  13578. if(!module.is.visible() && module.has.results()) {
  13579. if( module.can.transition() ) {
  13580. module.debug('Showing results with css animations');
  13581. $results
  13582. .transition({
  13583. animation : settings.transition + ' in',
  13584. debug : settings.debug,
  13585. verbose : settings.verbose,
  13586. duration : settings.duration,
  13587. onComplete : function() {
  13588. callback();
  13589. },
  13590. queue : true
  13591. })
  13592. ;
  13593. }
  13594. else {
  13595. module.debug('Showing results with javascript');
  13596. $results
  13597. .stop()
  13598. .fadeIn(settings.duration, settings.easing)
  13599. ;
  13600. }
  13601. settings.onResultsOpen.call($results);
  13602. }
  13603. },
  13604. hideResults: function(callback) {
  13605. callback = $.isFunction(callback)
  13606. ? callback
  13607. : function(){}
  13608. ;
  13609. if( module.is.visible() ) {
  13610. if( module.can.transition() ) {
  13611. module.debug('Hiding results with css animations');
  13612. $results
  13613. .transition({
  13614. animation : settings.transition + ' out',
  13615. debug : settings.debug,
  13616. verbose : settings.verbose,
  13617. duration : settings.duration,
  13618. onComplete : function() {
  13619. callback();
  13620. },
  13621. queue : true
  13622. })
  13623. ;
  13624. }
  13625. else {
  13626. module.debug('Hiding results with javascript');
  13627. $results
  13628. .stop()
  13629. .fadeOut(settings.duration, settings.easing)
  13630. ;
  13631. }
  13632. settings.onResultsClose.call($results);
  13633. }
  13634. },
  13635. generateResults: function(response) {
  13636. module.debug('Generating html from response', response);
  13637. var
  13638. template = settings.templates[settings.type],
  13639. isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])),
  13640. isProperArray = ($.isArray(response[fields.results]) && response[fields.results].length > 0),
  13641. html = ''
  13642. ;
  13643. if(isProperObject || isProperArray ) {
  13644. if(settings.maxResults > 0) {
  13645. if(isProperObject) {
  13646. if(settings.type == 'standard') {
  13647. module.error(error.maxResults);
  13648. }
  13649. }
  13650. else {
  13651. response[fields.results] = response[fields.results].slice(0, settings.maxResults);
  13652. }
  13653. }
  13654. if($.isFunction(template)) {
  13655. html = template(response, fields);
  13656. }
  13657. else {
  13658. module.error(error.noTemplate, false);
  13659. }
  13660. }
  13661. else if(settings.showNoResults) {
  13662. html = module.displayMessage(error.noResults, 'empty');
  13663. }
  13664. settings.onResults.call(element, response);
  13665. return html;
  13666. },
  13667. displayMessage: function(text, type) {
  13668. type = type || 'standard';
  13669. module.debug('Displaying message', text, type);
  13670. module.addResults( settings.templates.message(text, type) );
  13671. return settings.templates.message(text, type);
  13672. },
  13673. setting: function(name, value) {
  13674. if( $.isPlainObject(name) ) {
  13675. $.extend(true, settings, name);
  13676. }
  13677. else if(value !== undefined) {
  13678. settings[name] = value;
  13679. }
  13680. else {
  13681. return settings[name];
  13682. }
  13683. },
  13684. internal: function(name, value) {
  13685. if( $.isPlainObject(name) ) {
  13686. $.extend(true, module, name);
  13687. }
  13688. else if(value !== undefined) {
  13689. module[name] = value;
  13690. }
  13691. else {
  13692. return module[name];
  13693. }
  13694. },
  13695. debug: function() {
  13696. if(!settings.silent && settings.debug) {
  13697. if(settings.performance) {
  13698. module.performance.log(arguments);
  13699. }
  13700. else {
  13701. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13702. module.debug.apply(console, arguments);
  13703. }
  13704. }
  13705. },
  13706. verbose: function() {
  13707. if(!settings.silent && settings.verbose && settings.debug) {
  13708. if(settings.performance) {
  13709. module.performance.log(arguments);
  13710. }
  13711. else {
  13712. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13713. module.verbose.apply(console, arguments);
  13714. }
  13715. }
  13716. },
  13717. error: function() {
  13718. if(!settings.silent) {
  13719. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  13720. module.error.apply(console, arguments);
  13721. }
  13722. },
  13723. performance: {
  13724. log: function(message) {
  13725. var
  13726. currentTime,
  13727. executionTime,
  13728. previousTime
  13729. ;
  13730. if(settings.performance) {
  13731. currentTime = new Date().getTime();
  13732. previousTime = time || currentTime;
  13733. executionTime = currentTime - previousTime;
  13734. time = currentTime;
  13735. performance.push({
  13736. 'Name' : message[0],
  13737. 'Arguments' : [].slice.call(message, 1) || '',
  13738. 'Element' : element,
  13739. 'Execution Time' : executionTime
  13740. });
  13741. }
  13742. clearTimeout(module.performance.timer);
  13743. module.performance.timer = setTimeout(module.performance.display, 500);
  13744. },
  13745. display: function() {
  13746. var
  13747. title = settings.name + ':',
  13748. totalTime = 0
  13749. ;
  13750. time = false;
  13751. clearTimeout(module.performance.timer);
  13752. $.each(performance, function(index, data) {
  13753. totalTime += data['Execution Time'];
  13754. });
  13755. title += ' ' + totalTime + 'ms';
  13756. if(moduleSelector) {
  13757. title += ' \'' + moduleSelector + '\'';
  13758. }
  13759. if($allModules.length > 1) {
  13760. title += ' ' + '(' + $allModules.length + ')';
  13761. }
  13762. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  13763. console.groupCollapsed(title);
  13764. if(console.table) {
  13765. console.table(performance);
  13766. }
  13767. else {
  13768. $.each(performance, function(index, data) {
  13769. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  13770. });
  13771. }
  13772. console.groupEnd();
  13773. }
  13774. performance = [];
  13775. }
  13776. },
  13777. invoke: function(query, passedArguments, context) {
  13778. var
  13779. object = instance,
  13780. maxDepth,
  13781. found,
  13782. response
  13783. ;
  13784. passedArguments = passedArguments || queryArguments;
  13785. context = element || context;
  13786. if(typeof query == 'string' && object !== undefined) {
  13787. query = query.split(/[\. ]/);
  13788. maxDepth = query.length - 1;
  13789. $.each(query, function(depth, value) {
  13790. var camelCaseValue = (depth != maxDepth)
  13791. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  13792. : query
  13793. ;
  13794. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  13795. object = object[camelCaseValue];
  13796. }
  13797. else if( object[camelCaseValue] !== undefined ) {
  13798. found = object[camelCaseValue];
  13799. return false;
  13800. }
  13801. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  13802. object = object[value];
  13803. }
  13804. else if( object[value] !== undefined ) {
  13805. found = object[value];
  13806. return false;
  13807. }
  13808. else {
  13809. return false;
  13810. }
  13811. });
  13812. }
  13813. if( $.isFunction( found ) ) {
  13814. response = found.apply(context, passedArguments);
  13815. }
  13816. else if(found !== undefined) {
  13817. response = found;
  13818. }
  13819. if($.isArray(returnedValue)) {
  13820. returnedValue.push(response);
  13821. }
  13822. else if(returnedValue !== undefined) {
  13823. returnedValue = [returnedValue, response];
  13824. }
  13825. else if(response !== undefined) {
  13826. returnedValue = response;
  13827. }
  13828. return found;
  13829. }
  13830. };
  13831. if(methodInvoked) {
  13832. if(instance === undefined) {
  13833. module.initialize();
  13834. }
  13835. module.invoke(query);
  13836. }
  13837. else {
  13838. if(instance !== undefined) {
  13839. instance.invoke('destroy');
  13840. }
  13841. module.initialize();
  13842. }
  13843. })
  13844. ;
  13845. return (returnedValue !== undefined)
  13846. ? returnedValue
  13847. : this
  13848. ;
  13849. };
  13850. $.fn.search.settings = {
  13851. name : 'Search',
  13852. namespace : 'search',
  13853. silent : false,
  13854. debug : false,
  13855. verbose : false,
  13856. performance : true,
  13857. // template to use (specified in settings.templates)
  13858. type : 'standard',
  13859. // minimum characters required to search
  13860. minCharacters : 1,
  13861. // whether to select first result after searching automatically
  13862. selectFirstResult : false,
  13863. // API config
  13864. apiSettings : false,
  13865. // object to search
  13866. source : false,
  13867. // Whether search should query current term on focus
  13868. searchOnFocus : true,
  13869. // fields to search
  13870. searchFields : [
  13871. 'title',
  13872. 'description'
  13873. ],
  13874. // field to display in standard results template
  13875. displayField : '',
  13876. // search anywhere in value (set to 'exact' to require exact matches
  13877. fullTextSearch : 'exact',
  13878. // whether to add events to prompt automatically
  13879. automatic : true,
  13880. // delay before hiding menu after blur
  13881. hideDelay : 0,
  13882. // delay before searching
  13883. searchDelay : 200,
  13884. // maximum results returned from search
  13885. maxResults : 7,
  13886. // whether to store lookups in local cache
  13887. cache : true,
  13888. // whether no results errors should be shown
  13889. showNoResults : true,
  13890. // transition settings
  13891. transition : 'scale',
  13892. duration : 200,
  13893. easing : 'easeOutExpo',
  13894. // callbacks
  13895. onSelect : false,
  13896. onResultsAdd : false,
  13897. onSearchQuery : function(query){},
  13898. onResults : function(response){},
  13899. onResultsOpen : function(){},
  13900. onResultsClose : function(){},
  13901. className: {
  13902. animating : 'animating',
  13903. active : 'active',
  13904. empty : 'empty',
  13905. focus : 'focus',
  13906. hidden : 'hidden',
  13907. loading : 'loading',
  13908. results : 'results',
  13909. pressed : 'down'
  13910. },
  13911. error : {
  13912. source : 'Cannot search. No source used, and Semantic API module was not included',
  13913. noResults : 'Your search returned no results',
  13914. logging : 'Error in debug logging, exiting.',
  13915. noEndpoint : 'No search endpoint was specified',
  13916. noTemplate : 'A valid template name was not specified.',
  13917. oldSearchSyntax : 'searchFullText setting has been renamed fullTextSearch for consistency, please adjust your settings.',
  13918. serverError : 'There was an issue querying the server.',
  13919. maxResults : 'Results must be an array to use maxResults setting',
  13920. method : 'The method you called is not defined.'
  13921. },
  13922. metadata: {
  13923. cache : 'cache',
  13924. results : 'results',
  13925. result : 'result'
  13926. },
  13927. regExp: {
  13928. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  13929. beginsWith : '(?:\s|^)'
  13930. },
  13931. // maps api response attributes to internal representation
  13932. fields: {
  13933. categories : 'results', // array of categories (category view)
  13934. categoryName : 'name', // name of category (category view)
  13935. categoryResults : 'results', // array of results (category view)
  13936. description : 'description', // result description
  13937. image : 'image', // result image
  13938. price : 'price', // result price
  13939. results : 'results', // array of results (standard)
  13940. title : 'title', // result title
  13941. url : 'url', // result url
  13942. action : 'action', // "view more" object name
  13943. actionText : 'text', // "view more" text
  13944. actionURL : 'url' // "view more" url
  13945. },
  13946. selector : {
  13947. prompt : '.prompt',
  13948. searchButton : '.search.button',
  13949. results : '.results',
  13950. message : '.results > .message',
  13951. category : '.category',
  13952. result : '.result',
  13953. title : '.title, .name'
  13954. },
  13955. templates: {
  13956. escape: function(string) {
  13957. var
  13958. badChars = /[&<>"'`]/g,
  13959. shouldEscape = /[&<>"'`]/,
  13960. escape = {
  13961. "&": "&amp;",
  13962. "<": "&lt;",
  13963. ">": "&gt;",
  13964. '"': "&quot;",
  13965. "'": "&#x27;",
  13966. "`": "&#x60;"
  13967. },
  13968. escapedChar = function(chr) {
  13969. return escape[chr];
  13970. }
  13971. ;
  13972. if(shouldEscape.test(string)) {
  13973. return string.replace(badChars, escapedChar);
  13974. }
  13975. return string;
  13976. },
  13977. message: function(message, type) {
  13978. var
  13979. html = ''
  13980. ;
  13981. if(message !== undefined && type !== undefined) {
  13982. html += ''
  13983. + '<div class="message ' + type + '">'
  13984. ;
  13985. // message type
  13986. if(type == 'empty') {
  13987. html += ''
  13988. + '<div class="header">No Results</div class="header">'
  13989. + '<div class="description">' + message + '</div class="description">'
  13990. ;
  13991. }
  13992. else {
  13993. html += ' <div class="description">' + message + '</div>';
  13994. }
  13995. html += '</div>';
  13996. }
  13997. return html;
  13998. },
  13999. category: function(response, fields) {
  14000. var
  14001. html = '',
  14002. escape = $.fn.search.settings.templates.escape
  14003. ;
  14004. if(response[fields.categoryResults] !== undefined) {
  14005. // each category
  14006. $.each(response[fields.categoryResults], function(index, category) {
  14007. if(category[fields.results] !== undefined && category.results.length > 0) {
  14008. html += '<div class="category">';
  14009. if(category[fields.categoryName] !== undefined) {
  14010. html += '<div class="name">' + category[fields.categoryName] + '</div>';
  14011. }
  14012. // each item inside category
  14013. html += '<div class="results">';
  14014. $.each(category.results, function(index, result) {
  14015. if(result[fields.url]) {
  14016. html += '<a class="result" href="' + result[fields.url] + '">';
  14017. }
  14018. else {
  14019. html += '<a class="result">';
  14020. }
  14021. if(result[fields.image] !== undefined) {
  14022. html += ''
  14023. + '<div class="image">'
  14024. + ' <img src="' + result[fields.image] + '">'
  14025. + '</div>'
  14026. ;
  14027. }
  14028. html += '<div class="content">';
  14029. if(result[fields.price] !== undefined) {
  14030. html += '<div class="price">' + result[fields.price] + '</div>';
  14031. }
  14032. if(result[fields.title] !== undefined) {
  14033. html += '<div class="title">' + result[fields.title] + '</div>';
  14034. }
  14035. if(result[fields.description] !== undefined) {
  14036. html += '<div class="description">' + result[fields.description] + '</div>';
  14037. }
  14038. html += ''
  14039. + '</div>'
  14040. ;
  14041. html += '</a>';
  14042. });
  14043. html += '</div>';
  14044. html += ''
  14045. + '</div>'
  14046. ;
  14047. }
  14048. });
  14049. if(response[fields.action]) {
  14050. html += ''
  14051. + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">'
  14052. + response[fields.action][fields.actionText]
  14053. + '</a>';
  14054. }
  14055. return html;
  14056. }
  14057. return false;
  14058. },
  14059. standard: function(response, fields) {
  14060. var
  14061. html = ''
  14062. ;
  14063. if(response[fields.results] !== undefined) {
  14064. // each result
  14065. $.each(response[fields.results], function(index, result) {
  14066. if(result[fields.url]) {
  14067. html += '<a class="result" href="' + result[fields.url] + '">';
  14068. }
  14069. else {
  14070. html += '<a class="result">';
  14071. }
  14072. if(result[fields.image] !== undefined) {
  14073. html += ''
  14074. + '<div class="image">'
  14075. + ' <img src="' + result[fields.image] + '">'
  14076. + '</div>'
  14077. ;
  14078. }
  14079. html += '<div class="content">';
  14080. if(result[fields.price] !== undefined) {
  14081. html += '<div class="price">' + result[fields.price] + '</div>';
  14082. }
  14083. if(result[fields.title] !== undefined) {
  14084. html += '<div class="title">' + result[fields.title] + '</div>';
  14085. }
  14086. if(result[fields.description] !== undefined) {
  14087. html += '<div class="description">' + result[fields.description] + '</div>';
  14088. }
  14089. html += ''
  14090. + '</div>'
  14091. ;
  14092. html += '</a>';
  14093. });
  14094. if(response[fields.action]) {
  14095. html += ''
  14096. + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">'
  14097. + response[fields.action][fields.actionText]
  14098. + '</a>';
  14099. }
  14100. return html;
  14101. }
  14102. return false;
  14103. }
  14104. }
  14105. };
  14106. })( jQuery, window, document );
  14107. /*!
  14108. * # Semantic UI 2.4.1 - Shape
  14109. * http://github.com/semantic-org/semantic-ui/
  14110. *
  14111. *
  14112. * Released under the MIT license
  14113. * http://opensource.org/licenses/MIT
  14114. *
  14115. */
  14116. ;(function ($, window, document, undefined) {
  14117. 'use strict';
  14118. window = (typeof window != 'undefined' && window.Math == Math)
  14119. ? window
  14120. : (typeof self != 'undefined' && self.Math == Math)
  14121. ? self
  14122. : Function('return this')()
  14123. ;
  14124. $.fn.shape = function(parameters) {
  14125. var
  14126. $allModules = $(this),
  14127. $body = $('body'),
  14128. time = new Date().getTime(),
  14129. performance = [],
  14130. query = arguments[0],
  14131. methodInvoked = (typeof query == 'string'),
  14132. queryArguments = [].slice.call(arguments, 1),
  14133. requestAnimationFrame = window.requestAnimationFrame
  14134. || window.mozRequestAnimationFrame
  14135. || window.webkitRequestAnimationFrame
  14136. || window.msRequestAnimationFrame
  14137. || function(callback) { setTimeout(callback, 0); },
  14138. returnedValue
  14139. ;
  14140. $allModules
  14141. .each(function() {
  14142. var
  14143. moduleSelector = $allModules.selector || '',
  14144. settings = ( $.isPlainObject(parameters) )
  14145. ? $.extend(true, {}, $.fn.shape.settings, parameters)
  14146. : $.extend({}, $.fn.shape.settings),
  14147. // internal aliases
  14148. namespace = settings.namespace,
  14149. selector = settings.selector,
  14150. error = settings.error,
  14151. className = settings.className,
  14152. // define namespaces for modules
  14153. eventNamespace = '.' + namespace,
  14154. moduleNamespace = 'module-' + namespace,
  14155. // selector cache
  14156. $module = $(this),
  14157. $sides = $module.find(selector.sides),
  14158. $side = $module.find(selector.side),
  14159. // private variables
  14160. nextIndex = false,
  14161. $activeSide,
  14162. $nextSide,
  14163. // standard module
  14164. element = this,
  14165. instance = $module.data(moduleNamespace),
  14166. module
  14167. ;
  14168. module = {
  14169. initialize: function() {
  14170. module.verbose('Initializing module for', element);
  14171. module.set.defaultSide();
  14172. module.instantiate();
  14173. },
  14174. instantiate: function() {
  14175. module.verbose('Storing instance of module', module);
  14176. instance = module;
  14177. $module
  14178. .data(moduleNamespace, instance)
  14179. ;
  14180. },
  14181. destroy: function() {
  14182. module.verbose('Destroying previous module for', element);
  14183. $module
  14184. .removeData(moduleNamespace)
  14185. .off(eventNamespace)
  14186. ;
  14187. },
  14188. refresh: function() {
  14189. module.verbose('Refreshing selector cache for', element);
  14190. $module = $(element);
  14191. $sides = $(this).find(selector.shape);
  14192. $side = $(this).find(selector.side);
  14193. },
  14194. repaint: function() {
  14195. module.verbose('Forcing repaint event');
  14196. var
  14197. shape = $sides[0] || document.createElement('div'),
  14198. fakeAssignment = shape.offsetWidth
  14199. ;
  14200. },
  14201. animate: function(propertyObject, callback) {
  14202. module.verbose('Animating box with properties', propertyObject);
  14203. callback = callback || function(event) {
  14204. module.verbose('Executing animation callback');
  14205. if(event !== undefined) {
  14206. event.stopPropagation();
  14207. }
  14208. module.reset();
  14209. module.set.active();
  14210. };
  14211. settings.beforeChange.call($nextSide[0]);
  14212. if(module.get.transitionEvent()) {
  14213. module.verbose('Starting CSS animation');
  14214. $module
  14215. .addClass(className.animating)
  14216. ;
  14217. $sides
  14218. .css(propertyObject)
  14219. .one(module.get.transitionEvent(), callback)
  14220. ;
  14221. module.set.duration(settings.duration);
  14222. requestAnimationFrame(function() {
  14223. $module
  14224. .addClass(className.animating)
  14225. ;
  14226. $activeSide
  14227. .addClass(className.hidden)
  14228. ;
  14229. });
  14230. }
  14231. else {
  14232. callback();
  14233. }
  14234. },
  14235. queue: function(method) {
  14236. module.debug('Queueing animation of', method);
  14237. $sides
  14238. .one(module.get.transitionEvent(), function() {
  14239. module.debug('Executing queued animation');
  14240. setTimeout(function(){
  14241. $module.shape(method);
  14242. }, 0);
  14243. })
  14244. ;
  14245. },
  14246. reset: function() {
  14247. module.verbose('Animating states reset');
  14248. $module
  14249. .removeClass(className.animating)
  14250. .attr('style', '')
  14251. .removeAttr('style')
  14252. ;
  14253. // removeAttr style does not consistently work in safari
  14254. $sides
  14255. .attr('style', '')
  14256. .removeAttr('style')
  14257. ;
  14258. $side
  14259. .attr('style', '')
  14260. .removeAttr('style')
  14261. .removeClass(className.hidden)
  14262. ;
  14263. $nextSide
  14264. .removeClass(className.animating)
  14265. .attr('style', '')
  14266. .removeAttr('style')
  14267. ;
  14268. },
  14269. is: {
  14270. complete: function() {
  14271. return ($side.filter('.' + className.active)[0] == $nextSide[0]);
  14272. },
  14273. animating: function() {
  14274. return $module.hasClass(className.animating);
  14275. }
  14276. },
  14277. set: {
  14278. defaultSide: function() {
  14279. $activeSide = $module.find('.' + settings.className.active);
  14280. $nextSide = ( $activeSide.next(selector.side).length > 0 )
  14281. ? $activeSide.next(selector.side)
  14282. : $module.find(selector.side).first()
  14283. ;
  14284. nextIndex = false;
  14285. module.verbose('Active side set to', $activeSide);
  14286. module.verbose('Next side set to', $nextSide);
  14287. },
  14288. duration: function(duration) {
  14289. duration = duration || settings.duration;
  14290. duration = (typeof duration == 'number')
  14291. ? duration + 'ms'
  14292. : duration
  14293. ;
  14294. module.verbose('Setting animation duration', duration);
  14295. if(settings.duration || settings.duration === 0) {
  14296. $sides.add($side)
  14297. .css({
  14298. '-webkit-transition-duration': duration,
  14299. '-moz-transition-duration': duration,
  14300. '-ms-transition-duration': duration,
  14301. '-o-transition-duration': duration,
  14302. 'transition-duration': duration
  14303. })
  14304. ;
  14305. }
  14306. },
  14307. currentStageSize: function() {
  14308. var
  14309. $activeSide = $module.find('.' + settings.className.active),
  14310. width = $activeSide.outerWidth(true),
  14311. height = $activeSide.outerHeight(true)
  14312. ;
  14313. $module
  14314. .css({
  14315. width: width,
  14316. height: height
  14317. })
  14318. ;
  14319. },
  14320. stageSize: function() {
  14321. var
  14322. $clone = $module.clone().addClass(className.loading),
  14323. $activeSide = $clone.find('.' + settings.className.active),
  14324. $nextSide = (nextIndex)
  14325. ? $clone.find(selector.side).eq(nextIndex)
  14326. : ( $activeSide.next(selector.side).length > 0 )
  14327. ? $activeSide.next(selector.side)
  14328. : $clone.find(selector.side).first(),
  14329. newWidth = (settings.width == 'next')
  14330. ? $nextSide.outerWidth(true)
  14331. : (settings.width == 'initial')
  14332. ? $module.width()
  14333. : settings.width,
  14334. newHeight = (settings.height == 'next')
  14335. ? $nextSide.outerHeight(true)
  14336. : (settings.height == 'initial')
  14337. ? $module.height()
  14338. : settings.height
  14339. ;
  14340. $activeSide.removeClass(className.active);
  14341. $nextSide.addClass(className.active);
  14342. $clone.insertAfter($module);
  14343. $clone.remove();
  14344. if(settings.width != 'auto') {
  14345. $module.css('width', newWidth + settings.jitter);
  14346. module.verbose('Specifying width during animation', newWidth);
  14347. }
  14348. if(settings.height != 'auto') {
  14349. $module.css('height', newHeight + settings.jitter);
  14350. module.verbose('Specifying height during animation', newHeight);
  14351. }
  14352. },
  14353. nextSide: function(selector) {
  14354. nextIndex = selector;
  14355. $nextSide = $side.filter(selector);
  14356. nextIndex = $side.index($nextSide);
  14357. if($nextSide.length === 0) {
  14358. module.set.defaultSide();
  14359. module.error(error.side);
  14360. }
  14361. module.verbose('Next side manually set to', $nextSide);
  14362. },
  14363. active: function() {
  14364. module.verbose('Setting new side to active', $nextSide);
  14365. $side
  14366. .removeClass(className.active)
  14367. ;
  14368. $nextSide
  14369. .addClass(className.active)
  14370. ;
  14371. settings.onChange.call($nextSide[0]);
  14372. module.set.defaultSide();
  14373. }
  14374. },
  14375. flip: {
  14376. up: function() {
  14377. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14378. module.debug('Side already visible', $nextSide);
  14379. return;
  14380. }
  14381. if( !module.is.animating()) {
  14382. module.debug('Flipping up', $nextSide);
  14383. var
  14384. transform = module.get.transform.up()
  14385. ;
  14386. module.set.stageSize();
  14387. module.stage.above();
  14388. module.animate(transform);
  14389. }
  14390. else {
  14391. module.queue('flip up');
  14392. }
  14393. },
  14394. down: function() {
  14395. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14396. module.debug('Side already visible', $nextSide);
  14397. return;
  14398. }
  14399. if( !module.is.animating()) {
  14400. module.debug('Flipping down', $nextSide);
  14401. var
  14402. transform = module.get.transform.down()
  14403. ;
  14404. module.set.stageSize();
  14405. module.stage.below();
  14406. module.animate(transform);
  14407. }
  14408. else {
  14409. module.queue('flip down');
  14410. }
  14411. },
  14412. left: function() {
  14413. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14414. module.debug('Side already visible', $nextSide);
  14415. return;
  14416. }
  14417. if( !module.is.animating()) {
  14418. module.debug('Flipping left', $nextSide);
  14419. var
  14420. transform = module.get.transform.left()
  14421. ;
  14422. module.set.stageSize();
  14423. module.stage.left();
  14424. module.animate(transform);
  14425. }
  14426. else {
  14427. module.queue('flip left');
  14428. }
  14429. },
  14430. right: function() {
  14431. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14432. module.debug('Side already visible', $nextSide);
  14433. return;
  14434. }
  14435. if( !module.is.animating()) {
  14436. module.debug('Flipping right', $nextSide);
  14437. var
  14438. transform = module.get.transform.right()
  14439. ;
  14440. module.set.stageSize();
  14441. module.stage.right();
  14442. module.animate(transform);
  14443. }
  14444. else {
  14445. module.queue('flip right');
  14446. }
  14447. },
  14448. over: function() {
  14449. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14450. module.debug('Side already visible', $nextSide);
  14451. return;
  14452. }
  14453. if( !module.is.animating()) {
  14454. module.debug('Flipping over', $nextSide);
  14455. module.set.stageSize();
  14456. module.stage.behind();
  14457. module.animate(module.get.transform.over() );
  14458. }
  14459. else {
  14460. module.queue('flip over');
  14461. }
  14462. },
  14463. back: function() {
  14464. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  14465. module.debug('Side already visible', $nextSide);
  14466. return;
  14467. }
  14468. if( !module.is.animating()) {
  14469. module.debug('Flipping back', $nextSide);
  14470. module.set.stageSize();
  14471. module.stage.behind();
  14472. module.animate(module.get.transform.back() );
  14473. }
  14474. else {
  14475. module.queue('flip back');
  14476. }
  14477. }
  14478. },
  14479. get: {
  14480. transform: {
  14481. up: function() {
  14482. var
  14483. translate = {
  14484. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14485. z: -($activeSide.outerHeight(true) / 2)
  14486. }
  14487. ;
  14488. return {
  14489. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)'
  14490. };
  14491. },
  14492. down: function() {
  14493. var
  14494. translate = {
  14495. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14496. z: -($activeSide.outerHeight(true) / 2)
  14497. }
  14498. ;
  14499. return {
  14500. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)'
  14501. };
  14502. },
  14503. left: function() {
  14504. var
  14505. translate = {
  14506. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  14507. z : -($activeSide.outerWidth(true) / 2)
  14508. }
  14509. ;
  14510. return {
  14511. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)'
  14512. };
  14513. },
  14514. right: function() {
  14515. var
  14516. translate = {
  14517. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  14518. z : -($activeSide.outerWidth(true) / 2)
  14519. }
  14520. ;
  14521. return {
  14522. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)'
  14523. };
  14524. },
  14525. over: function() {
  14526. var
  14527. translate = {
  14528. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  14529. }
  14530. ;
  14531. return {
  14532. transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
  14533. };
  14534. },
  14535. back: function() {
  14536. var
  14537. translate = {
  14538. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  14539. }
  14540. ;
  14541. return {
  14542. transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
  14543. };
  14544. }
  14545. },
  14546. transitionEvent: function() {
  14547. var
  14548. element = document.createElement('element'),
  14549. transitions = {
  14550. 'transition' :'transitionend',
  14551. 'OTransition' :'oTransitionEnd',
  14552. 'MozTransition' :'transitionend',
  14553. 'WebkitTransition' :'webkitTransitionEnd'
  14554. },
  14555. transition
  14556. ;
  14557. for(transition in transitions){
  14558. if( element.style[transition] !== undefined ){
  14559. return transitions[transition];
  14560. }
  14561. }
  14562. },
  14563. nextSide: function() {
  14564. return ( $activeSide.next(selector.side).length > 0 )
  14565. ? $activeSide.next(selector.side)
  14566. : $module.find(selector.side).first()
  14567. ;
  14568. }
  14569. },
  14570. stage: {
  14571. above: function() {
  14572. var
  14573. box = {
  14574. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14575. depth : {
  14576. active : ($nextSide.outerHeight(true) / 2),
  14577. next : ($activeSide.outerHeight(true) / 2)
  14578. }
  14579. }
  14580. ;
  14581. module.verbose('Setting the initial animation position as above', $nextSide, box);
  14582. $sides
  14583. .css({
  14584. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14585. })
  14586. ;
  14587. $activeSide
  14588. .css({
  14589. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14590. })
  14591. ;
  14592. $nextSide
  14593. .addClass(className.animating)
  14594. .css({
  14595. 'top' : box.origin + 'px',
  14596. 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)'
  14597. })
  14598. ;
  14599. },
  14600. below: function() {
  14601. var
  14602. box = {
  14603. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  14604. depth : {
  14605. active : ($nextSide.outerHeight(true) / 2),
  14606. next : ($activeSide.outerHeight(true) / 2)
  14607. }
  14608. }
  14609. ;
  14610. module.verbose('Setting the initial animation position as below', $nextSide, box);
  14611. $sides
  14612. .css({
  14613. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14614. })
  14615. ;
  14616. $activeSide
  14617. .css({
  14618. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14619. })
  14620. ;
  14621. $nextSide
  14622. .addClass(className.animating)
  14623. .css({
  14624. 'top' : box.origin + 'px',
  14625. 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)'
  14626. })
  14627. ;
  14628. },
  14629. left: function() {
  14630. var
  14631. height = {
  14632. active : $activeSide.outerWidth(true),
  14633. next : $nextSide.outerWidth(true)
  14634. },
  14635. box = {
  14636. origin : ( ( height.active - height.next ) / 2),
  14637. depth : {
  14638. active : (height.next / 2),
  14639. next : (height.active / 2)
  14640. }
  14641. }
  14642. ;
  14643. module.verbose('Setting the initial animation position as left', $nextSide, box);
  14644. $sides
  14645. .css({
  14646. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14647. })
  14648. ;
  14649. $activeSide
  14650. .css({
  14651. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14652. })
  14653. ;
  14654. $nextSide
  14655. .addClass(className.animating)
  14656. .css({
  14657. 'left' : box.origin + 'px',
  14658. 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)'
  14659. })
  14660. ;
  14661. },
  14662. right: function() {
  14663. var
  14664. height = {
  14665. active : $activeSide.outerWidth(true),
  14666. next : $nextSide.outerWidth(true)
  14667. },
  14668. box = {
  14669. origin : ( ( height.active - height.next ) / 2),
  14670. depth : {
  14671. active : (height.next / 2),
  14672. next : (height.active / 2)
  14673. }
  14674. }
  14675. ;
  14676. module.verbose('Setting the initial animation position as left', $nextSide, box);
  14677. $sides
  14678. .css({
  14679. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  14680. })
  14681. ;
  14682. $activeSide
  14683. .css({
  14684. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  14685. })
  14686. ;
  14687. $nextSide
  14688. .addClass(className.animating)
  14689. .css({
  14690. 'left' : box.origin + 'px',
  14691. 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)'
  14692. })
  14693. ;
  14694. },
  14695. behind: function() {
  14696. var
  14697. height = {
  14698. active : $activeSide.outerWidth(true),
  14699. next : $nextSide.outerWidth(true)
  14700. },
  14701. box = {
  14702. origin : ( ( height.active - height.next ) / 2),
  14703. depth : {
  14704. active : (height.next / 2),
  14705. next : (height.active / 2)
  14706. }
  14707. }
  14708. ;
  14709. module.verbose('Setting the initial animation position as behind', $nextSide, box);
  14710. $activeSide
  14711. .css({
  14712. 'transform' : 'rotateY(0deg)'
  14713. })
  14714. ;
  14715. $nextSide
  14716. .addClass(className.animating)
  14717. .css({
  14718. 'left' : box.origin + 'px',
  14719. 'transform' : 'rotateY(-180deg)'
  14720. })
  14721. ;
  14722. }
  14723. },
  14724. setting: function(name, value) {
  14725. module.debug('Changing setting', name, value);
  14726. if( $.isPlainObject(name) ) {
  14727. $.extend(true, settings, name);
  14728. }
  14729. else if(value !== undefined) {
  14730. if($.isPlainObject(settings[name])) {
  14731. $.extend(true, settings[name], value);
  14732. }
  14733. else {
  14734. settings[name] = value;
  14735. }
  14736. }
  14737. else {
  14738. return settings[name];
  14739. }
  14740. },
  14741. internal: function(name, value) {
  14742. if( $.isPlainObject(name) ) {
  14743. $.extend(true, module, name);
  14744. }
  14745. else if(value !== undefined) {
  14746. module[name] = value;
  14747. }
  14748. else {
  14749. return module[name];
  14750. }
  14751. },
  14752. debug: function() {
  14753. if(!settings.silent && settings.debug) {
  14754. if(settings.performance) {
  14755. module.performance.log(arguments);
  14756. }
  14757. else {
  14758. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14759. module.debug.apply(console, arguments);
  14760. }
  14761. }
  14762. },
  14763. verbose: function() {
  14764. if(!settings.silent && settings.verbose && settings.debug) {
  14765. if(settings.performance) {
  14766. module.performance.log(arguments);
  14767. }
  14768. else {
  14769. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14770. module.verbose.apply(console, arguments);
  14771. }
  14772. }
  14773. },
  14774. error: function() {
  14775. if(!settings.silent) {
  14776. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  14777. module.error.apply(console, arguments);
  14778. }
  14779. },
  14780. performance: {
  14781. log: function(message) {
  14782. var
  14783. currentTime,
  14784. executionTime,
  14785. previousTime
  14786. ;
  14787. if(settings.performance) {
  14788. currentTime = new Date().getTime();
  14789. previousTime = time || currentTime;
  14790. executionTime = currentTime - previousTime;
  14791. time = currentTime;
  14792. performance.push({
  14793. 'Name' : message[0],
  14794. 'Arguments' : [].slice.call(message, 1) || '',
  14795. 'Element' : element,
  14796. 'Execution Time' : executionTime
  14797. });
  14798. }
  14799. clearTimeout(module.performance.timer);
  14800. module.performance.timer = setTimeout(module.performance.display, 500);
  14801. },
  14802. display: function() {
  14803. var
  14804. title = settings.name + ':',
  14805. totalTime = 0
  14806. ;
  14807. time = false;
  14808. clearTimeout(module.performance.timer);
  14809. $.each(performance, function(index, data) {
  14810. totalTime += data['Execution Time'];
  14811. });
  14812. title += ' ' + totalTime + 'ms';
  14813. if(moduleSelector) {
  14814. title += ' \'' + moduleSelector + '\'';
  14815. }
  14816. if($allModules.length > 1) {
  14817. title += ' ' + '(' + $allModules.length + ')';
  14818. }
  14819. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  14820. console.groupCollapsed(title);
  14821. if(console.table) {
  14822. console.table(performance);
  14823. }
  14824. else {
  14825. $.each(performance, function(index, data) {
  14826. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  14827. });
  14828. }
  14829. console.groupEnd();
  14830. }
  14831. performance = [];
  14832. }
  14833. },
  14834. invoke: function(query, passedArguments, context) {
  14835. var
  14836. object = instance,
  14837. maxDepth,
  14838. found,
  14839. response
  14840. ;
  14841. passedArguments = passedArguments || queryArguments;
  14842. context = element || context;
  14843. if(typeof query == 'string' && object !== undefined) {
  14844. query = query.split(/[\. ]/);
  14845. maxDepth = query.length - 1;
  14846. $.each(query, function(depth, value) {
  14847. var camelCaseValue = (depth != maxDepth)
  14848. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  14849. : query
  14850. ;
  14851. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  14852. object = object[camelCaseValue];
  14853. }
  14854. else if( object[camelCaseValue] !== undefined ) {
  14855. found = object[camelCaseValue];
  14856. return false;
  14857. }
  14858. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  14859. object = object[value];
  14860. }
  14861. else if( object[value] !== undefined ) {
  14862. found = object[value];
  14863. return false;
  14864. }
  14865. else {
  14866. return false;
  14867. }
  14868. });
  14869. }
  14870. if ( $.isFunction( found ) ) {
  14871. response = found.apply(context, passedArguments);
  14872. }
  14873. else if(found !== undefined) {
  14874. response = found;
  14875. }
  14876. if($.isArray(returnedValue)) {
  14877. returnedValue.push(response);
  14878. }
  14879. else if(returnedValue !== undefined) {
  14880. returnedValue = [returnedValue, response];
  14881. }
  14882. else if(response !== undefined) {
  14883. returnedValue = response;
  14884. }
  14885. return found;
  14886. }
  14887. };
  14888. if(methodInvoked) {
  14889. if(instance === undefined) {
  14890. module.initialize();
  14891. }
  14892. module.invoke(query);
  14893. }
  14894. else {
  14895. if(instance !== undefined) {
  14896. instance.invoke('destroy');
  14897. }
  14898. module.initialize();
  14899. }
  14900. })
  14901. ;
  14902. return (returnedValue !== undefined)
  14903. ? returnedValue
  14904. : this
  14905. ;
  14906. };
  14907. $.fn.shape.settings = {
  14908. // module info
  14909. name : 'Shape',
  14910. // hide all debug content
  14911. silent : false,
  14912. // debug content outputted to console
  14913. debug : false,
  14914. // verbose debug output
  14915. verbose : false,
  14916. // fudge factor in pixels when swapping from 2d to 3d (can be useful to correct rounding errors)
  14917. jitter : 0,
  14918. // performance data output
  14919. performance: true,
  14920. // event namespace
  14921. namespace : 'shape',
  14922. // width during animation, can be set to 'auto', initial', 'next' or pixel amount
  14923. width: 'initial',
  14924. // height during animation, can be set to 'auto', 'initial', 'next' or pixel amount
  14925. height: 'initial',
  14926. // callback occurs on side change
  14927. beforeChange : function() {},
  14928. onChange : function() {},
  14929. // allow animation to same side
  14930. allowRepeats: false,
  14931. // animation duration
  14932. duration : false,
  14933. // possible errors
  14934. error: {
  14935. side : 'You tried to switch to a side that does not exist.',
  14936. method : 'The method you called is not defined'
  14937. },
  14938. // classnames used
  14939. className : {
  14940. animating : 'animating',
  14941. hidden : 'hidden',
  14942. loading : 'loading',
  14943. active : 'active'
  14944. },
  14945. // selectors used
  14946. selector : {
  14947. sides : '.sides',
  14948. side : '.side'
  14949. }
  14950. };
  14951. })( jQuery, window, document );
  14952. /*!
  14953. * # Semantic UI 2.4.1 - Sidebar
  14954. * http://github.com/semantic-org/semantic-ui/
  14955. *
  14956. *
  14957. * Released under the MIT license
  14958. * http://opensource.org/licenses/MIT
  14959. *
  14960. */
  14961. ;(function ($, window, document, undefined) {
  14962. 'use strict';
  14963. window = (typeof window != 'undefined' && window.Math == Math)
  14964. ? window
  14965. : (typeof self != 'undefined' && self.Math == Math)
  14966. ? self
  14967. : Function('return this')()
  14968. ;
  14969. $.fn.sidebar = function(parameters) {
  14970. var
  14971. $allModules = $(this),
  14972. $window = $(window),
  14973. $document = $(document),
  14974. $html = $('html'),
  14975. $head = $('head'),
  14976. moduleSelector = $allModules.selector || '',
  14977. time = new Date().getTime(),
  14978. performance = [],
  14979. query = arguments[0],
  14980. methodInvoked = (typeof query == 'string'),
  14981. queryArguments = [].slice.call(arguments, 1),
  14982. requestAnimationFrame = window.requestAnimationFrame
  14983. || window.mozRequestAnimationFrame
  14984. || window.webkitRequestAnimationFrame
  14985. || window.msRequestAnimationFrame
  14986. || function(callback) { setTimeout(callback, 0); },
  14987. returnedValue
  14988. ;
  14989. $allModules
  14990. .each(function() {
  14991. var
  14992. settings = ( $.isPlainObject(parameters) )
  14993. ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
  14994. : $.extend({}, $.fn.sidebar.settings),
  14995. selector = settings.selector,
  14996. className = settings.className,
  14997. namespace = settings.namespace,
  14998. regExp = settings.regExp,
  14999. error = settings.error,
  15000. eventNamespace = '.' + namespace,
  15001. moduleNamespace = 'module-' + namespace,
  15002. $module = $(this),
  15003. $context = $(settings.context),
  15004. $sidebars = $module.children(selector.sidebar),
  15005. $fixed = $context.children(selector.fixed),
  15006. $pusher = $context.children(selector.pusher),
  15007. $style,
  15008. element = this,
  15009. instance = $module.data(moduleNamespace),
  15010. elementNamespace,
  15011. id,
  15012. currentScroll,
  15013. transitionEvent,
  15014. module
  15015. ;
  15016. module = {
  15017. initialize: function() {
  15018. module.debug('Initializing sidebar', parameters);
  15019. module.create.id();
  15020. transitionEvent = module.get.transitionEvent();
  15021. // avoids locking rendering if initialized in onReady
  15022. if(settings.delaySetup) {
  15023. requestAnimationFrame(module.setup.layout);
  15024. }
  15025. else {
  15026. module.setup.layout();
  15027. }
  15028. requestAnimationFrame(function() {
  15029. module.setup.cache();
  15030. });
  15031. module.instantiate();
  15032. },
  15033. instantiate: function() {
  15034. module.verbose('Storing instance of module', module);
  15035. instance = module;
  15036. $module
  15037. .data(moduleNamespace, module)
  15038. ;
  15039. },
  15040. create: {
  15041. id: function() {
  15042. id = (Math.random().toString(16) + '000000000').substr(2,8);
  15043. elementNamespace = '.' + id;
  15044. module.verbose('Creating unique id for element', id);
  15045. }
  15046. },
  15047. destroy: function() {
  15048. module.verbose('Destroying previous module for', $module);
  15049. $module
  15050. .off(eventNamespace)
  15051. .removeData(moduleNamespace)
  15052. ;
  15053. if(module.is.ios()) {
  15054. module.remove.ios();
  15055. }
  15056. // bound by uuid
  15057. $context.off(elementNamespace);
  15058. $window.off(elementNamespace);
  15059. $document.off(elementNamespace);
  15060. },
  15061. event: {
  15062. clickaway: function(event) {
  15063. var
  15064. clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
  15065. clickedContext = ($context.is(event.target))
  15066. ;
  15067. if(clickedInPusher) {
  15068. module.verbose('User clicked on dimmed page');
  15069. module.hide();
  15070. }
  15071. if(clickedContext) {
  15072. module.verbose('User clicked on dimmable context (scaled out page)');
  15073. module.hide();
  15074. }
  15075. },
  15076. touch: function(event) {
  15077. //event.stopPropagation();
  15078. },
  15079. containScroll: function(event) {
  15080. if(element.scrollTop <= 0) {
  15081. element.scrollTop = 1;
  15082. }
  15083. if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
  15084. element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
  15085. }
  15086. },
  15087. scroll: function(event) {
  15088. if( $(event.target).closest(selector.sidebar).length === 0 ) {
  15089. event.preventDefault();
  15090. }
  15091. }
  15092. },
  15093. bind: {
  15094. clickaway: function() {
  15095. module.verbose('Adding clickaway events to context', $context);
  15096. if(settings.closable) {
  15097. $context
  15098. .on('click' + elementNamespace, module.event.clickaway)
  15099. .on('touchend' + elementNamespace, module.event.clickaway)
  15100. ;
  15101. }
  15102. },
  15103. scrollLock: function() {
  15104. if(settings.scrollLock) {
  15105. module.debug('Disabling page scroll');
  15106. $window
  15107. .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
  15108. ;
  15109. }
  15110. module.verbose('Adding events to contain sidebar scroll');
  15111. $document
  15112. .on('touchmove' + elementNamespace, module.event.touch)
  15113. ;
  15114. $module
  15115. .on('scroll' + eventNamespace, module.event.containScroll)
  15116. ;
  15117. }
  15118. },
  15119. unbind: {
  15120. clickaway: function() {
  15121. module.verbose('Removing clickaway events from context', $context);
  15122. $context.off(elementNamespace);
  15123. },
  15124. scrollLock: function() {
  15125. module.verbose('Removing scroll lock from page');
  15126. $document.off(elementNamespace);
  15127. $window.off(elementNamespace);
  15128. $module.off('scroll' + eventNamespace);
  15129. }
  15130. },
  15131. add: {
  15132. inlineCSS: function() {
  15133. var
  15134. width = module.cache.width || $module.outerWidth(),
  15135. height = module.cache.height || $module.outerHeight(),
  15136. isRTL = module.is.rtl(),
  15137. direction = module.get.direction(),
  15138. distance = {
  15139. left : width,
  15140. right : -width,
  15141. top : height,
  15142. bottom : -height
  15143. },
  15144. style
  15145. ;
  15146. if(isRTL){
  15147. module.verbose('RTL detected, flipping widths');
  15148. distance.left = -width;
  15149. distance.right = width;
  15150. }
  15151. style = '<style>';
  15152. if(direction === 'left' || direction === 'right') {
  15153. module.debug('Adding CSS rules for animation distance', width);
  15154. style += ''
  15155. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  15156. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  15157. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15158. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15159. + ' }'
  15160. ;
  15161. }
  15162. else if(direction === 'top' || direction == 'bottom') {
  15163. style += ''
  15164. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  15165. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  15166. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15167. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15168. + ' }'
  15169. ;
  15170. }
  15171. /* IE is only browser not to create context with transforms */
  15172. /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
  15173. if( module.is.ie() ) {
  15174. if(direction === 'left' || direction === 'right') {
  15175. module.debug('Adding CSS rules for animation distance', width);
  15176. style += ''
  15177. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  15178. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15179. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  15180. + ' }'
  15181. ;
  15182. }
  15183. else if(direction === 'top' || direction == 'bottom') {
  15184. style += ''
  15185. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  15186. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15187. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  15188. + ' }'
  15189. ;
  15190. }
  15191. /* opposite sides visible forces content overlay */
  15192. style += ''
  15193. + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
  15194. + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
  15195. + ' -webkit-transform: translate3d(0px, 0, 0);'
  15196. + ' transform: translate3d(0px, 0, 0);'
  15197. + ' }'
  15198. ;
  15199. }
  15200. style += '</style>';
  15201. $style = $(style)
  15202. .appendTo($head)
  15203. ;
  15204. module.debug('Adding sizing css to head', $style);
  15205. }
  15206. },
  15207. refresh: function() {
  15208. module.verbose('Refreshing selector cache');
  15209. $context = $(settings.context);
  15210. $sidebars = $context.children(selector.sidebar);
  15211. $pusher = $context.children(selector.pusher);
  15212. $fixed = $context.children(selector.fixed);
  15213. module.clear.cache();
  15214. },
  15215. refreshSidebars: function() {
  15216. module.verbose('Refreshing other sidebars');
  15217. $sidebars = $context.children(selector.sidebar);
  15218. },
  15219. repaint: function() {
  15220. module.verbose('Forcing repaint event');
  15221. element.style.display = 'none';
  15222. var ignored = element.offsetHeight;
  15223. element.scrollTop = element.scrollTop;
  15224. element.style.display = '';
  15225. },
  15226. setup: {
  15227. cache: function() {
  15228. module.cache = {
  15229. width : $module.outerWidth(),
  15230. height : $module.outerHeight(),
  15231. rtl : ($module.css('direction') == 'rtl')
  15232. };
  15233. },
  15234. layout: function() {
  15235. if( $context.children(selector.pusher).length === 0 ) {
  15236. module.debug('Adding wrapper element for sidebar');
  15237. module.error(error.pusher);
  15238. $pusher = $('<div class="pusher" />');
  15239. $context
  15240. .children()
  15241. .not(selector.omitted)
  15242. .not($sidebars)
  15243. .wrapAll($pusher)
  15244. ;
  15245. module.refresh();
  15246. }
  15247. if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
  15248. module.debug('Moved sidebar to correct parent element');
  15249. module.error(error.movedSidebar, element);
  15250. $module.detach().prependTo($context);
  15251. module.refresh();
  15252. }
  15253. module.clear.cache();
  15254. module.set.pushable();
  15255. module.set.direction();
  15256. }
  15257. },
  15258. attachEvents: function(selector, event) {
  15259. var
  15260. $toggle = $(selector)
  15261. ;
  15262. event = $.isFunction(module[event])
  15263. ? module[event]
  15264. : module.toggle
  15265. ;
  15266. if($toggle.length > 0) {
  15267. module.debug('Attaching sidebar events to element', selector, event);
  15268. $toggle
  15269. .on('click' + eventNamespace, event)
  15270. ;
  15271. }
  15272. else {
  15273. module.error(error.notFound, selector);
  15274. }
  15275. },
  15276. show: function(callback) {
  15277. callback = $.isFunction(callback)
  15278. ? callback
  15279. : function(){}
  15280. ;
  15281. if(module.is.hidden()) {
  15282. module.refreshSidebars();
  15283. if(settings.overlay) {
  15284. module.error(error.overlay);
  15285. settings.transition = 'overlay';
  15286. }
  15287. module.refresh();
  15288. if(module.othersActive()) {
  15289. module.debug('Other sidebars currently visible');
  15290. if(settings.exclusive) {
  15291. // if not overlay queue animation after hide
  15292. if(settings.transition != 'overlay') {
  15293. module.hideOthers(module.show);
  15294. return;
  15295. }
  15296. else {
  15297. module.hideOthers();
  15298. }
  15299. }
  15300. else {
  15301. settings.transition = 'overlay';
  15302. }
  15303. }
  15304. module.pushPage(function() {
  15305. callback.call(element);
  15306. settings.onShow.call(element);
  15307. });
  15308. settings.onChange.call(element);
  15309. settings.onVisible.call(element);
  15310. }
  15311. else {
  15312. module.debug('Sidebar is already visible');
  15313. }
  15314. },
  15315. hide: function(callback) {
  15316. callback = $.isFunction(callback)
  15317. ? callback
  15318. : function(){}
  15319. ;
  15320. if(module.is.visible() || module.is.animating()) {
  15321. module.debug('Hiding sidebar', callback);
  15322. module.refreshSidebars();
  15323. module.pullPage(function() {
  15324. callback.call(element);
  15325. settings.onHidden.call(element);
  15326. });
  15327. settings.onChange.call(element);
  15328. settings.onHide.call(element);
  15329. }
  15330. },
  15331. othersAnimating: function() {
  15332. return ($sidebars.not($module).filter('.' + className.animating).length > 0);
  15333. },
  15334. othersVisible: function() {
  15335. return ($sidebars.not($module).filter('.' + className.visible).length > 0);
  15336. },
  15337. othersActive: function() {
  15338. return(module.othersVisible() || module.othersAnimating());
  15339. },
  15340. hideOthers: function(callback) {
  15341. var
  15342. $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
  15343. sidebarCount = $otherSidebars.length,
  15344. callbackCount = 0
  15345. ;
  15346. callback = callback || function(){};
  15347. $otherSidebars
  15348. .sidebar('hide', function() {
  15349. callbackCount++;
  15350. if(callbackCount == sidebarCount) {
  15351. callback();
  15352. }
  15353. })
  15354. ;
  15355. },
  15356. toggle: function() {
  15357. module.verbose('Determining toggled direction');
  15358. if(module.is.hidden()) {
  15359. module.show();
  15360. }
  15361. else {
  15362. module.hide();
  15363. }
  15364. },
  15365. pushPage: function(callback) {
  15366. var
  15367. transition = module.get.transition(),
  15368. $transition = (transition === 'overlay' || module.othersActive())
  15369. ? $module
  15370. : $pusher,
  15371. animate,
  15372. dim,
  15373. transitionEnd
  15374. ;
  15375. callback = $.isFunction(callback)
  15376. ? callback
  15377. : function(){}
  15378. ;
  15379. if(settings.transition == 'scale down') {
  15380. module.scrollToTop();
  15381. }
  15382. module.set.transition(transition);
  15383. module.repaint();
  15384. animate = function() {
  15385. module.bind.clickaway();
  15386. module.add.inlineCSS();
  15387. module.set.animating();
  15388. module.set.visible();
  15389. };
  15390. dim = function() {
  15391. module.set.dimmed();
  15392. };
  15393. transitionEnd = function(event) {
  15394. if( event.target == $transition[0] ) {
  15395. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  15396. module.remove.animating();
  15397. module.bind.scrollLock();
  15398. callback.call(element);
  15399. }
  15400. };
  15401. $transition.off(transitionEvent + elementNamespace);
  15402. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  15403. requestAnimationFrame(animate);
  15404. if(settings.dimPage && !module.othersVisible()) {
  15405. requestAnimationFrame(dim);
  15406. }
  15407. },
  15408. pullPage: function(callback) {
  15409. var
  15410. transition = module.get.transition(),
  15411. $transition = (transition == 'overlay' || module.othersActive())
  15412. ? $module
  15413. : $pusher,
  15414. animate,
  15415. transitionEnd
  15416. ;
  15417. callback = $.isFunction(callback)
  15418. ? callback
  15419. : function(){}
  15420. ;
  15421. module.verbose('Removing context push state', module.get.direction());
  15422. module.unbind.clickaway();
  15423. module.unbind.scrollLock();
  15424. animate = function() {
  15425. module.set.transition(transition);
  15426. module.set.animating();
  15427. module.remove.visible();
  15428. if(settings.dimPage && !module.othersVisible()) {
  15429. $pusher.removeClass(className.dimmed);
  15430. }
  15431. };
  15432. transitionEnd = function(event) {
  15433. if( event.target == $transition[0] ) {
  15434. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  15435. module.remove.animating();
  15436. module.remove.transition();
  15437. module.remove.inlineCSS();
  15438. if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
  15439. module.scrollBack();
  15440. }
  15441. callback.call(element);
  15442. }
  15443. };
  15444. $transition.off(transitionEvent + elementNamespace);
  15445. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  15446. requestAnimationFrame(animate);
  15447. },
  15448. scrollToTop: function() {
  15449. module.verbose('Scrolling to top of page to avoid animation issues');
  15450. currentScroll = $(window).scrollTop();
  15451. $module.scrollTop(0);
  15452. window.scrollTo(0, 0);
  15453. },
  15454. scrollBack: function() {
  15455. module.verbose('Scrolling back to original page position');
  15456. window.scrollTo(0, currentScroll);
  15457. },
  15458. clear: {
  15459. cache: function() {
  15460. module.verbose('Clearing cached dimensions');
  15461. module.cache = {};
  15462. }
  15463. },
  15464. set: {
  15465. // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
  15466. // (This is no longer necessary in latest iOS)
  15467. ios: function() {
  15468. $html.addClass(className.ios);
  15469. },
  15470. // container
  15471. pushed: function() {
  15472. $context.addClass(className.pushed);
  15473. },
  15474. pushable: function() {
  15475. $context.addClass(className.pushable);
  15476. },
  15477. // pusher
  15478. dimmed: function() {
  15479. $pusher.addClass(className.dimmed);
  15480. },
  15481. // sidebar
  15482. active: function() {
  15483. $module.addClass(className.active);
  15484. },
  15485. animating: function() {
  15486. $module.addClass(className.animating);
  15487. },
  15488. transition: function(transition) {
  15489. transition = transition || module.get.transition();
  15490. $module.addClass(transition);
  15491. },
  15492. direction: function(direction) {
  15493. direction = direction || module.get.direction();
  15494. $module.addClass(className[direction]);
  15495. },
  15496. visible: function() {
  15497. $module.addClass(className.visible);
  15498. },
  15499. overlay: function() {
  15500. $module.addClass(className.overlay);
  15501. }
  15502. },
  15503. remove: {
  15504. inlineCSS: function() {
  15505. module.debug('Removing inline css styles', $style);
  15506. if($style && $style.length > 0) {
  15507. $style.remove();
  15508. }
  15509. },
  15510. // ios scroll on html not document
  15511. ios: function() {
  15512. $html.removeClass(className.ios);
  15513. },
  15514. // context
  15515. pushed: function() {
  15516. $context.removeClass(className.pushed);
  15517. },
  15518. pushable: function() {
  15519. $context.removeClass(className.pushable);
  15520. },
  15521. // sidebar
  15522. active: function() {
  15523. $module.removeClass(className.active);
  15524. },
  15525. animating: function() {
  15526. $module.removeClass(className.animating);
  15527. },
  15528. transition: function(transition) {
  15529. transition = transition || module.get.transition();
  15530. $module.removeClass(transition);
  15531. },
  15532. direction: function(direction) {
  15533. direction = direction || module.get.direction();
  15534. $module.removeClass(className[direction]);
  15535. },
  15536. visible: function() {
  15537. $module.removeClass(className.visible);
  15538. },
  15539. overlay: function() {
  15540. $module.removeClass(className.overlay);
  15541. }
  15542. },
  15543. get: {
  15544. direction: function() {
  15545. if($module.hasClass(className.top)) {
  15546. return className.top;
  15547. }
  15548. else if($module.hasClass(className.right)) {
  15549. return className.right;
  15550. }
  15551. else if($module.hasClass(className.bottom)) {
  15552. return className.bottom;
  15553. }
  15554. return className.left;
  15555. },
  15556. transition: function() {
  15557. var
  15558. direction = module.get.direction(),
  15559. transition
  15560. ;
  15561. transition = ( module.is.mobile() )
  15562. ? (settings.mobileTransition == 'auto')
  15563. ? settings.defaultTransition.mobile[direction]
  15564. : settings.mobileTransition
  15565. : (settings.transition == 'auto')
  15566. ? settings.defaultTransition.computer[direction]
  15567. : settings.transition
  15568. ;
  15569. module.verbose('Determined transition', transition);
  15570. return transition;
  15571. },
  15572. transitionEvent: function() {
  15573. var
  15574. element = document.createElement('element'),
  15575. transitions = {
  15576. 'transition' :'transitionend',
  15577. 'OTransition' :'oTransitionEnd',
  15578. 'MozTransition' :'transitionend',
  15579. 'WebkitTransition' :'webkitTransitionEnd'
  15580. },
  15581. transition
  15582. ;
  15583. for(transition in transitions){
  15584. if( element.style[transition] !== undefined ){
  15585. return transitions[transition];
  15586. }
  15587. }
  15588. }
  15589. },
  15590. is: {
  15591. ie: function() {
  15592. var
  15593. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  15594. isIE = ('ActiveXObject' in window)
  15595. ;
  15596. return (isIE11 || isIE);
  15597. },
  15598. ios: function() {
  15599. var
  15600. userAgent = navigator.userAgent,
  15601. isIOS = userAgent.match(regExp.ios),
  15602. isMobileChrome = userAgent.match(regExp.mobileChrome)
  15603. ;
  15604. if(isIOS && !isMobileChrome) {
  15605. module.verbose('Browser was found to be iOS', userAgent);
  15606. return true;
  15607. }
  15608. else {
  15609. return false;
  15610. }
  15611. },
  15612. mobile: function() {
  15613. var
  15614. userAgent = navigator.userAgent,
  15615. isMobile = userAgent.match(regExp.mobile)
  15616. ;
  15617. if(isMobile) {
  15618. module.verbose('Browser was found to be mobile', userAgent);
  15619. return true;
  15620. }
  15621. else {
  15622. module.verbose('Browser is not mobile, using regular transition', userAgent);
  15623. return false;
  15624. }
  15625. },
  15626. hidden: function() {
  15627. return !module.is.visible();
  15628. },
  15629. visible: function() {
  15630. return $module.hasClass(className.visible);
  15631. },
  15632. // alias
  15633. open: function() {
  15634. return module.is.visible();
  15635. },
  15636. closed: function() {
  15637. return module.is.hidden();
  15638. },
  15639. vertical: function() {
  15640. return $module.hasClass(className.top);
  15641. },
  15642. animating: function() {
  15643. return $context.hasClass(className.animating);
  15644. },
  15645. rtl: function () {
  15646. if(module.cache.rtl === undefined) {
  15647. module.cache.rtl = ($module.css('direction') == 'rtl');
  15648. }
  15649. return module.cache.rtl;
  15650. }
  15651. },
  15652. setting: function(name, value) {
  15653. module.debug('Changing setting', name, value);
  15654. if( $.isPlainObject(name) ) {
  15655. $.extend(true, settings, name);
  15656. }
  15657. else if(value !== undefined) {
  15658. if($.isPlainObject(settings[name])) {
  15659. $.extend(true, settings[name], value);
  15660. }
  15661. else {
  15662. settings[name] = value;
  15663. }
  15664. }
  15665. else {
  15666. return settings[name];
  15667. }
  15668. },
  15669. internal: function(name, value) {
  15670. if( $.isPlainObject(name) ) {
  15671. $.extend(true, module, name);
  15672. }
  15673. else if(value !== undefined) {
  15674. module[name] = value;
  15675. }
  15676. else {
  15677. return module[name];
  15678. }
  15679. },
  15680. debug: function() {
  15681. if(!settings.silent && settings.debug) {
  15682. if(settings.performance) {
  15683. module.performance.log(arguments);
  15684. }
  15685. else {
  15686. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15687. module.debug.apply(console, arguments);
  15688. }
  15689. }
  15690. },
  15691. verbose: function() {
  15692. if(!settings.silent && settings.verbose && settings.debug) {
  15693. if(settings.performance) {
  15694. module.performance.log(arguments);
  15695. }
  15696. else {
  15697. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15698. module.verbose.apply(console, arguments);
  15699. }
  15700. }
  15701. },
  15702. error: function() {
  15703. if(!settings.silent) {
  15704. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  15705. module.error.apply(console, arguments);
  15706. }
  15707. },
  15708. performance: {
  15709. log: function(message) {
  15710. var
  15711. currentTime,
  15712. executionTime,
  15713. previousTime
  15714. ;
  15715. if(settings.performance) {
  15716. currentTime = new Date().getTime();
  15717. previousTime = time || currentTime;
  15718. executionTime = currentTime - previousTime;
  15719. time = currentTime;
  15720. performance.push({
  15721. 'Name' : message[0],
  15722. 'Arguments' : [].slice.call(message, 1) || '',
  15723. 'Element' : element,
  15724. 'Execution Time' : executionTime
  15725. });
  15726. }
  15727. clearTimeout(module.performance.timer);
  15728. module.performance.timer = setTimeout(module.performance.display, 500);
  15729. },
  15730. display: function() {
  15731. var
  15732. title = settings.name + ':',
  15733. totalTime = 0
  15734. ;
  15735. time = false;
  15736. clearTimeout(module.performance.timer);
  15737. $.each(performance, function(index, data) {
  15738. totalTime += data['Execution Time'];
  15739. });
  15740. title += ' ' + totalTime + 'ms';
  15741. if(moduleSelector) {
  15742. title += ' \'' + moduleSelector + '\'';
  15743. }
  15744. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  15745. console.groupCollapsed(title);
  15746. if(console.table) {
  15747. console.table(performance);
  15748. }
  15749. else {
  15750. $.each(performance, function(index, data) {
  15751. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  15752. });
  15753. }
  15754. console.groupEnd();
  15755. }
  15756. performance = [];
  15757. }
  15758. },
  15759. invoke: function(query, passedArguments, context) {
  15760. var
  15761. object = instance,
  15762. maxDepth,
  15763. found,
  15764. response
  15765. ;
  15766. passedArguments = passedArguments || queryArguments;
  15767. context = element || context;
  15768. if(typeof query == 'string' && object !== undefined) {
  15769. query = query.split(/[\. ]/);
  15770. maxDepth = query.length - 1;
  15771. $.each(query, function(depth, value) {
  15772. var camelCaseValue = (depth != maxDepth)
  15773. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  15774. : query
  15775. ;
  15776. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  15777. object = object[camelCaseValue];
  15778. }
  15779. else if( object[camelCaseValue] !== undefined ) {
  15780. found = object[camelCaseValue];
  15781. return false;
  15782. }
  15783. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  15784. object = object[value];
  15785. }
  15786. else if( object[value] !== undefined ) {
  15787. found = object[value];
  15788. return false;
  15789. }
  15790. else {
  15791. module.error(error.method, query);
  15792. return false;
  15793. }
  15794. });
  15795. }
  15796. if ( $.isFunction( found ) ) {
  15797. response = found.apply(context, passedArguments);
  15798. }
  15799. else if(found !== undefined) {
  15800. response = found;
  15801. }
  15802. if($.isArray(returnedValue)) {
  15803. returnedValue.push(response);
  15804. }
  15805. else if(returnedValue !== undefined) {
  15806. returnedValue = [returnedValue, response];
  15807. }
  15808. else if(response !== undefined) {
  15809. returnedValue = response;
  15810. }
  15811. return found;
  15812. }
  15813. }
  15814. ;
  15815. if(methodInvoked) {
  15816. if(instance === undefined) {
  15817. module.initialize();
  15818. }
  15819. module.invoke(query);
  15820. }
  15821. else {
  15822. if(instance !== undefined) {
  15823. module.invoke('destroy');
  15824. }
  15825. module.initialize();
  15826. }
  15827. });
  15828. return (returnedValue !== undefined)
  15829. ? returnedValue
  15830. : this
  15831. ;
  15832. };
  15833. $.fn.sidebar.settings = {
  15834. name : 'Sidebar',
  15835. namespace : 'sidebar',
  15836. silent : false,
  15837. debug : false,
  15838. verbose : false,
  15839. performance : true,
  15840. transition : 'auto',
  15841. mobileTransition : 'auto',
  15842. defaultTransition : {
  15843. computer: {
  15844. left : 'uncover',
  15845. right : 'uncover',
  15846. top : 'overlay',
  15847. bottom : 'overlay'
  15848. },
  15849. mobile: {
  15850. left : 'uncover',
  15851. right : 'uncover',
  15852. top : 'overlay',
  15853. bottom : 'overlay'
  15854. }
  15855. },
  15856. context : 'body',
  15857. exclusive : false,
  15858. closable : true,
  15859. dimPage : true,
  15860. scrollLock : false,
  15861. returnScroll : false,
  15862. delaySetup : false,
  15863. duration : 500,
  15864. onChange : function(){},
  15865. onShow : function(){},
  15866. onHide : function(){},
  15867. onHidden : function(){},
  15868. onVisible : function(){},
  15869. className : {
  15870. active : 'active',
  15871. animating : 'animating',
  15872. dimmed : 'dimmed',
  15873. ios : 'ios',
  15874. pushable : 'pushable',
  15875. pushed : 'pushed',
  15876. right : 'right',
  15877. top : 'top',
  15878. left : 'left',
  15879. bottom : 'bottom',
  15880. visible : 'visible'
  15881. },
  15882. selector: {
  15883. fixed : '.fixed',
  15884. omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
  15885. pusher : '.pusher',
  15886. sidebar : '.ui.sidebar'
  15887. },
  15888. regExp: {
  15889. ios : /(iPad|iPhone|iPod)/g,
  15890. mobileChrome : /(CriOS)/g,
  15891. 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
  15892. },
  15893. error : {
  15894. method : 'The method you called is not defined.',
  15895. pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
  15896. movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
  15897. overlay : 'The overlay setting is no longer supported, use animation: overlay',
  15898. notFound : 'There were no elements that matched the specified selector'
  15899. }
  15900. };
  15901. })( jQuery, window, document );
  15902. /*!
  15903. * # Semantic UI 2.4.1 - Sticky
  15904. * http://github.com/semantic-org/semantic-ui/
  15905. *
  15906. *
  15907. * Released under the MIT license
  15908. * http://opensource.org/licenses/MIT
  15909. *
  15910. */
  15911. ;(function ($, window, document, undefined) {
  15912. 'use strict';
  15913. window = (typeof window != 'undefined' && window.Math == Math)
  15914. ? window
  15915. : (typeof self != 'undefined' && self.Math == Math)
  15916. ? self
  15917. : Function('return this')()
  15918. ;
  15919. $.fn.sticky = function(parameters) {
  15920. var
  15921. $allModules = $(this),
  15922. moduleSelector = $allModules.selector || '',
  15923. time = new Date().getTime(),
  15924. performance = [],
  15925. query = arguments[0],
  15926. methodInvoked = (typeof query == 'string'),
  15927. queryArguments = [].slice.call(arguments, 1),
  15928. returnedValue
  15929. ;
  15930. $allModules
  15931. .each(function() {
  15932. var
  15933. settings = ( $.isPlainObject(parameters) )
  15934. ? $.extend(true, {}, $.fn.sticky.settings, parameters)
  15935. : $.extend({}, $.fn.sticky.settings),
  15936. className = settings.className,
  15937. namespace = settings.namespace,
  15938. error = settings.error,
  15939. eventNamespace = '.' + namespace,
  15940. moduleNamespace = 'module-' + namespace,
  15941. $module = $(this),
  15942. $window = $(window),
  15943. $scroll = $(settings.scrollContext),
  15944. $container,
  15945. $context,
  15946. selector = $module.selector || '',
  15947. instance = $module.data(moduleNamespace),
  15948. requestAnimationFrame = window.requestAnimationFrame
  15949. || window.mozRequestAnimationFrame
  15950. || window.webkitRequestAnimationFrame
  15951. || window.msRequestAnimationFrame
  15952. || function(callback) { setTimeout(callback, 0); },
  15953. element = this,
  15954. documentObserver,
  15955. observer,
  15956. module
  15957. ;
  15958. module = {
  15959. initialize: function() {
  15960. module.determineContainer();
  15961. module.determineContext();
  15962. module.verbose('Initializing sticky', settings, $container);
  15963. module.save.positions();
  15964. module.checkErrors();
  15965. module.bind.events();
  15966. if(settings.observeChanges) {
  15967. module.observeChanges();
  15968. }
  15969. module.instantiate();
  15970. },
  15971. instantiate: function() {
  15972. module.verbose('Storing instance of module', module);
  15973. instance = module;
  15974. $module
  15975. .data(moduleNamespace, module)
  15976. ;
  15977. },
  15978. destroy: function() {
  15979. module.verbose('Destroying previous instance');
  15980. module.reset();
  15981. if(documentObserver) {
  15982. documentObserver.disconnect();
  15983. }
  15984. if(observer) {
  15985. observer.disconnect();
  15986. }
  15987. $window
  15988. .off('load' + eventNamespace, module.event.load)
  15989. .off('resize' + eventNamespace, module.event.resize)
  15990. ;
  15991. $scroll
  15992. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  15993. ;
  15994. $module.removeData(moduleNamespace);
  15995. },
  15996. observeChanges: function() {
  15997. if('MutationObserver' in window) {
  15998. documentObserver = new MutationObserver(module.event.documentChanged);
  15999. observer = new MutationObserver(module.event.changed);
  16000. documentObserver.observe(document, {
  16001. childList : true,
  16002. subtree : true
  16003. });
  16004. observer.observe(element, {
  16005. childList : true,
  16006. subtree : true
  16007. });
  16008. observer.observe($context[0], {
  16009. childList : true,
  16010. subtree : true
  16011. });
  16012. module.debug('Setting up mutation observer', observer);
  16013. }
  16014. },
  16015. determineContainer: function() {
  16016. if(settings.container) {
  16017. $container = $(settings.container);
  16018. }
  16019. else {
  16020. $container = $module.offsetParent();
  16021. }
  16022. },
  16023. determineContext: function() {
  16024. if(settings.context) {
  16025. $context = $(settings.context);
  16026. }
  16027. else {
  16028. $context = $container;
  16029. }
  16030. if($context.length === 0) {
  16031. module.error(error.invalidContext, settings.context, $module);
  16032. return;
  16033. }
  16034. },
  16035. checkErrors: function() {
  16036. if( module.is.hidden() ) {
  16037. module.error(error.visible, $module);
  16038. }
  16039. if(module.cache.element.height > module.cache.context.height) {
  16040. module.reset();
  16041. module.error(error.elementSize, $module);
  16042. return;
  16043. }
  16044. },
  16045. bind: {
  16046. events: function() {
  16047. $window
  16048. .on('load' + eventNamespace, module.event.load)
  16049. .on('resize' + eventNamespace, module.event.resize)
  16050. ;
  16051. // pub/sub pattern
  16052. $scroll
  16053. .off('scroll' + eventNamespace)
  16054. .on('scroll' + eventNamespace, module.event.scroll)
  16055. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  16056. ;
  16057. }
  16058. },
  16059. event: {
  16060. changed: function(mutations) {
  16061. clearTimeout(module.timer);
  16062. module.timer = setTimeout(function() {
  16063. module.verbose('DOM tree modified, updating sticky menu', mutations);
  16064. module.refresh();
  16065. }, 100);
  16066. },
  16067. documentChanged: function(mutations) {
  16068. [].forEach.call(mutations, function(mutation) {
  16069. if(mutation.removedNodes) {
  16070. [].forEach.call(mutation.removedNodes, function(node) {
  16071. if(node == element || $(node).find(element).length > 0) {
  16072. module.debug('Element removed from DOM, tearing down events');
  16073. module.destroy();
  16074. }
  16075. });
  16076. }
  16077. });
  16078. },
  16079. load: function() {
  16080. module.verbose('Page contents finished loading');
  16081. requestAnimationFrame(module.refresh);
  16082. },
  16083. resize: function() {
  16084. module.verbose('Window resized');
  16085. requestAnimationFrame(module.refresh);
  16086. },
  16087. scroll: function() {
  16088. requestAnimationFrame(function() {
  16089. $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
  16090. });
  16091. },
  16092. scrollchange: function(event, scrollPosition) {
  16093. module.stick(scrollPosition);
  16094. settings.onScroll.call(element);
  16095. }
  16096. },
  16097. refresh: function(hardRefresh) {
  16098. module.reset();
  16099. if(!settings.context) {
  16100. module.determineContext();
  16101. }
  16102. if(hardRefresh) {
  16103. module.determineContainer();
  16104. }
  16105. module.save.positions();
  16106. module.stick();
  16107. settings.onReposition.call(element);
  16108. },
  16109. supports: {
  16110. sticky: function() {
  16111. var
  16112. $element = $('<div/>'),
  16113. element = $element[0]
  16114. ;
  16115. $element.addClass(className.supported);
  16116. return($element.css('position').match('sticky'));
  16117. }
  16118. },
  16119. save: {
  16120. lastScroll: function(scroll) {
  16121. module.lastScroll = scroll;
  16122. },
  16123. elementScroll: function(scroll) {
  16124. module.elementScroll = scroll;
  16125. },
  16126. positions: function() {
  16127. var
  16128. scrollContext = {
  16129. height : $scroll.height()
  16130. },
  16131. element = {
  16132. margin: {
  16133. top : parseInt($module.css('margin-top'), 10),
  16134. bottom : parseInt($module.css('margin-bottom'), 10),
  16135. },
  16136. offset : $module.offset(),
  16137. width : $module.outerWidth(),
  16138. height : $module.outerHeight()
  16139. },
  16140. context = {
  16141. offset : $context.offset(),
  16142. height : $context.outerHeight()
  16143. },
  16144. container = {
  16145. height: $container.outerHeight()
  16146. }
  16147. ;
  16148. if( !module.is.standardScroll() ) {
  16149. module.debug('Non-standard scroll. Removing scroll offset from element offset');
  16150. scrollContext.top = $scroll.scrollTop();
  16151. scrollContext.left = $scroll.scrollLeft();
  16152. element.offset.top += scrollContext.top;
  16153. context.offset.top += scrollContext.top;
  16154. element.offset.left += scrollContext.left;
  16155. context.offset.left += scrollContext.left;
  16156. }
  16157. module.cache = {
  16158. fits : ( (element.height + settings.offset) <= scrollContext.height),
  16159. sameHeight : (element.height == context.height),
  16160. scrollContext : {
  16161. height : scrollContext.height
  16162. },
  16163. element: {
  16164. margin : element.margin,
  16165. top : element.offset.top - element.margin.top,
  16166. left : element.offset.left,
  16167. width : element.width,
  16168. height : element.height,
  16169. bottom : element.offset.top + element.height
  16170. },
  16171. context: {
  16172. top : context.offset.top,
  16173. height : context.height,
  16174. bottom : context.offset.top + context.height
  16175. }
  16176. };
  16177. module.set.containerSize();
  16178. module.stick();
  16179. module.debug('Caching element positions', module.cache);
  16180. }
  16181. },
  16182. get: {
  16183. direction: function(scroll) {
  16184. var
  16185. direction = 'down'
  16186. ;
  16187. scroll = scroll || $scroll.scrollTop();
  16188. if(module.lastScroll !== undefined) {
  16189. if(module.lastScroll < scroll) {
  16190. direction = 'down';
  16191. }
  16192. else if(module.lastScroll > scroll) {
  16193. direction = 'up';
  16194. }
  16195. }
  16196. return direction;
  16197. },
  16198. scrollChange: function(scroll) {
  16199. scroll = scroll || $scroll.scrollTop();
  16200. return (module.lastScroll)
  16201. ? (scroll - module.lastScroll)
  16202. : 0
  16203. ;
  16204. },
  16205. currentElementScroll: function() {
  16206. if(module.elementScroll) {
  16207. return module.elementScroll;
  16208. }
  16209. return ( module.is.top() )
  16210. ? Math.abs(parseInt($module.css('top'), 10)) || 0
  16211. : Math.abs(parseInt($module.css('bottom'), 10)) || 0
  16212. ;
  16213. },
  16214. elementScroll: function(scroll) {
  16215. scroll = scroll || $scroll.scrollTop();
  16216. var
  16217. element = module.cache.element,
  16218. scrollContext = module.cache.scrollContext,
  16219. delta = module.get.scrollChange(scroll),
  16220. maxScroll = (element.height - scrollContext.height + settings.offset),
  16221. elementScroll = module.get.currentElementScroll(),
  16222. possibleScroll = (elementScroll + delta)
  16223. ;
  16224. if(module.cache.fits || possibleScroll < 0) {
  16225. elementScroll = 0;
  16226. }
  16227. else if(possibleScroll > maxScroll ) {
  16228. elementScroll = maxScroll;
  16229. }
  16230. else {
  16231. elementScroll = possibleScroll;
  16232. }
  16233. return elementScroll;
  16234. }
  16235. },
  16236. remove: {
  16237. lastScroll: function() {
  16238. delete module.lastScroll;
  16239. },
  16240. elementScroll: function(scroll) {
  16241. delete module.elementScroll;
  16242. },
  16243. minimumSize: function() {
  16244. $container
  16245. .css('min-height', '')
  16246. ;
  16247. },
  16248. offset: function() {
  16249. $module.css('margin-top', '');
  16250. }
  16251. },
  16252. set: {
  16253. offset: function() {
  16254. module.verbose('Setting offset on element', settings.offset);
  16255. $module
  16256. .css('margin-top', settings.offset)
  16257. ;
  16258. },
  16259. containerSize: function() {
  16260. var
  16261. tagName = $container.get(0).tagName
  16262. ;
  16263. if(tagName === 'HTML' || tagName == 'body') {
  16264. // this can trigger for too many reasons
  16265. //module.error(error.container, tagName, $module);
  16266. module.determineContainer();
  16267. }
  16268. else {
  16269. if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
  16270. module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
  16271. $container.css({
  16272. height: module.cache.context.height
  16273. });
  16274. }
  16275. }
  16276. },
  16277. minimumSize: function() {
  16278. var
  16279. element = module.cache.element
  16280. ;
  16281. $container
  16282. .css('min-height', element.height)
  16283. ;
  16284. },
  16285. scroll: function(scroll) {
  16286. module.debug('Setting scroll on element', scroll);
  16287. if(module.elementScroll == scroll) {
  16288. return;
  16289. }
  16290. if( module.is.top() ) {
  16291. $module
  16292. .css('bottom', '')
  16293. .css('top', -scroll)
  16294. ;
  16295. }
  16296. if( module.is.bottom() ) {
  16297. $module
  16298. .css('top', '')
  16299. .css('bottom', scroll)
  16300. ;
  16301. }
  16302. },
  16303. size: function() {
  16304. if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
  16305. element.style.setProperty('width', module.cache.element.width + 'px', 'important');
  16306. element.style.setProperty('height', module.cache.element.height + 'px', 'important');
  16307. }
  16308. }
  16309. },
  16310. is: {
  16311. standardScroll: function() {
  16312. return ($scroll[0] == window);
  16313. },
  16314. top: function() {
  16315. return $module.hasClass(className.top);
  16316. },
  16317. bottom: function() {
  16318. return $module.hasClass(className.bottom);
  16319. },
  16320. initialPosition: function() {
  16321. return (!module.is.fixed() && !module.is.bound());
  16322. },
  16323. hidden: function() {
  16324. return (!$module.is(':visible'));
  16325. },
  16326. bound: function() {
  16327. return $module.hasClass(className.bound);
  16328. },
  16329. fixed: function() {
  16330. return $module.hasClass(className.fixed);
  16331. }
  16332. },
  16333. stick: function(scroll) {
  16334. var
  16335. cachedPosition = scroll || $scroll.scrollTop(),
  16336. cache = module.cache,
  16337. fits = cache.fits,
  16338. sameHeight = cache.sameHeight,
  16339. element = cache.element,
  16340. scrollContext = cache.scrollContext,
  16341. context = cache.context,
  16342. offset = (module.is.bottom() && settings.pushing)
  16343. ? settings.bottomOffset
  16344. : settings.offset,
  16345. scroll = {
  16346. top : cachedPosition + offset,
  16347. bottom : cachedPosition + offset + scrollContext.height
  16348. },
  16349. direction = module.get.direction(scroll.top),
  16350. elementScroll = (fits)
  16351. ? 0
  16352. : module.get.elementScroll(scroll.top),
  16353. // shorthand
  16354. doesntFit = !fits,
  16355. elementVisible = (element.height !== 0)
  16356. ;
  16357. if(elementVisible && !sameHeight) {
  16358. if( module.is.initialPosition() ) {
  16359. if(scroll.top >= context.bottom) {
  16360. module.debug('Initial element position is bottom of container');
  16361. module.bindBottom();
  16362. }
  16363. else if(scroll.top > element.top) {
  16364. if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  16365. module.debug('Initial element position is bottom of container');
  16366. module.bindBottom();
  16367. }
  16368. else {
  16369. module.debug('Initial element position is fixed');
  16370. module.fixTop();
  16371. }
  16372. }
  16373. }
  16374. else if( module.is.fixed() ) {
  16375. // currently fixed top
  16376. if( module.is.top() ) {
  16377. if( scroll.top <= element.top ) {
  16378. module.debug('Fixed element reached top of container');
  16379. module.setInitialPosition();
  16380. }
  16381. else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  16382. module.debug('Fixed element reached bottom of container');
  16383. module.bindBottom();
  16384. }
  16385. // scroll element if larger than screen
  16386. else if(doesntFit) {
  16387. module.set.scroll(elementScroll);
  16388. module.save.lastScroll(scroll.top);
  16389. module.save.elementScroll(elementScroll);
  16390. }
  16391. }
  16392. // currently fixed bottom
  16393. else if(module.is.bottom() ) {
  16394. // top edge
  16395. if( (scroll.bottom - element.height) <= element.top) {
  16396. module.debug('Bottom fixed rail has reached top of container');
  16397. module.setInitialPosition();
  16398. }
  16399. // bottom edge
  16400. else if(scroll.bottom >= context.bottom) {
  16401. module.debug('Bottom fixed rail has reached bottom of container');
  16402. module.bindBottom();
  16403. }
  16404. // scroll element if larger than screen
  16405. else if(doesntFit) {
  16406. module.set.scroll(elementScroll);
  16407. module.save.lastScroll(scroll.top);
  16408. module.save.elementScroll(elementScroll);
  16409. }
  16410. }
  16411. }
  16412. else if( module.is.bottom() ) {
  16413. if( scroll.top <= element.top ) {
  16414. module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
  16415. module.setInitialPosition();
  16416. }
  16417. else {
  16418. if(settings.pushing) {
  16419. if(module.is.bound() && scroll.bottom <= context.bottom ) {
  16420. module.debug('Fixing bottom attached element to bottom of browser.');
  16421. module.fixBottom();
  16422. }
  16423. }
  16424. else {
  16425. if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
  16426. module.debug('Fixing bottom attached element to top of browser.');
  16427. module.fixTop();
  16428. }
  16429. }
  16430. }
  16431. }
  16432. }
  16433. },
  16434. bindTop: function() {
  16435. module.debug('Binding element to top of parent container');
  16436. module.remove.offset();
  16437. $module
  16438. .css({
  16439. left : '',
  16440. top : '',
  16441. marginBottom : ''
  16442. })
  16443. .removeClass(className.fixed)
  16444. .removeClass(className.bottom)
  16445. .addClass(className.bound)
  16446. .addClass(className.top)
  16447. ;
  16448. settings.onTop.call(element);
  16449. settings.onUnstick.call(element);
  16450. },
  16451. bindBottom: function() {
  16452. module.debug('Binding element to bottom of parent container');
  16453. module.remove.offset();
  16454. $module
  16455. .css({
  16456. left : '',
  16457. top : ''
  16458. })
  16459. .removeClass(className.fixed)
  16460. .removeClass(className.top)
  16461. .addClass(className.bound)
  16462. .addClass(className.bottom)
  16463. ;
  16464. settings.onBottom.call(element);
  16465. settings.onUnstick.call(element);
  16466. },
  16467. setInitialPosition: function() {
  16468. module.debug('Returning to initial position');
  16469. module.unfix();
  16470. module.unbind();
  16471. },
  16472. fixTop: function() {
  16473. module.debug('Fixing element to top of page');
  16474. if(settings.setSize) {
  16475. module.set.size();
  16476. }
  16477. module.set.minimumSize();
  16478. module.set.offset();
  16479. $module
  16480. .css({
  16481. left : module.cache.element.left,
  16482. bottom : '',
  16483. marginBottom : ''
  16484. })
  16485. .removeClass(className.bound)
  16486. .removeClass(className.bottom)
  16487. .addClass(className.fixed)
  16488. .addClass(className.top)
  16489. ;
  16490. settings.onStick.call(element);
  16491. },
  16492. fixBottom: function() {
  16493. module.debug('Sticking element to bottom of page');
  16494. if(settings.setSize) {
  16495. module.set.size();
  16496. }
  16497. module.set.minimumSize();
  16498. module.set.offset();
  16499. $module
  16500. .css({
  16501. left : module.cache.element.left,
  16502. bottom : '',
  16503. marginBottom : ''
  16504. })
  16505. .removeClass(className.bound)
  16506. .removeClass(className.top)
  16507. .addClass(className.fixed)
  16508. .addClass(className.bottom)
  16509. ;
  16510. settings.onStick.call(element);
  16511. },
  16512. unbind: function() {
  16513. if( module.is.bound() ) {
  16514. module.debug('Removing container bound position on element');
  16515. module.remove.offset();
  16516. $module
  16517. .removeClass(className.bound)
  16518. .removeClass(className.top)
  16519. .removeClass(className.bottom)
  16520. ;
  16521. }
  16522. },
  16523. unfix: function() {
  16524. if( module.is.fixed() ) {
  16525. module.debug('Removing fixed position on element');
  16526. module.remove.minimumSize();
  16527. module.remove.offset();
  16528. $module
  16529. .removeClass(className.fixed)
  16530. .removeClass(className.top)
  16531. .removeClass(className.bottom)
  16532. ;
  16533. settings.onUnstick.call(element);
  16534. }
  16535. },
  16536. reset: function() {
  16537. module.debug('Resetting elements position');
  16538. module.unbind();
  16539. module.unfix();
  16540. module.resetCSS();
  16541. module.remove.offset();
  16542. module.remove.lastScroll();
  16543. },
  16544. resetCSS: function() {
  16545. $module
  16546. .css({
  16547. width : '',
  16548. height : ''
  16549. })
  16550. ;
  16551. $container
  16552. .css({
  16553. height: ''
  16554. })
  16555. ;
  16556. },
  16557. setting: function(name, value) {
  16558. if( $.isPlainObject(name) ) {
  16559. $.extend(true, settings, name);
  16560. }
  16561. else if(value !== undefined) {
  16562. settings[name] = value;
  16563. }
  16564. else {
  16565. return settings[name];
  16566. }
  16567. },
  16568. internal: function(name, value) {
  16569. if( $.isPlainObject(name) ) {
  16570. $.extend(true, module, name);
  16571. }
  16572. else if(value !== undefined) {
  16573. module[name] = value;
  16574. }
  16575. else {
  16576. return module[name];
  16577. }
  16578. },
  16579. debug: function() {
  16580. if(!settings.silent && settings.debug) {
  16581. if(settings.performance) {
  16582. module.performance.log(arguments);
  16583. }
  16584. else {
  16585. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16586. module.debug.apply(console, arguments);
  16587. }
  16588. }
  16589. },
  16590. verbose: function() {
  16591. if(!settings.silent && settings.verbose && settings.debug) {
  16592. if(settings.performance) {
  16593. module.performance.log(arguments);
  16594. }
  16595. else {
  16596. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16597. module.verbose.apply(console, arguments);
  16598. }
  16599. }
  16600. },
  16601. error: function() {
  16602. if(!settings.silent) {
  16603. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  16604. module.error.apply(console, arguments);
  16605. }
  16606. },
  16607. performance: {
  16608. log: function(message) {
  16609. var
  16610. currentTime,
  16611. executionTime,
  16612. previousTime
  16613. ;
  16614. if(settings.performance) {
  16615. currentTime = new Date().getTime();
  16616. previousTime = time || currentTime;
  16617. executionTime = currentTime - previousTime;
  16618. time = currentTime;
  16619. performance.push({
  16620. 'Name' : message[0],
  16621. 'Arguments' : [].slice.call(message, 1) || '',
  16622. 'Element' : element,
  16623. 'Execution Time' : executionTime
  16624. });
  16625. }
  16626. clearTimeout(module.performance.timer);
  16627. module.performance.timer = setTimeout(module.performance.display, 0);
  16628. },
  16629. display: function() {
  16630. var
  16631. title = settings.name + ':',
  16632. totalTime = 0
  16633. ;
  16634. time = false;
  16635. clearTimeout(module.performance.timer);
  16636. $.each(performance, function(index, data) {
  16637. totalTime += data['Execution Time'];
  16638. });
  16639. title += ' ' + totalTime + 'ms';
  16640. if(moduleSelector) {
  16641. title += ' \'' + moduleSelector + '\'';
  16642. }
  16643. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  16644. console.groupCollapsed(title);
  16645. if(console.table) {
  16646. console.table(performance);
  16647. }
  16648. else {
  16649. $.each(performance, function(index, data) {
  16650. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  16651. });
  16652. }
  16653. console.groupEnd();
  16654. }
  16655. performance = [];
  16656. }
  16657. },
  16658. invoke: function(query, passedArguments, context) {
  16659. var
  16660. object = instance,
  16661. maxDepth,
  16662. found,
  16663. response
  16664. ;
  16665. passedArguments = passedArguments || queryArguments;
  16666. context = element || context;
  16667. if(typeof query == 'string' && object !== undefined) {
  16668. query = query.split(/[\. ]/);
  16669. maxDepth = query.length - 1;
  16670. $.each(query, function(depth, value) {
  16671. var camelCaseValue = (depth != maxDepth)
  16672. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  16673. : query
  16674. ;
  16675. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  16676. object = object[camelCaseValue];
  16677. }
  16678. else if( object[camelCaseValue] !== undefined ) {
  16679. found = object[camelCaseValue];
  16680. return false;
  16681. }
  16682. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  16683. object = object[value];
  16684. }
  16685. else if( object[value] !== undefined ) {
  16686. found = object[value];
  16687. return false;
  16688. }
  16689. else {
  16690. return false;
  16691. }
  16692. });
  16693. }
  16694. if ( $.isFunction( found ) ) {
  16695. response = found.apply(context, passedArguments);
  16696. }
  16697. else if(found !== undefined) {
  16698. response = found;
  16699. }
  16700. if($.isArray(returnedValue)) {
  16701. returnedValue.push(response);
  16702. }
  16703. else if(returnedValue !== undefined) {
  16704. returnedValue = [returnedValue, response];
  16705. }
  16706. else if(response !== undefined) {
  16707. returnedValue = response;
  16708. }
  16709. return found;
  16710. }
  16711. };
  16712. if(methodInvoked) {
  16713. if(instance === undefined) {
  16714. module.initialize();
  16715. }
  16716. module.invoke(query);
  16717. }
  16718. else {
  16719. if(instance !== undefined) {
  16720. instance.invoke('destroy');
  16721. }
  16722. module.initialize();
  16723. }
  16724. })
  16725. ;
  16726. return (returnedValue !== undefined)
  16727. ? returnedValue
  16728. : this
  16729. ;
  16730. };
  16731. $.fn.sticky.settings = {
  16732. name : 'Sticky',
  16733. namespace : 'sticky',
  16734. silent : false,
  16735. debug : false,
  16736. verbose : true,
  16737. performance : true,
  16738. // whether to stick in the opposite direction on scroll up
  16739. pushing : false,
  16740. context : false,
  16741. container : false,
  16742. // Context to watch scroll events
  16743. scrollContext : window,
  16744. // Offset to adjust scroll
  16745. offset : 0,
  16746. // Offset to adjust scroll when attached to bottom of screen
  16747. bottomOffset : 0,
  16748. // will only set container height if difference between context and container is larger than this number
  16749. jitter : 5,
  16750. // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
  16751. setSize : true,
  16752. // Whether to automatically observe changes with Mutation Observers
  16753. observeChanges : false,
  16754. // Called when position is recalculated
  16755. onReposition : function(){},
  16756. // Called on each scroll
  16757. onScroll : function(){},
  16758. // Called when element is stuck to viewport
  16759. onStick : function(){},
  16760. // Called when element is unstuck from viewport
  16761. onUnstick : function(){},
  16762. // Called when element reaches top of context
  16763. onTop : function(){},
  16764. // Called when element reaches bottom of context
  16765. onBottom : function(){},
  16766. error : {
  16767. container : 'Sticky element must be inside a relative container',
  16768. visible : 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to surpress this warning in production.',
  16769. method : 'The method you called is not defined.',
  16770. invalidContext : 'Context specified does not exist',
  16771. elementSize : 'Sticky element is larger than its container, cannot create sticky.'
  16772. },
  16773. className : {
  16774. bound : 'bound',
  16775. fixed : 'fixed',
  16776. supported : 'native',
  16777. top : 'top',
  16778. bottom : 'bottom'
  16779. }
  16780. };
  16781. })( jQuery, window, document );
  16782. /*!
  16783. * # Semantic UI 2.4.1 - Tab
  16784. * http://github.com/semantic-org/semantic-ui/
  16785. *
  16786. *
  16787. * Released under the MIT license
  16788. * http://opensource.org/licenses/MIT
  16789. *
  16790. */
  16791. ;(function ($, window, document, undefined) {
  16792. 'use strict';
  16793. window = (typeof window != 'undefined' && window.Math == Math)
  16794. ? window
  16795. : (typeof self != 'undefined' && self.Math == Math)
  16796. ? self
  16797. : Function('return this')()
  16798. ;
  16799. $.fn.tab = function(parameters) {
  16800. var
  16801. // use window context if none specified
  16802. $allModules = $.isFunction(this)
  16803. ? $(window)
  16804. : $(this),
  16805. moduleSelector = $allModules.selector || '',
  16806. time = new Date().getTime(),
  16807. performance = [],
  16808. query = arguments[0],
  16809. methodInvoked = (typeof query == 'string'),
  16810. queryArguments = [].slice.call(arguments, 1),
  16811. initializedHistory = false,
  16812. returnedValue
  16813. ;
  16814. $allModules
  16815. .each(function() {
  16816. var
  16817. settings = ( $.isPlainObject(parameters) )
  16818. ? $.extend(true, {}, $.fn.tab.settings, parameters)
  16819. : $.extend({}, $.fn.tab.settings),
  16820. className = settings.className,
  16821. metadata = settings.metadata,
  16822. selector = settings.selector,
  16823. error = settings.error,
  16824. eventNamespace = '.' + settings.namespace,
  16825. moduleNamespace = 'module-' + settings.namespace,
  16826. $module = $(this),
  16827. $context,
  16828. $tabs,
  16829. cache = {},
  16830. firstLoad = true,
  16831. recursionDepth = 0,
  16832. element = this,
  16833. instance = $module.data(moduleNamespace),
  16834. activeTabPath,
  16835. parameterArray,
  16836. module,
  16837. historyEvent
  16838. ;
  16839. module = {
  16840. initialize: function() {
  16841. module.debug('Initializing tab menu item', $module);
  16842. module.fix.callbacks();
  16843. module.determineTabs();
  16844. module.debug('Determining tabs', settings.context, $tabs);
  16845. // set up automatic routing
  16846. if(settings.auto) {
  16847. module.set.auto();
  16848. }
  16849. module.bind.events();
  16850. if(settings.history && !initializedHistory) {
  16851. module.initializeHistory();
  16852. initializedHistory = true;
  16853. }
  16854. module.instantiate();
  16855. },
  16856. instantiate: function () {
  16857. module.verbose('Storing instance of module', module);
  16858. instance = module;
  16859. $module
  16860. .data(moduleNamespace, module)
  16861. ;
  16862. },
  16863. destroy: function() {
  16864. module.debug('Destroying tabs', $module);
  16865. $module
  16866. .removeData(moduleNamespace)
  16867. .off(eventNamespace)
  16868. ;
  16869. },
  16870. bind: {
  16871. events: function() {
  16872. // if using $.tab don't add events
  16873. if( !$.isWindow( element ) ) {
  16874. module.debug('Attaching tab activation events to element', $module);
  16875. $module
  16876. .on('click' + eventNamespace, module.event.click)
  16877. ;
  16878. }
  16879. }
  16880. },
  16881. determineTabs: function() {
  16882. var
  16883. $reference
  16884. ;
  16885. // determine tab context
  16886. if(settings.context === 'parent') {
  16887. if($module.closest(selector.ui).length > 0) {
  16888. $reference = $module.closest(selector.ui);
  16889. module.verbose('Using closest UI element as parent', $reference);
  16890. }
  16891. else {
  16892. $reference = $module;
  16893. }
  16894. $context = $reference.parent();
  16895. module.verbose('Determined parent element for creating context', $context);
  16896. }
  16897. else if(settings.context) {
  16898. $context = $(settings.context);
  16899. module.verbose('Using selector for tab context', settings.context, $context);
  16900. }
  16901. else {
  16902. $context = $('body');
  16903. }
  16904. // find tabs
  16905. if(settings.childrenOnly) {
  16906. $tabs = $context.children(selector.tabs);
  16907. module.debug('Searching tab context children for tabs', $context, $tabs);
  16908. }
  16909. else {
  16910. $tabs = $context.find(selector.tabs);
  16911. module.debug('Searching tab context for tabs', $context, $tabs);
  16912. }
  16913. },
  16914. fix: {
  16915. callbacks: function() {
  16916. if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
  16917. if(parameters.onTabLoad) {
  16918. parameters.onLoad = parameters.onTabLoad;
  16919. delete parameters.onTabLoad;
  16920. module.error(error.legacyLoad, parameters.onLoad);
  16921. }
  16922. if(parameters.onTabInit) {
  16923. parameters.onFirstLoad = parameters.onTabInit;
  16924. delete parameters.onTabInit;
  16925. module.error(error.legacyInit, parameters.onFirstLoad);
  16926. }
  16927. settings = $.extend(true, {}, $.fn.tab.settings, parameters);
  16928. }
  16929. }
  16930. },
  16931. initializeHistory: function() {
  16932. module.debug('Initializing page state');
  16933. if( $.address === undefined ) {
  16934. module.error(error.state);
  16935. return false;
  16936. }
  16937. else {
  16938. if(settings.historyType == 'state') {
  16939. module.debug('Using HTML5 to manage state');
  16940. if(settings.path !== false) {
  16941. $.address
  16942. .history(true)
  16943. .state(settings.path)
  16944. ;
  16945. }
  16946. else {
  16947. module.error(error.path);
  16948. return false;
  16949. }
  16950. }
  16951. $.address
  16952. .bind('change', module.event.history.change)
  16953. ;
  16954. }
  16955. },
  16956. event: {
  16957. click: function(event) {
  16958. var
  16959. tabPath = $(this).data(metadata.tab)
  16960. ;
  16961. if(tabPath !== undefined) {
  16962. if(settings.history) {
  16963. module.verbose('Updating page state', event);
  16964. $.address.value(tabPath);
  16965. }
  16966. else {
  16967. module.verbose('Changing tab', event);
  16968. module.changeTab(tabPath);
  16969. }
  16970. event.preventDefault();
  16971. }
  16972. else {
  16973. module.debug('No tab specified');
  16974. }
  16975. },
  16976. history: {
  16977. change: function(event) {
  16978. var
  16979. tabPath = event.pathNames.join('/') || module.get.initialPath(),
  16980. pageTitle = settings.templates.determineTitle(tabPath) || false
  16981. ;
  16982. module.performance.display();
  16983. module.debug('History change event', tabPath, event);
  16984. historyEvent = event;
  16985. if(tabPath !== undefined) {
  16986. module.changeTab(tabPath);
  16987. }
  16988. if(pageTitle) {
  16989. $.address.title(pageTitle);
  16990. }
  16991. }
  16992. }
  16993. },
  16994. refresh: function() {
  16995. if(activeTabPath) {
  16996. module.debug('Refreshing tab', activeTabPath);
  16997. module.changeTab(activeTabPath);
  16998. }
  16999. },
  17000. cache: {
  17001. read: function(cacheKey) {
  17002. return (cacheKey !== undefined)
  17003. ? cache[cacheKey]
  17004. : false
  17005. ;
  17006. },
  17007. add: function(cacheKey, content) {
  17008. cacheKey = cacheKey || activeTabPath;
  17009. module.debug('Adding cached content for', cacheKey);
  17010. cache[cacheKey] = content;
  17011. },
  17012. remove: function(cacheKey) {
  17013. cacheKey = cacheKey || activeTabPath;
  17014. module.debug('Removing cached content for', cacheKey);
  17015. delete cache[cacheKey];
  17016. }
  17017. },
  17018. set: {
  17019. auto: function() {
  17020. var
  17021. url = (typeof settings.path == 'string')
  17022. ? settings.path.replace(/\/$/, '') + '/{$tab}'
  17023. : '/{$tab}'
  17024. ;
  17025. module.verbose('Setting up automatic tab retrieval from server', url);
  17026. if($.isPlainObject(settings.apiSettings)) {
  17027. settings.apiSettings.url = url;
  17028. }
  17029. else {
  17030. settings.apiSettings = {
  17031. url: url
  17032. };
  17033. }
  17034. },
  17035. loading: function(tabPath) {
  17036. var
  17037. $tab = module.get.tabElement(tabPath),
  17038. isLoading = $tab.hasClass(className.loading)
  17039. ;
  17040. if(!isLoading) {
  17041. module.verbose('Setting loading state for', $tab);
  17042. $tab
  17043. .addClass(className.loading)
  17044. .siblings($tabs)
  17045. .removeClass(className.active + ' ' + className.loading)
  17046. ;
  17047. if($tab.length > 0) {
  17048. settings.onRequest.call($tab[0], tabPath);
  17049. }
  17050. }
  17051. },
  17052. state: function(state) {
  17053. $.address.value(state);
  17054. }
  17055. },
  17056. changeTab: function(tabPath) {
  17057. var
  17058. pushStateAvailable = (window.history && window.history.pushState),
  17059. shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
  17060. remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
  17061. // only add default path if not remote content
  17062. pathArray = (remoteContent && !shouldIgnoreLoad)
  17063. ? module.utilities.pathToArray(tabPath)
  17064. : module.get.defaultPathArray(tabPath)
  17065. ;
  17066. tabPath = module.utilities.arrayToPath(pathArray);
  17067. $.each(pathArray, function(index, tab) {
  17068. var
  17069. currentPathArray = pathArray.slice(0, index + 1),
  17070. currentPath = module.utilities.arrayToPath(currentPathArray),
  17071. isTab = module.is.tab(currentPath),
  17072. isLastIndex = (index + 1 == pathArray.length),
  17073. $tab = module.get.tabElement(currentPath),
  17074. $anchor,
  17075. nextPathArray,
  17076. nextPath,
  17077. isLastTab
  17078. ;
  17079. module.verbose('Looking for tab', tab);
  17080. if(isTab) {
  17081. module.verbose('Tab was found', tab);
  17082. // scope up
  17083. activeTabPath = currentPath;
  17084. parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
  17085. if(isLastIndex) {
  17086. isLastTab = true;
  17087. }
  17088. else {
  17089. nextPathArray = pathArray.slice(0, index + 2);
  17090. nextPath = module.utilities.arrayToPath(nextPathArray);
  17091. isLastTab = ( !module.is.tab(nextPath) );
  17092. if(isLastTab) {
  17093. module.verbose('Tab parameters found', nextPathArray);
  17094. }
  17095. }
  17096. if(isLastTab && remoteContent) {
  17097. if(!shouldIgnoreLoad) {
  17098. module.activate.navigation(currentPath);
  17099. module.fetch.content(currentPath, tabPath);
  17100. }
  17101. else {
  17102. module.debug('Ignoring remote content on first tab load', currentPath);
  17103. firstLoad = false;
  17104. module.cache.add(tabPath, $tab.html());
  17105. module.activate.all(currentPath);
  17106. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  17107. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  17108. }
  17109. return false;
  17110. }
  17111. else {
  17112. module.debug('Opened local tab', currentPath);
  17113. module.activate.all(currentPath);
  17114. if( !module.cache.read(currentPath) ) {
  17115. module.cache.add(currentPath, true);
  17116. module.debug('First time tab loaded calling tab init');
  17117. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  17118. }
  17119. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  17120. }
  17121. }
  17122. else if(tabPath.search('/') == -1 && tabPath !== '') {
  17123. // look for in page anchor
  17124. $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
  17125. currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
  17126. $tab = module.get.tabElement(currentPath);
  17127. // if anchor exists use parent tab
  17128. if($anchor && $anchor.length > 0 && currentPath) {
  17129. module.debug('Anchor link used, opening parent tab', $tab, $anchor);
  17130. if( !$tab.hasClass(className.active) ) {
  17131. setTimeout(function() {
  17132. module.scrollTo($anchor);
  17133. }, 0);
  17134. }
  17135. module.activate.all(currentPath);
  17136. if( !module.cache.read(currentPath) ) {
  17137. module.cache.add(currentPath, true);
  17138. module.debug('First time tab loaded calling tab init');
  17139. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  17140. }
  17141. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  17142. return false;
  17143. }
  17144. }
  17145. else {
  17146. module.error(error.missingTab, $module, $context, currentPath);
  17147. return false;
  17148. }
  17149. });
  17150. },
  17151. scrollTo: function($element) {
  17152. var
  17153. scrollOffset = ($element && $element.length > 0)
  17154. ? $element.offset().top
  17155. : false
  17156. ;
  17157. if(scrollOffset !== false) {
  17158. module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
  17159. $(document).scrollTop(scrollOffset);
  17160. }
  17161. },
  17162. update: {
  17163. content: function(tabPath, html, evaluateScripts) {
  17164. var
  17165. $tab = module.get.tabElement(tabPath),
  17166. tab = $tab[0]
  17167. ;
  17168. evaluateScripts = (evaluateScripts !== undefined)
  17169. ? evaluateScripts
  17170. : settings.evaluateScripts
  17171. ;
  17172. if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') {
  17173. $tab
  17174. .empty()
  17175. .append($(html).clone(true))
  17176. ;
  17177. }
  17178. else {
  17179. if(evaluateScripts) {
  17180. module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
  17181. $tab.html(html);
  17182. }
  17183. else {
  17184. module.debug('Updating HTML', tabPath, html);
  17185. tab.innerHTML = html;
  17186. }
  17187. }
  17188. }
  17189. },
  17190. fetch: {
  17191. content: function(tabPath, fullTabPath) {
  17192. var
  17193. $tab = module.get.tabElement(tabPath),
  17194. apiSettings = {
  17195. dataType : 'html',
  17196. encodeParameters : false,
  17197. on : 'now',
  17198. cache : settings.alwaysRefresh,
  17199. headers : {
  17200. 'X-Remote': true
  17201. },
  17202. onSuccess : function(response) {
  17203. if(settings.cacheType == 'response') {
  17204. module.cache.add(fullTabPath, response);
  17205. }
  17206. module.update.content(tabPath, response);
  17207. if(tabPath == activeTabPath) {
  17208. module.debug('Content loaded', tabPath);
  17209. module.activate.tab(tabPath);
  17210. }
  17211. else {
  17212. module.debug('Content loaded in background', tabPath);
  17213. }
  17214. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17215. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17216. if(settings.loadOnce) {
  17217. module.cache.add(fullTabPath, true);
  17218. }
  17219. else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) {
  17220. setTimeout(function() {
  17221. var
  17222. $clone = $tab.children().clone(true)
  17223. ;
  17224. $clone = $clone.not('script');
  17225. module.cache.add(fullTabPath, $clone);
  17226. }, 0);
  17227. }
  17228. else {
  17229. module.cache.add(fullTabPath, $tab.html());
  17230. }
  17231. },
  17232. urlData: {
  17233. tab: fullTabPath
  17234. }
  17235. },
  17236. request = $tab.api('get request') || false,
  17237. existingRequest = ( request && request.state() === 'pending' ),
  17238. requestSettings,
  17239. cachedContent
  17240. ;
  17241. fullTabPath = fullTabPath || tabPath;
  17242. cachedContent = module.cache.read(fullTabPath);
  17243. if(settings.cache && cachedContent) {
  17244. module.activate.tab(tabPath);
  17245. module.debug('Adding cached content', fullTabPath);
  17246. if(!settings.loadOnce) {
  17247. if(settings.evaluateScripts == 'once') {
  17248. module.update.content(tabPath, cachedContent, false);
  17249. }
  17250. else {
  17251. module.update.content(tabPath, cachedContent);
  17252. }
  17253. }
  17254. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  17255. }
  17256. else if(existingRequest) {
  17257. module.set.loading(tabPath);
  17258. module.debug('Content is already loading', fullTabPath);
  17259. }
  17260. else if($.api !== undefined) {
  17261. requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
  17262. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  17263. module.set.loading(tabPath);
  17264. $tab.api(requestSettings);
  17265. }
  17266. else {
  17267. module.error(error.api);
  17268. }
  17269. }
  17270. },
  17271. activate: {
  17272. all: function(tabPath) {
  17273. module.activate.tab(tabPath);
  17274. module.activate.navigation(tabPath);
  17275. },
  17276. tab: function(tabPath) {
  17277. var
  17278. $tab = module.get.tabElement(tabPath),
  17279. $deactiveTabs = (settings.deactivate == 'siblings')
  17280. ? $tab.siblings($tabs)
  17281. : $tabs.not($tab),
  17282. isActive = $tab.hasClass(className.active)
  17283. ;
  17284. module.verbose('Showing tab content for', $tab);
  17285. if(!isActive) {
  17286. $tab
  17287. .addClass(className.active)
  17288. ;
  17289. $deactiveTabs
  17290. .removeClass(className.active + ' ' + className.loading)
  17291. ;
  17292. if($tab.length > 0) {
  17293. settings.onVisible.call($tab[0], tabPath);
  17294. }
  17295. }
  17296. },
  17297. navigation: function(tabPath) {
  17298. var
  17299. $navigation = module.get.navElement(tabPath),
  17300. $deactiveNavigation = (settings.deactivate == 'siblings')
  17301. ? $navigation.siblings($allModules)
  17302. : $allModules.not($navigation),
  17303. isActive = $navigation.hasClass(className.active)
  17304. ;
  17305. module.verbose('Activating tab navigation for', $navigation, tabPath);
  17306. if(!isActive) {
  17307. $navigation
  17308. .addClass(className.active)
  17309. ;
  17310. $deactiveNavigation
  17311. .removeClass(className.active + ' ' + className.loading)
  17312. ;
  17313. }
  17314. }
  17315. },
  17316. deactivate: {
  17317. all: function() {
  17318. module.deactivate.navigation();
  17319. module.deactivate.tabs();
  17320. },
  17321. navigation: function() {
  17322. $allModules
  17323. .removeClass(className.active)
  17324. ;
  17325. },
  17326. tabs: function() {
  17327. $tabs
  17328. .removeClass(className.active + ' ' + className.loading)
  17329. ;
  17330. }
  17331. },
  17332. is: {
  17333. tab: function(tabName) {
  17334. return (tabName !== undefined)
  17335. ? ( module.get.tabElement(tabName).length > 0 )
  17336. : false
  17337. ;
  17338. }
  17339. },
  17340. get: {
  17341. initialPath: function() {
  17342. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  17343. },
  17344. path: function() {
  17345. return $.address.value();
  17346. },
  17347. // adds default tabs to tab path
  17348. defaultPathArray: function(tabPath) {
  17349. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  17350. },
  17351. defaultPath: function(tabPath) {
  17352. var
  17353. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0),
  17354. defaultTab = $defaultNav.data(metadata.tab) || false
  17355. ;
  17356. if( defaultTab ) {
  17357. module.debug('Found default tab', defaultTab);
  17358. if(recursionDepth < settings.maxDepth) {
  17359. recursionDepth++;
  17360. return module.get.defaultPath(defaultTab);
  17361. }
  17362. module.error(error.recursion);
  17363. }
  17364. else {
  17365. module.debug('No default tabs found for', tabPath, $tabs);
  17366. }
  17367. recursionDepth = 0;
  17368. return tabPath;
  17369. },
  17370. navElement: function(tabPath) {
  17371. tabPath = tabPath || activeTabPath;
  17372. return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  17373. },
  17374. tabElement: function(tabPath) {
  17375. var
  17376. $fullPathTab,
  17377. $simplePathTab,
  17378. tabPathArray,
  17379. lastTab
  17380. ;
  17381. tabPath = tabPath || activeTabPath;
  17382. tabPathArray = module.utilities.pathToArray(tabPath);
  17383. lastTab = module.utilities.last(tabPathArray);
  17384. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  17385. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]');
  17386. return ($fullPathTab.length > 0)
  17387. ? $fullPathTab
  17388. : $simplePathTab
  17389. ;
  17390. },
  17391. tab: function() {
  17392. return activeTabPath;
  17393. }
  17394. },
  17395. utilities: {
  17396. filterArray: function(keepArray, removeArray) {
  17397. return $.grep(keepArray, function(keepValue) {
  17398. return ( $.inArray(keepValue, removeArray) == -1);
  17399. });
  17400. },
  17401. last: function(array) {
  17402. return $.isArray(array)
  17403. ? array[ array.length - 1]
  17404. : false
  17405. ;
  17406. },
  17407. pathToArray: function(pathName) {
  17408. if(pathName === undefined) {
  17409. pathName = activeTabPath;
  17410. }
  17411. return typeof pathName == 'string'
  17412. ? pathName.split('/')
  17413. : [pathName]
  17414. ;
  17415. },
  17416. arrayToPath: function(pathArray) {
  17417. return $.isArray(pathArray)
  17418. ? pathArray.join('/')
  17419. : false
  17420. ;
  17421. }
  17422. },
  17423. setting: function(name, value) {
  17424. module.debug('Changing setting', name, value);
  17425. if( $.isPlainObject(name) ) {
  17426. $.extend(true, settings, name);
  17427. }
  17428. else if(value !== undefined) {
  17429. if($.isPlainObject(settings[name])) {
  17430. $.extend(true, settings[name], value);
  17431. }
  17432. else {
  17433. settings[name] = value;
  17434. }
  17435. }
  17436. else {
  17437. return settings[name];
  17438. }
  17439. },
  17440. internal: function(name, value) {
  17441. if( $.isPlainObject(name) ) {
  17442. $.extend(true, module, name);
  17443. }
  17444. else if(value !== undefined) {
  17445. module[name] = value;
  17446. }
  17447. else {
  17448. return module[name];
  17449. }
  17450. },
  17451. debug: function() {
  17452. if(!settings.silent && settings.debug) {
  17453. if(settings.performance) {
  17454. module.performance.log(arguments);
  17455. }
  17456. else {
  17457. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17458. module.debug.apply(console, arguments);
  17459. }
  17460. }
  17461. },
  17462. verbose: function() {
  17463. if(!settings.silent && settings.verbose && settings.debug) {
  17464. if(settings.performance) {
  17465. module.performance.log(arguments);
  17466. }
  17467. else {
  17468. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17469. module.verbose.apply(console, arguments);
  17470. }
  17471. }
  17472. },
  17473. error: function() {
  17474. if(!settings.silent) {
  17475. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  17476. module.error.apply(console, arguments);
  17477. }
  17478. },
  17479. performance: {
  17480. log: function(message) {
  17481. var
  17482. currentTime,
  17483. executionTime,
  17484. previousTime
  17485. ;
  17486. if(settings.performance) {
  17487. currentTime = new Date().getTime();
  17488. previousTime = time || currentTime;
  17489. executionTime = currentTime - previousTime;
  17490. time = currentTime;
  17491. performance.push({
  17492. 'Name' : message[0],
  17493. 'Arguments' : [].slice.call(message, 1) || '',
  17494. 'Element' : element,
  17495. 'Execution Time' : executionTime
  17496. });
  17497. }
  17498. clearTimeout(module.performance.timer);
  17499. module.performance.timer = setTimeout(module.performance.display, 500);
  17500. },
  17501. display: function() {
  17502. var
  17503. title = settings.name + ':',
  17504. totalTime = 0
  17505. ;
  17506. time = false;
  17507. clearTimeout(module.performance.timer);
  17508. $.each(performance, function(index, data) {
  17509. totalTime += data['Execution Time'];
  17510. });
  17511. title += ' ' + totalTime + 'ms';
  17512. if(moduleSelector) {
  17513. title += ' \'' + moduleSelector + '\'';
  17514. }
  17515. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  17516. console.groupCollapsed(title);
  17517. if(console.table) {
  17518. console.table(performance);
  17519. }
  17520. else {
  17521. $.each(performance, function(index, data) {
  17522. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  17523. });
  17524. }
  17525. console.groupEnd();
  17526. }
  17527. performance = [];
  17528. }
  17529. },
  17530. invoke: function(query, passedArguments, context) {
  17531. var
  17532. object = instance,
  17533. maxDepth,
  17534. found,
  17535. response
  17536. ;
  17537. passedArguments = passedArguments || queryArguments;
  17538. context = element || context;
  17539. if(typeof query == 'string' && object !== undefined) {
  17540. query = query.split(/[\. ]/);
  17541. maxDepth = query.length - 1;
  17542. $.each(query, function(depth, value) {
  17543. var camelCaseValue = (depth != maxDepth)
  17544. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  17545. : query
  17546. ;
  17547. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  17548. object = object[camelCaseValue];
  17549. }
  17550. else if( object[camelCaseValue] !== undefined ) {
  17551. found = object[camelCaseValue];
  17552. return false;
  17553. }
  17554. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  17555. object = object[value];
  17556. }
  17557. else if( object[value] !== undefined ) {
  17558. found = object[value];
  17559. return false;
  17560. }
  17561. else {
  17562. module.error(error.method, query);
  17563. return false;
  17564. }
  17565. });
  17566. }
  17567. if ( $.isFunction( found ) ) {
  17568. response = found.apply(context, passedArguments);
  17569. }
  17570. else if(found !== undefined) {
  17571. response = found;
  17572. }
  17573. if($.isArray(returnedValue)) {
  17574. returnedValue.push(response);
  17575. }
  17576. else if(returnedValue !== undefined) {
  17577. returnedValue = [returnedValue, response];
  17578. }
  17579. else if(response !== undefined) {
  17580. returnedValue = response;
  17581. }
  17582. return found;
  17583. }
  17584. };
  17585. if(methodInvoked) {
  17586. if(instance === undefined) {
  17587. module.initialize();
  17588. }
  17589. module.invoke(query);
  17590. }
  17591. else {
  17592. if(instance !== undefined) {
  17593. instance.invoke('destroy');
  17594. }
  17595. module.initialize();
  17596. }
  17597. })
  17598. ;
  17599. return (returnedValue !== undefined)
  17600. ? returnedValue
  17601. : this
  17602. ;
  17603. };
  17604. // shortcut for tabbed content with no defined navigation
  17605. $.tab = function() {
  17606. $(window).tab.apply(this, arguments);
  17607. };
  17608. $.fn.tab.settings = {
  17609. name : 'Tab',
  17610. namespace : 'tab',
  17611. silent : false,
  17612. debug : false,
  17613. verbose : false,
  17614. performance : true,
  17615. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  17616. history : false, // use browser history
  17617. historyType : 'hash', // #/ or html5 state
  17618. path : false, // base path of url
  17619. context : false, // specify a context that tabs must appear inside
  17620. childrenOnly : false, // use only tabs that are children of context
  17621. maxDepth : 25, // max depth a tab can be nested
  17622. deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together
  17623. alwaysRefresh : false, // load tab content new every tab click
  17624. cache : true, // cache the content requests to pull locally
  17625. loadOnce : false, // Whether tab data should only be loaded once when using remote content
  17626. cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute
  17627. ignoreFirstLoad : false, // don't load remote content on first load
  17628. apiSettings : false, // settings for api call
  17629. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  17630. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  17631. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  17632. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  17633. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  17634. templates : {
  17635. determineTitle: function(tabArray) {} // returns page title for path
  17636. },
  17637. error: {
  17638. api : 'You attempted to load content without API module',
  17639. method : 'The method you called is not defined',
  17640. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  17641. noContent : 'The tab you specified is missing a content url.',
  17642. path : 'History enabled, but no path was specified',
  17643. recursion : 'Max recursive depth reached',
  17644. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  17645. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  17646. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  17647. },
  17648. metadata : {
  17649. tab : 'tab',
  17650. loaded : 'loaded',
  17651. promise: 'promise'
  17652. },
  17653. className : {
  17654. loading : 'loading',
  17655. active : 'active'
  17656. },
  17657. selector : {
  17658. tabs : '.ui.tab',
  17659. ui : '.ui'
  17660. }
  17661. };
  17662. })( jQuery, window, document );
  17663. /*!
  17664. * # Semantic UI 2.4.1 - Transition
  17665. * http://github.com/semantic-org/semantic-ui/
  17666. *
  17667. *
  17668. * Released under the MIT license
  17669. * http://opensource.org/licenses/MIT
  17670. *
  17671. */
  17672. ;(function ($, window, document, undefined) {
  17673. 'use strict';
  17674. window = (typeof window != 'undefined' && window.Math == Math)
  17675. ? window
  17676. : (typeof self != 'undefined' && self.Math == Math)
  17677. ? self
  17678. : Function('return this')()
  17679. ;
  17680. $.fn.transition = function() {
  17681. var
  17682. $allModules = $(this),
  17683. moduleSelector = $allModules.selector || '',
  17684. time = new Date().getTime(),
  17685. performance = [],
  17686. moduleArguments = arguments,
  17687. query = moduleArguments[0],
  17688. queryArguments = [].slice.call(arguments, 1),
  17689. methodInvoked = (typeof query === 'string'),
  17690. requestAnimationFrame = window.requestAnimationFrame
  17691. || window.mozRequestAnimationFrame
  17692. || window.webkitRequestAnimationFrame
  17693. || window.msRequestAnimationFrame
  17694. || function(callback) { setTimeout(callback, 0); },
  17695. returnedValue
  17696. ;
  17697. $allModules
  17698. .each(function(index) {
  17699. var
  17700. $module = $(this),
  17701. element = this,
  17702. // set at run time
  17703. settings,
  17704. instance,
  17705. error,
  17706. className,
  17707. metadata,
  17708. animationEnd,
  17709. animationName,
  17710. namespace,
  17711. moduleNamespace,
  17712. eventNamespace,
  17713. module
  17714. ;
  17715. module = {
  17716. initialize: function() {
  17717. // get full settings
  17718. settings = module.get.settings.apply(element, moduleArguments);
  17719. // shorthand
  17720. className = settings.className;
  17721. error = settings.error;
  17722. metadata = settings.metadata;
  17723. // define namespace
  17724. eventNamespace = '.' + settings.namespace;
  17725. moduleNamespace = 'module-' + settings.namespace;
  17726. instance = $module.data(moduleNamespace) || module;
  17727. // get vendor specific events
  17728. animationEnd = module.get.animationEndEvent();
  17729. if(methodInvoked) {
  17730. methodInvoked = module.invoke(query);
  17731. }
  17732. // method not invoked, lets run an animation
  17733. if(methodInvoked === false) {
  17734. module.verbose('Converted arguments into settings object', settings);
  17735. if(settings.interval) {
  17736. module.delay(settings.animate);
  17737. }
  17738. else {
  17739. module.animate();
  17740. }
  17741. module.instantiate();
  17742. }
  17743. },
  17744. instantiate: function() {
  17745. module.verbose('Storing instance of module', module);
  17746. instance = module;
  17747. $module
  17748. .data(moduleNamespace, instance)
  17749. ;
  17750. },
  17751. destroy: function() {
  17752. module.verbose('Destroying previous module for', element);
  17753. $module
  17754. .removeData(moduleNamespace)
  17755. ;
  17756. },
  17757. refresh: function() {
  17758. module.verbose('Refreshing display type on next animation');
  17759. delete module.displayType;
  17760. },
  17761. forceRepaint: function() {
  17762. module.verbose('Forcing element repaint');
  17763. var
  17764. $parentElement = $module.parent(),
  17765. $nextElement = $module.next()
  17766. ;
  17767. if($nextElement.length === 0) {
  17768. $module.detach().appendTo($parentElement);
  17769. }
  17770. else {
  17771. $module.detach().insertBefore($nextElement);
  17772. }
  17773. },
  17774. repaint: function() {
  17775. module.verbose('Repainting element');
  17776. var
  17777. fakeAssignment = element.offsetWidth
  17778. ;
  17779. },
  17780. delay: function(interval) {
  17781. var
  17782. direction = module.get.animationDirection(),
  17783. shouldReverse,
  17784. delay
  17785. ;
  17786. if(!direction) {
  17787. direction = module.can.transition()
  17788. ? module.get.direction()
  17789. : 'static'
  17790. ;
  17791. }
  17792. interval = (interval !== undefined)
  17793. ? interval
  17794. : settings.interval
  17795. ;
  17796. shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
  17797. delay = (shouldReverse || settings.reverse == true)
  17798. ? ($allModules.length - index) * settings.interval
  17799. : index * settings.interval
  17800. ;
  17801. module.debug('Delaying animation by', delay);
  17802. setTimeout(module.animate, delay);
  17803. },
  17804. animate: function(overrideSettings) {
  17805. settings = overrideSettings || settings;
  17806. if(!module.is.supported()) {
  17807. module.error(error.support);
  17808. return false;
  17809. }
  17810. module.debug('Preparing animation', settings.animation);
  17811. if(module.is.animating()) {
  17812. if(settings.queue) {
  17813. if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
  17814. module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
  17815. }
  17816. else {
  17817. module.queue(settings.animation);
  17818. }
  17819. return false;
  17820. }
  17821. else if(!settings.allowRepeats && module.is.occurring()) {
  17822. module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
  17823. return false;
  17824. }
  17825. else {
  17826. module.debug('New animation started, completing previous early', settings.animation);
  17827. instance.complete();
  17828. }
  17829. }
  17830. if( module.can.animate() ) {
  17831. module.set.animating(settings.animation);
  17832. }
  17833. else {
  17834. module.error(error.noAnimation, settings.animation, element);
  17835. }
  17836. },
  17837. reset: function() {
  17838. module.debug('Resetting animation to beginning conditions');
  17839. module.remove.animationCallbacks();
  17840. module.restore.conditions();
  17841. module.remove.animating();
  17842. },
  17843. queue: function(animation) {
  17844. module.debug('Queueing animation of', animation);
  17845. module.queuing = true;
  17846. $module
  17847. .one(animationEnd + '.queue' + eventNamespace, function() {
  17848. module.queuing = false;
  17849. module.repaint();
  17850. module.animate.apply(this, settings);
  17851. })
  17852. ;
  17853. },
  17854. complete: function (event) {
  17855. module.debug('Animation complete', settings.animation);
  17856. module.remove.completeCallback();
  17857. module.remove.failSafe();
  17858. if(!module.is.looping()) {
  17859. if( module.is.outward() ) {
  17860. module.verbose('Animation is outward, hiding element');
  17861. module.restore.conditions();
  17862. module.hide();
  17863. }
  17864. else if( module.is.inward() ) {
  17865. module.verbose('Animation is outward, showing element');
  17866. module.restore.conditions();
  17867. module.show();
  17868. }
  17869. else {
  17870. module.verbose('Static animation completed');
  17871. module.restore.conditions();
  17872. settings.onComplete.call(element);
  17873. }
  17874. }
  17875. },
  17876. force: {
  17877. visible: function() {
  17878. var
  17879. style = $module.attr('style'),
  17880. userStyle = module.get.userStyle(),
  17881. displayType = module.get.displayType(),
  17882. overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
  17883. currentDisplay = $module.css('display'),
  17884. emptyStyle = (style === undefined || style === '')
  17885. ;
  17886. if(currentDisplay !== displayType) {
  17887. module.verbose('Overriding default display to show element', displayType);
  17888. $module
  17889. .attr('style', overrideStyle)
  17890. ;
  17891. }
  17892. else if(emptyStyle) {
  17893. $module.removeAttr('style');
  17894. }
  17895. },
  17896. hidden: function() {
  17897. var
  17898. style = $module.attr('style'),
  17899. currentDisplay = $module.css('display'),
  17900. emptyStyle = (style === undefined || style === '')
  17901. ;
  17902. if(currentDisplay !== 'none' && !module.is.hidden()) {
  17903. module.verbose('Overriding default display to hide element');
  17904. $module
  17905. .css('display', 'none')
  17906. ;
  17907. }
  17908. else if(emptyStyle) {
  17909. $module
  17910. .removeAttr('style')
  17911. ;
  17912. }
  17913. }
  17914. },
  17915. has: {
  17916. direction: function(animation) {
  17917. var
  17918. hasDirection = false
  17919. ;
  17920. animation = animation || settings.animation;
  17921. if(typeof animation === 'string') {
  17922. animation = animation.split(' ');
  17923. $.each(animation, function(index, word){
  17924. if(word === className.inward || word === className.outward) {
  17925. hasDirection = true;
  17926. }
  17927. });
  17928. }
  17929. return hasDirection;
  17930. },
  17931. inlineDisplay: function() {
  17932. var
  17933. style = $module.attr('style') || ''
  17934. ;
  17935. return $.isArray(style.match(/display.*?;/, ''));
  17936. }
  17937. },
  17938. set: {
  17939. animating: function(animation) {
  17940. var
  17941. animationClass,
  17942. direction
  17943. ;
  17944. // remove previous callbacks
  17945. module.remove.completeCallback();
  17946. // determine exact animation
  17947. animation = animation || settings.animation;
  17948. animationClass = module.get.animationClass(animation);
  17949. // save animation class in cache to restore class names
  17950. module.save.animation(animationClass);
  17951. // override display if necessary so animation appears visibly
  17952. module.force.visible();
  17953. module.remove.hidden();
  17954. module.remove.direction();
  17955. module.start.animation(animationClass);
  17956. },
  17957. duration: function(animationName, duration) {
  17958. duration = duration || settings.duration;
  17959. duration = (typeof duration == 'number')
  17960. ? duration + 'ms'
  17961. : duration
  17962. ;
  17963. if(duration || duration === 0) {
  17964. module.verbose('Setting animation duration', duration);
  17965. $module
  17966. .css({
  17967. 'animation-duration': duration
  17968. })
  17969. ;
  17970. }
  17971. },
  17972. direction: function(direction) {
  17973. direction = direction || module.get.direction();
  17974. if(direction == className.inward) {
  17975. module.set.inward();
  17976. }
  17977. else {
  17978. module.set.outward();
  17979. }
  17980. },
  17981. looping: function() {
  17982. module.debug('Transition set to loop');
  17983. $module
  17984. .addClass(className.looping)
  17985. ;
  17986. },
  17987. hidden: function() {
  17988. $module
  17989. .addClass(className.transition)
  17990. .addClass(className.hidden)
  17991. ;
  17992. },
  17993. inward: function() {
  17994. module.debug('Setting direction to inward');
  17995. $module
  17996. .removeClass(className.outward)
  17997. .addClass(className.inward)
  17998. ;
  17999. },
  18000. outward: function() {
  18001. module.debug('Setting direction to outward');
  18002. $module
  18003. .removeClass(className.inward)
  18004. .addClass(className.outward)
  18005. ;
  18006. },
  18007. visible: function() {
  18008. $module
  18009. .addClass(className.transition)
  18010. .addClass(className.visible)
  18011. ;
  18012. }
  18013. },
  18014. start: {
  18015. animation: function(animationClass) {
  18016. animationClass = animationClass || module.get.animationClass();
  18017. module.debug('Starting tween', animationClass);
  18018. $module
  18019. .addClass(animationClass)
  18020. .one(animationEnd + '.complete' + eventNamespace, module.complete)
  18021. ;
  18022. if(settings.useFailSafe) {
  18023. module.add.failSafe();
  18024. }
  18025. module.set.duration(settings.duration);
  18026. settings.onStart.call(element);
  18027. }
  18028. },
  18029. save: {
  18030. animation: function(animation) {
  18031. if(!module.cache) {
  18032. module.cache = {};
  18033. }
  18034. module.cache.animation = animation;
  18035. },
  18036. displayType: function(displayType) {
  18037. if(displayType !== 'none') {
  18038. $module.data(metadata.displayType, displayType);
  18039. }
  18040. },
  18041. transitionExists: function(animation, exists) {
  18042. $.fn.transition.exists[animation] = exists;
  18043. module.verbose('Saving existence of transition', animation, exists);
  18044. }
  18045. },
  18046. restore: {
  18047. conditions: function() {
  18048. var
  18049. animation = module.get.currentAnimation()
  18050. ;
  18051. if(animation) {
  18052. $module
  18053. .removeClass(animation)
  18054. ;
  18055. module.verbose('Removing animation class', module.cache);
  18056. }
  18057. module.remove.duration();
  18058. }
  18059. },
  18060. add: {
  18061. failSafe: function() {
  18062. var
  18063. duration = module.get.duration()
  18064. ;
  18065. module.timer = setTimeout(function() {
  18066. $module.triggerHandler(animationEnd);
  18067. }, duration + settings.failSafeDelay);
  18068. module.verbose('Adding fail safe timer', module.timer);
  18069. }
  18070. },
  18071. remove: {
  18072. animating: function() {
  18073. $module.removeClass(className.animating);
  18074. },
  18075. animationCallbacks: function() {
  18076. module.remove.queueCallback();
  18077. module.remove.completeCallback();
  18078. },
  18079. queueCallback: function() {
  18080. $module.off('.queue' + eventNamespace);
  18081. },
  18082. completeCallback: function() {
  18083. $module.off('.complete' + eventNamespace);
  18084. },
  18085. display: function() {
  18086. $module.css('display', '');
  18087. },
  18088. direction: function() {
  18089. $module
  18090. .removeClass(className.inward)
  18091. .removeClass(className.outward)
  18092. ;
  18093. },
  18094. duration: function() {
  18095. $module
  18096. .css('animation-duration', '')
  18097. ;
  18098. },
  18099. failSafe: function() {
  18100. module.verbose('Removing fail safe timer', module.timer);
  18101. if(module.timer) {
  18102. clearTimeout(module.timer);
  18103. }
  18104. },
  18105. hidden: function() {
  18106. $module.removeClass(className.hidden);
  18107. },
  18108. visible: function() {
  18109. $module.removeClass(className.visible);
  18110. },
  18111. looping: function() {
  18112. module.debug('Transitions are no longer looping');
  18113. if( module.is.looping() ) {
  18114. module.reset();
  18115. $module
  18116. .removeClass(className.looping)
  18117. ;
  18118. }
  18119. },
  18120. transition: function() {
  18121. $module
  18122. .removeClass(className.visible)
  18123. .removeClass(className.hidden)
  18124. ;
  18125. }
  18126. },
  18127. get: {
  18128. settings: function(animation, duration, onComplete) {
  18129. // single settings object
  18130. if(typeof animation == 'object') {
  18131. return $.extend(true, {}, $.fn.transition.settings, animation);
  18132. }
  18133. // all arguments provided
  18134. else if(typeof onComplete == 'function') {
  18135. return $.extend({}, $.fn.transition.settings, {
  18136. animation : animation,
  18137. onComplete : onComplete,
  18138. duration : duration
  18139. });
  18140. }
  18141. // only duration provided
  18142. else if(typeof duration == 'string' || typeof duration == 'number') {
  18143. return $.extend({}, $.fn.transition.settings, {
  18144. animation : animation,
  18145. duration : duration
  18146. });
  18147. }
  18148. // duration is actually settings object
  18149. else if(typeof duration == 'object') {
  18150. return $.extend({}, $.fn.transition.settings, duration, {
  18151. animation : animation
  18152. });
  18153. }
  18154. // duration is actually callback
  18155. else if(typeof duration == 'function') {
  18156. return $.extend({}, $.fn.transition.settings, {
  18157. animation : animation,
  18158. onComplete : duration
  18159. });
  18160. }
  18161. // only animation provided
  18162. else {
  18163. return $.extend({}, $.fn.transition.settings, {
  18164. animation : animation
  18165. });
  18166. }
  18167. },
  18168. animationClass: function(animation) {
  18169. var
  18170. animationClass = animation || settings.animation,
  18171. directionClass = (module.can.transition() && !module.has.direction())
  18172. ? module.get.direction() + ' '
  18173. : ''
  18174. ;
  18175. return className.animating + ' '
  18176. + className.transition + ' '
  18177. + directionClass
  18178. + animationClass
  18179. ;
  18180. },
  18181. currentAnimation: function() {
  18182. return (module.cache && module.cache.animation !== undefined)
  18183. ? module.cache.animation
  18184. : false
  18185. ;
  18186. },
  18187. currentDirection: function() {
  18188. return module.is.inward()
  18189. ? className.inward
  18190. : className.outward
  18191. ;
  18192. },
  18193. direction: function() {
  18194. return module.is.hidden() || !module.is.visible()
  18195. ? className.inward
  18196. : className.outward
  18197. ;
  18198. },
  18199. animationDirection: function(animation) {
  18200. var
  18201. direction
  18202. ;
  18203. animation = animation || settings.animation;
  18204. if(typeof animation === 'string') {
  18205. animation = animation.split(' ');
  18206. // search animation name for out/in class
  18207. $.each(animation, function(index, word){
  18208. if(word === className.inward) {
  18209. direction = className.inward;
  18210. }
  18211. else if(word === className.outward) {
  18212. direction = className.outward;
  18213. }
  18214. });
  18215. }
  18216. // return found direction
  18217. if(direction) {
  18218. return direction;
  18219. }
  18220. return false;
  18221. },
  18222. duration: function(duration) {
  18223. duration = duration || settings.duration;
  18224. if(duration === false) {
  18225. duration = $module.css('animation-duration') || 0;
  18226. }
  18227. return (typeof duration === 'string')
  18228. ? (duration.indexOf('ms') > -1)
  18229. ? parseFloat(duration)
  18230. : parseFloat(duration) * 1000
  18231. : duration
  18232. ;
  18233. },
  18234. displayType: function(shouldDetermine) {
  18235. shouldDetermine = (shouldDetermine !== undefined)
  18236. ? shouldDetermine
  18237. : true
  18238. ;
  18239. if(settings.displayType) {
  18240. return settings.displayType;
  18241. }
  18242. if(shouldDetermine && $module.data(metadata.displayType) === undefined) {
  18243. // create fake element to determine display state
  18244. module.can.transition(true);
  18245. }
  18246. return $module.data(metadata.displayType);
  18247. },
  18248. userStyle: function(style) {
  18249. style = style || $module.attr('style') || '';
  18250. return style.replace(/display.*?;/, '');
  18251. },
  18252. transitionExists: function(animation) {
  18253. return $.fn.transition.exists[animation];
  18254. },
  18255. animationStartEvent: function() {
  18256. var
  18257. element = document.createElement('div'),
  18258. animations = {
  18259. 'animation' :'animationstart',
  18260. 'OAnimation' :'oAnimationStart',
  18261. 'MozAnimation' :'mozAnimationStart',
  18262. 'WebkitAnimation' :'webkitAnimationStart'
  18263. },
  18264. animation
  18265. ;
  18266. for(animation in animations){
  18267. if( element.style[animation] !== undefined ){
  18268. return animations[animation];
  18269. }
  18270. }
  18271. return false;
  18272. },
  18273. animationEndEvent: function() {
  18274. var
  18275. element = document.createElement('div'),
  18276. animations = {
  18277. 'animation' :'animationend',
  18278. 'OAnimation' :'oAnimationEnd',
  18279. 'MozAnimation' :'mozAnimationEnd',
  18280. 'WebkitAnimation' :'webkitAnimationEnd'
  18281. },
  18282. animation
  18283. ;
  18284. for(animation in animations){
  18285. if( element.style[animation] !== undefined ){
  18286. return animations[animation];
  18287. }
  18288. }
  18289. return false;
  18290. }
  18291. },
  18292. can: {
  18293. transition: function(forced) {
  18294. var
  18295. animation = settings.animation,
  18296. transitionExists = module.get.transitionExists(animation),
  18297. displayType = module.get.displayType(false),
  18298. elementClass,
  18299. tagName,
  18300. $clone,
  18301. currentAnimation,
  18302. inAnimation,
  18303. directionExists
  18304. ;
  18305. if( transitionExists === undefined || forced) {
  18306. module.verbose('Determining whether animation exists');
  18307. elementClass = $module.attr('class');
  18308. tagName = $module.prop('tagName');
  18309. $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
  18310. currentAnimation = $clone
  18311. .addClass(animation)
  18312. .removeClass(className.inward)
  18313. .removeClass(className.outward)
  18314. .addClass(className.animating)
  18315. .addClass(className.transition)
  18316. .css('animationName')
  18317. ;
  18318. inAnimation = $clone
  18319. .addClass(className.inward)
  18320. .css('animationName')
  18321. ;
  18322. if(!displayType) {
  18323. displayType = $clone
  18324. .attr('class', elementClass)
  18325. .removeAttr('style')
  18326. .removeClass(className.hidden)
  18327. .removeClass(className.visible)
  18328. .show()
  18329. .css('display')
  18330. ;
  18331. module.verbose('Determining final display state', displayType);
  18332. module.save.displayType(displayType);
  18333. }
  18334. $clone.remove();
  18335. if(currentAnimation != inAnimation) {
  18336. module.debug('Direction exists for animation', animation);
  18337. directionExists = true;
  18338. }
  18339. else if(currentAnimation == 'none' || !currentAnimation) {
  18340. module.debug('No animation defined in css', animation);
  18341. return;
  18342. }
  18343. else {
  18344. module.debug('Static animation found', animation, displayType);
  18345. directionExists = false;
  18346. }
  18347. module.save.transitionExists(animation, directionExists);
  18348. }
  18349. return (transitionExists !== undefined)
  18350. ? transitionExists
  18351. : directionExists
  18352. ;
  18353. },
  18354. animate: function() {
  18355. // can transition does not return a value if animation does not exist
  18356. return (module.can.transition() !== undefined);
  18357. }
  18358. },
  18359. is: {
  18360. animating: function() {
  18361. return $module.hasClass(className.animating);
  18362. },
  18363. inward: function() {
  18364. return $module.hasClass(className.inward);
  18365. },
  18366. outward: function() {
  18367. return $module.hasClass(className.outward);
  18368. },
  18369. looping: function() {
  18370. return $module.hasClass(className.looping);
  18371. },
  18372. occurring: function(animation) {
  18373. animation = animation || settings.animation;
  18374. animation = '.' + animation.replace(' ', '.');
  18375. return ( $module.filter(animation).length > 0 );
  18376. },
  18377. visible: function() {
  18378. return $module.is(':visible');
  18379. },
  18380. hidden: function() {
  18381. return $module.css('visibility') === 'hidden';
  18382. },
  18383. supported: function() {
  18384. return(animationEnd !== false);
  18385. }
  18386. },
  18387. hide: function() {
  18388. module.verbose('Hiding element');
  18389. if( module.is.animating() ) {
  18390. module.reset();
  18391. }
  18392. element.blur(); // IE will trigger focus change if element is not blurred before hiding
  18393. module.remove.display();
  18394. module.remove.visible();
  18395. module.set.hidden();
  18396. module.force.hidden();
  18397. settings.onHide.call(element);
  18398. settings.onComplete.call(element);
  18399. // module.repaint();
  18400. },
  18401. show: function(display) {
  18402. module.verbose('Showing element', display);
  18403. module.remove.hidden();
  18404. module.set.visible();
  18405. module.force.visible();
  18406. settings.onShow.call(element);
  18407. settings.onComplete.call(element);
  18408. // module.repaint();
  18409. },
  18410. toggle: function() {
  18411. if( module.is.visible() ) {
  18412. module.hide();
  18413. }
  18414. else {
  18415. module.show();
  18416. }
  18417. },
  18418. stop: function() {
  18419. module.debug('Stopping current animation');
  18420. $module.triggerHandler(animationEnd);
  18421. },
  18422. stopAll: function() {
  18423. module.debug('Stopping all animation');
  18424. module.remove.queueCallback();
  18425. $module.triggerHandler(animationEnd);
  18426. },
  18427. clear: {
  18428. queue: function() {
  18429. module.debug('Clearing animation queue');
  18430. module.remove.queueCallback();
  18431. }
  18432. },
  18433. enable: function() {
  18434. module.verbose('Starting animation');
  18435. $module.removeClass(className.disabled);
  18436. },
  18437. disable: function() {
  18438. module.debug('Stopping animation');
  18439. $module.addClass(className.disabled);
  18440. },
  18441. setting: function(name, value) {
  18442. module.debug('Changing setting', name, value);
  18443. if( $.isPlainObject(name) ) {
  18444. $.extend(true, settings, name);
  18445. }
  18446. else if(value !== undefined) {
  18447. if($.isPlainObject(settings[name])) {
  18448. $.extend(true, settings[name], value);
  18449. }
  18450. else {
  18451. settings[name] = value;
  18452. }
  18453. }
  18454. else {
  18455. return settings[name];
  18456. }
  18457. },
  18458. internal: function(name, value) {
  18459. if( $.isPlainObject(name) ) {
  18460. $.extend(true, module, name);
  18461. }
  18462. else if(value !== undefined) {
  18463. module[name] = value;
  18464. }
  18465. else {
  18466. return module[name];
  18467. }
  18468. },
  18469. debug: function() {
  18470. if(!settings.silent && settings.debug) {
  18471. if(settings.performance) {
  18472. module.performance.log(arguments);
  18473. }
  18474. else {
  18475. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18476. module.debug.apply(console, arguments);
  18477. }
  18478. }
  18479. },
  18480. verbose: function() {
  18481. if(!settings.silent && settings.verbose && settings.debug) {
  18482. if(settings.performance) {
  18483. module.performance.log(arguments);
  18484. }
  18485. else {
  18486. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18487. module.verbose.apply(console, arguments);
  18488. }
  18489. }
  18490. },
  18491. error: function() {
  18492. if(!settings.silent) {
  18493. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  18494. module.error.apply(console, arguments);
  18495. }
  18496. },
  18497. performance: {
  18498. log: function(message) {
  18499. var
  18500. currentTime,
  18501. executionTime,
  18502. previousTime
  18503. ;
  18504. if(settings.performance) {
  18505. currentTime = new Date().getTime();
  18506. previousTime = time || currentTime;
  18507. executionTime = currentTime - previousTime;
  18508. time = currentTime;
  18509. performance.push({
  18510. 'Name' : message[0],
  18511. 'Arguments' : [].slice.call(message, 1) || '',
  18512. 'Element' : element,
  18513. 'Execution Time' : executionTime
  18514. });
  18515. }
  18516. clearTimeout(module.performance.timer);
  18517. module.performance.timer = setTimeout(module.performance.display, 500);
  18518. },
  18519. display: function() {
  18520. var
  18521. title = settings.name + ':',
  18522. totalTime = 0
  18523. ;
  18524. time = false;
  18525. clearTimeout(module.performance.timer);
  18526. $.each(performance, function(index, data) {
  18527. totalTime += data['Execution Time'];
  18528. });
  18529. title += ' ' + totalTime + 'ms';
  18530. if(moduleSelector) {
  18531. title += ' \'' + moduleSelector + '\'';
  18532. }
  18533. if($allModules.length > 1) {
  18534. title += ' ' + '(' + $allModules.length + ')';
  18535. }
  18536. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  18537. console.groupCollapsed(title);
  18538. if(console.table) {
  18539. console.table(performance);
  18540. }
  18541. else {
  18542. $.each(performance, function(index, data) {
  18543. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  18544. });
  18545. }
  18546. console.groupEnd();
  18547. }
  18548. performance = [];
  18549. }
  18550. },
  18551. // modified for transition to return invoke success
  18552. invoke: function(query, passedArguments, context) {
  18553. var
  18554. object = instance,
  18555. maxDepth,
  18556. found,
  18557. response
  18558. ;
  18559. passedArguments = passedArguments || queryArguments;
  18560. context = element || context;
  18561. if(typeof query == 'string' && object !== undefined) {
  18562. query = query.split(/[\. ]/);
  18563. maxDepth = query.length - 1;
  18564. $.each(query, function(depth, value) {
  18565. var camelCaseValue = (depth != maxDepth)
  18566. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  18567. : query
  18568. ;
  18569. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  18570. object = object[camelCaseValue];
  18571. }
  18572. else if( object[camelCaseValue] !== undefined ) {
  18573. found = object[camelCaseValue];
  18574. return false;
  18575. }
  18576. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  18577. object = object[value];
  18578. }
  18579. else if( object[value] !== undefined ) {
  18580. found = object[value];
  18581. return false;
  18582. }
  18583. else {
  18584. return false;
  18585. }
  18586. });
  18587. }
  18588. if ( $.isFunction( found ) ) {
  18589. response = found.apply(context, passedArguments);
  18590. }
  18591. else if(found !== undefined) {
  18592. response = found;
  18593. }
  18594. if($.isArray(returnedValue)) {
  18595. returnedValue.push(response);
  18596. }
  18597. else if(returnedValue !== undefined) {
  18598. returnedValue = [returnedValue, response];
  18599. }
  18600. else if(response !== undefined) {
  18601. returnedValue = response;
  18602. }
  18603. return (found !== undefined)
  18604. ? found
  18605. : false
  18606. ;
  18607. }
  18608. };
  18609. module.initialize();
  18610. })
  18611. ;
  18612. return (returnedValue !== undefined)
  18613. ? returnedValue
  18614. : this
  18615. ;
  18616. };
  18617. // Records if CSS transition is available
  18618. $.fn.transition.exists = {};
  18619. $.fn.transition.settings = {
  18620. // module info
  18621. name : 'Transition',
  18622. // hide all output from this component regardless of other settings
  18623. silent : false,
  18624. // debug content outputted to console
  18625. debug : false,
  18626. // verbose debug output
  18627. verbose : false,
  18628. // performance data output
  18629. performance : true,
  18630. // event namespace
  18631. namespace : 'transition',
  18632. // delay between animations in group
  18633. interval : 0,
  18634. // whether group animations should be reversed
  18635. reverse : 'auto',
  18636. // animation callback event
  18637. onStart : function() {},
  18638. onComplete : function() {},
  18639. onShow : function() {},
  18640. onHide : function() {},
  18641. // whether timeout should be used to ensure callback fires in cases animationend does not
  18642. useFailSafe : true,
  18643. // delay in ms for fail safe
  18644. failSafeDelay : 100,
  18645. // whether EXACT animation can occur twice in a row
  18646. allowRepeats : false,
  18647. // Override final display type on visible
  18648. displayType : false,
  18649. // animation duration
  18650. animation : 'fade',
  18651. duration : false,
  18652. // new animations will occur after previous ones
  18653. queue : true,
  18654. metadata : {
  18655. displayType: 'display'
  18656. },
  18657. className : {
  18658. animating : 'animating',
  18659. disabled : 'disabled',
  18660. hidden : 'hidden',
  18661. inward : 'in',
  18662. loading : 'loading',
  18663. looping : 'looping',
  18664. outward : 'out',
  18665. transition : 'transition',
  18666. visible : 'visible'
  18667. },
  18668. // possible errors
  18669. error: {
  18670. noAnimation : 'Element is no longer attached to DOM. Unable to animate. Use silent setting to surpress this warning in production.',
  18671. repeated : 'That animation is already occurring, cancelling repeated animation',
  18672. method : 'The method you called is not defined',
  18673. support : 'This browser does not support CSS animations'
  18674. }
  18675. };
  18676. })( jQuery, window, document );
  18677. /*!
  18678. * # Semantic UI 2.4.1 - API
  18679. * http://github.com/semantic-org/semantic-ui/
  18680. *
  18681. *
  18682. * Released under the MIT license
  18683. * http://opensource.org/licenses/MIT
  18684. *
  18685. */
  18686. ;(function ($, window, document, undefined) {
  18687. 'use strict';
  18688. var
  18689. window = (typeof window != 'undefined' && window.Math == Math)
  18690. ? window
  18691. : (typeof self != 'undefined' && self.Math == Math)
  18692. ? self
  18693. : Function('return this')()
  18694. ;
  18695. $.api = $.fn.api = function(parameters) {
  18696. var
  18697. // use window context if none specified
  18698. $allModules = $.isFunction(this)
  18699. ? $(window)
  18700. : $(this),
  18701. moduleSelector = $allModules.selector || '',
  18702. time = new Date().getTime(),
  18703. performance = [],
  18704. query = arguments[0],
  18705. methodInvoked = (typeof query == 'string'),
  18706. queryArguments = [].slice.call(arguments, 1),
  18707. returnedValue
  18708. ;
  18709. $allModules
  18710. .each(function() {
  18711. var
  18712. settings = ( $.isPlainObject(parameters) )
  18713. ? $.extend(true, {}, $.fn.api.settings, parameters)
  18714. : $.extend({}, $.fn.api.settings),
  18715. // internal aliases
  18716. namespace = settings.namespace,
  18717. metadata = settings.metadata,
  18718. selector = settings.selector,
  18719. error = settings.error,
  18720. className = settings.className,
  18721. // define namespaces for modules
  18722. eventNamespace = '.' + namespace,
  18723. moduleNamespace = 'module-' + namespace,
  18724. // element that creates request
  18725. $module = $(this),
  18726. $form = $module.closest(selector.form),
  18727. // context used for state
  18728. $context = (settings.stateContext)
  18729. ? $(settings.stateContext)
  18730. : $module,
  18731. // request details
  18732. ajaxSettings,
  18733. requestSettings,
  18734. url,
  18735. data,
  18736. requestStartTime,
  18737. // standard module
  18738. element = this,
  18739. context = $context[0],
  18740. instance = $module.data(moduleNamespace),
  18741. module
  18742. ;
  18743. module = {
  18744. initialize: function() {
  18745. if(!methodInvoked) {
  18746. module.bind.events();
  18747. }
  18748. module.instantiate();
  18749. },
  18750. instantiate: function() {
  18751. module.verbose('Storing instance of module', module);
  18752. instance = module;
  18753. $module
  18754. .data(moduleNamespace, instance)
  18755. ;
  18756. },
  18757. destroy: function() {
  18758. module.verbose('Destroying previous module for', element);
  18759. $module
  18760. .removeData(moduleNamespace)
  18761. .off(eventNamespace)
  18762. ;
  18763. },
  18764. bind: {
  18765. events: function() {
  18766. var
  18767. triggerEvent = module.get.event()
  18768. ;
  18769. if( triggerEvent ) {
  18770. module.verbose('Attaching API events to element', triggerEvent);
  18771. $module
  18772. .on(triggerEvent + eventNamespace, module.event.trigger)
  18773. ;
  18774. }
  18775. else if(settings.on == 'now') {
  18776. module.debug('Querying API endpoint immediately');
  18777. module.query();
  18778. }
  18779. }
  18780. },
  18781. decode: {
  18782. json: function(response) {
  18783. if(response !== undefined && typeof response == 'string') {
  18784. try {
  18785. response = JSON.parse(response);
  18786. }
  18787. catch(e) {
  18788. // isnt json string
  18789. }
  18790. }
  18791. return response;
  18792. }
  18793. },
  18794. read: {
  18795. cachedResponse: function(url) {
  18796. var
  18797. response
  18798. ;
  18799. if(window.Storage === undefined) {
  18800. module.error(error.noStorage);
  18801. return;
  18802. }
  18803. response = sessionStorage.getItem(url);
  18804. module.debug('Using cached response', url, response);
  18805. response = module.decode.json(response);
  18806. return response;
  18807. }
  18808. },
  18809. write: {
  18810. cachedResponse: function(url, response) {
  18811. if(response && response === '') {
  18812. module.debug('Response empty, not caching', response);
  18813. return;
  18814. }
  18815. if(window.Storage === undefined) {
  18816. module.error(error.noStorage);
  18817. return;
  18818. }
  18819. if( $.isPlainObject(response) ) {
  18820. response = JSON.stringify(response);
  18821. }
  18822. sessionStorage.setItem(url, response);
  18823. module.verbose('Storing cached response for url', url, response);
  18824. }
  18825. },
  18826. query: function() {
  18827. if(module.is.disabled()) {
  18828. module.debug('Element is disabled API request aborted');
  18829. return;
  18830. }
  18831. if(module.is.loading()) {
  18832. if(settings.interruptRequests) {
  18833. module.debug('Interrupting previous request');
  18834. module.abort();
  18835. }
  18836. else {
  18837. module.debug('Cancelling request, previous request is still pending');
  18838. return;
  18839. }
  18840. }
  18841. // pass element metadata to url (value, text)
  18842. if(settings.defaultData) {
  18843. $.extend(true, settings.urlData, module.get.defaultData());
  18844. }
  18845. // Add form content
  18846. if(settings.serializeForm) {
  18847. settings.data = module.add.formData(settings.data);
  18848. }
  18849. // call beforesend and get any settings changes
  18850. requestSettings = module.get.settings();
  18851. // check if before send cancelled request
  18852. if(requestSettings === false) {
  18853. module.cancelled = true;
  18854. module.error(error.beforeSend);
  18855. return;
  18856. }
  18857. else {
  18858. module.cancelled = false;
  18859. }
  18860. // get url
  18861. url = module.get.templatedURL();
  18862. if(!url && !module.is.mocked()) {
  18863. module.error(error.missingURL);
  18864. return;
  18865. }
  18866. // replace variables
  18867. url = module.add.urlData( url );
  18868. // missing url parameters
  18869. if( !url && !module.is.mocked()) {
  18870. return;
  18871. }
  18872. requestSettings.url = settings.base + url;
  18873. // look for jQuery ajax parameters in settings
  18874. ajaxSettings = $.extend(true, {}, settings, {
  18875. type : settings.method || settings.type,
  18876. data : data,
  18877. url : settings.base + url,
  18878. beforeSend : settings.beforeXHR,
  18879. success : function() {},
  18880. failure : function() {},
  18881. complete : function() {}
  18882. });
  18883. module.debug('Querying URL', ajaxSettings.url);
  18884. module.verbose('Using AJAX settings', ajaxSettings);
  18885. if(settings.cache === 'local' && module.read.cachedResponse(url)) {
  18886. module.debug('Response returned from local cache');
  18887. module.request = module.create.request();
  18888. module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
  18889. return;
  18890. }
  18891. if( !settings.throttle ) {
  18892. module.debug('Sending request', data, ajaxSettings.method);
  18893. module.send.request();
  18894. }
  18895. else {
  18896. if(!settings.throttleFirstRequest && !module.timer) {
  18897. module.debug('Sending request', data, ajaxSettings.method);
  18898. module.send.request();
  18899. module.timer = setTimeout(function(){}, settings.throttle);
  18900. }
  18901. else {
  18902. module.debug('Throttling request', settings.throttle);
  18903. clearTimeout(module.timer);
  18904. module.timer = setTimeout(function() {
  18905. if(module.timer) {
  18906. delete module.timer;
  18907. }
  18908. module.debug('Sending throttled request', data, ajaxSettings.method);
  18909. module.send.request();
  18910. }, settings.throttle);
  18911. }
  18912. }
  18913. },
  18914. should: {
  18915. removeError: function() {
  18916. return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
  18917. }
  18918. },
  18919. is: {
  18920. disabled: function() {
  18921. return ($module.filter(selector.disabled).length > 0);
  18922. },
  18923. expectingJSON: function() {
  18924. return settings.dataType === 'json' || settings.dataType === 'jsonp';
  18925. },
  18926. form: function() {
  18927. return $module.is('form') || $context.is('form');
  18928. },
  18929. mocked: function() {
  18930. return (settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync);
  18931. },
  18932. input: function() {
  18933. return $module.is('input');
  18934. },
  18935. loading: function() {
  18936. return (module.request)
  18937. ? (module.request.state() == 'pending')
  18938. : false
  18939. ;
  18940. },
  18941. abortedRequest: function(xhr) {
  18942. if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
  18943. module.verbose('XHR request determined to be aborted');
  18944. return true;
  18945. }
  18946. else {
  18947. module.verbose('XHR request was not aborted');
  18948. return false;
  18949. }
  18950. },
  18951. validResponse: function(response) {
  18952. if( (!module.is.expectingJSON()) || !$.isFunction(settings.successTest) ) {
  18953. module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
  18954. return true;
  18955. }
  18956. module.debug('Checking JSON returned success', settings.successTest, response);
  18957. if( settings.successTest(response) ) {
  18958. module.debug('Response passed success test', response);
  18959. return true;
  18960. }
  18961. else {
  18962. module.debug('Response failed success test', response);
  18963. return false;
  18964. }
  18965. }
  18966. },
  18967. was: {
  18968. cancelled: function() {
  18969. return (module.cancelled || false);
  18970. },
  18971. succesful: function() {
  18972. return (module.request && module.request.state() == 'resolved');
  18973. },
  18974. failure: function() {
  18975. return (module.request && module.request.state() == 'rejected');
  18976. },
  18977. complete: function() {
  18978. return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
  18979. }
  18980. },
  18981. add: {
  18982. urlData: function(url, urlData) {
  18983. var
  18984. requiredVariables,
  18985. optionalVariables
  18986. ;
  18987. if(url) {
  18988. requiredVariables = url.match(settings.regExp.required);
  18989. optionalVariables = url.match(settings.regExp.optional);
  18990. urlData = urlData || settings.urlData;
  18991. if(requiredVariables) {
  18992. module.debug('Looking for required URL variables', requiredVariables);
  18993. $.each(requiredVariables, function(index, templatedString) {
  18994. var
  18995. // allow legacy {$var} style
  18996. variable = (templatedString.indexOf('$') !== -1)
  18997. ? templatedString.substr(2, templatedString.length - 3)
  18998. : templatedString.substr(1, templatedString.length - 2),
  18999. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  19000. ? urlData[variable]
  19001. : ($module.data(variable) !== undefined)
  19002. ? $module.data(variable)
  19003. : ($context.data(variable) !== undefined)
  19004. ? $context.data(variable)
  19005. : urlData[variable]
  19006. ;
  19007. // remove value
  19008. if(value === undefined) {
  19009. module.error(error.requiredParameter, variable, url);
  19010. url = false;
  19011. return false;
  19012. }
  19013. else {
  19014. module.verbose('Found required variable', variable, value);
  19015. value = (settings.encodeParameters)
  19016. ? module.get.urlEncodedValue(value)
  19017. : value
  19018. ;
  19019. url = url.replace(templatedString, value);
  19020. }
  19021. });
  19022. }
  19023. if(optionalVariables) {
  19024. module.debug('Looking for optional URL variables', requiredVariables);
  19025. $.each(optionalVariables, function(index, templatedString) {
  19026. var
  19027. // allow legacy {/$var} style
  19028. variable = (templatedString.indexOf('$') !== -1)
  19029. ? templatedString.substr(3, templatedString.length - 4)
  19030. : templatedString.substr(2, templatedString.length - 3),
  19031. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  19032. ? urlData[variable]
  19033. : ($module.data(variable) !== undefined)
  19034. ? $module.data(variable)
  19035. : ($context.data(variable) !== undefined)
  19036. ? $context.data(variable)
  19037. : urlData[variable]
  19038. ;
  19039. // optional replacement
  19040. if(value !== undefined) {
  19041. module.verbose('Optional variable Found', variable, value);
  19042. url = url.replace(templatedString, value);
  19043. }
  19044. else {
  19045. module.verbose('Optional variable not found', variable);
  19046. // remove preceding slash if set
  19047. if(url.indexOf('/' + templatedString) !== -1) {
  19048. url = url.replace('/' + templatedString, '');
  19049. }
  19050. else {
  19051. url = url.replace(templatedString, '');
  19052. }
  19053. }
  19054. });
  19055. }
  19056. }
  19057. return url;
  19058. },
  19059. formData: function(data) {
  19060. var
  19061. canSerialize = ($.fn.serializeObject !== undefined),
  19062. formData = (canSerialize)
  19063. ? $form.serializeObject()
  19064. : $form.serialize(),
  19065. hasOtherData
  19066. ;
  19067. data = data || settings.data;
  19068. hasOtherData = $.isPlainObject(data);
  19069. if(hasOtherData) {
  19070. if(canSerialize) {
  19071. module.debug('Extending existing data with form data', data, formData);
  19072. data = $.extend(true, {}, data, formData);
  19073. }
  19074. else {
  19075. module.error(error.missingSerialize);
  19076. module.debug('Cant extend data. Replacing data with form data', data, formData);
  19077. data = formData;
  19078. }
  19079. }
  19080. else {
  19081. module.debug('Adding form data', formData);
  19082. data = formData;
  19083. }
  19084. return data;
  19085. }
  19086. },
  19087. send: {
  19088. request: function() {
  19089. module.set.loading();
  19090. module.request = module.create.request();
  19091. if( module.is.mocked() ) {
  19092. module.mockedXHR = module.create.mockedXHR();
  19093. }
  19094. else {
  19095. module.xhr = module.create.xhr();
  19096. }
  19097. settings.onRequest.call(context, module.request, module.xhr);
  19098. }
  19099. },
  19100. event: {
  19101. trigger: function(event) {
  19102. module.query();
  19103. if(event.type == 'submit' || event.type == 'click') {
  19104. event.preventDefault();
  19105. }
  19106. },
  19107. xhr: {
  19108. always: function() {
  19109. // nothing special
  19110. },
  19111. done: function(response, textStatus, xhr) {
  19112. var
  19113. context = this,
  19114. elapsedTime = (new Date().getTime() - requestStartTime),
  19115. timeLeft = (settings.loadingDuration - elapsedTime),
  19116. translatedResponse = ( $.isFunction(settings.onResponse) )
  19117. ? module.is.expectingJSON()
  19118. ? settings.onResponse.call(context, $.extend(true, {}, response))
  19119. : settings.onResponse.call(context, response)
  19120. : false
  19121. ;
  19122. timeLeft = (timeLeft > 0)
  19123. ? timeLeft
  19124. : 0
  19125. ;
  19126. if(translatedResponse) {
  19127. module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
  19128. response = translatedResponse;
  19129. }
  19130. if(timeLeft > 0) {
  19131. module.debug('Response completed early delaying state change by', timeLeft);
  19132. }
  19133. setTimeout(function() {
  19134. if( module.is.validResponse(response) ) {
  19135. module.request.resolveWith(context, [response, xhr]);
  19136. }
  19137. else {
  19138. module.request.rejectWith(context, [xhr, 'invalid']);
  19139. }
  19140. }, timeLeft);
  19141. },
  19142. fail: function(xhr, status, httpMessage) {
  19143. var
  19144. context = this,
  19145. elapsedTime = (new Date().getTime() - requestStartTime),
  19146. timeLeft = (settings.loadingDuration - elapsedTime)
  19147. ;
  19148. timeLeft = (timeLeft > 0)
  19149. ? timeLeft
  19150. : 0
  19151. ;
  19152. if(timeLeft > 0) {
  19153. module.debug('Response completed early delaying state change by', timeLeft);
  19154. }
  19155. setTimeout(function() {
  19156. if( module.is.abortedRequest(xhr) ) {
  19157. module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
  19158. }
  19159. else {
  19160. module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
  19161. }
  19162. }, timeLeft);
  19163. }
  19164. },
  19165. request: {
  19166. done: function(response, xhr) {
  19167. module.debug('Successful API Response', response);
  19168. if(settings.cache === 'local' && url) {
  19169. module.write.cachedResponse(url, response);
  19170. module.debug('Saving server response locally', module.cache);
  19171. }
  19172. settings.onSuccess.call(context, response, $module, xhr);
  19173. },
  19174. complete: function(firstParameter, secondParameter) {
  19175. var
  19176. xhr,
  19177. response
  19178. ;
  19179. // have to guess callback parameters based on request success
  19180. if( module.was.succesful() ) {
  19181. response = firstParameter;
  19182. xhr = secondParameter;
  19183. }
  19184. else {
  19185. xhr = firstParameter;
  19186. response = module.get.responseFromXHR(xhr);
  19187. }
  19188. module.remove.loading();
  19189. settings.onComplete.call(context, response, $module, xhr);
  19190. },
  19191. fail: function(xhr, status, httpMessage) {
  19192. var
  19193. // pull response from xhr if available
  19194. response = module.get.responseFromXHR(xhr),
  19195. errorMessage = module.get.errorFromRequest(response, status, httpMessage)
  19196. ;
  19197. if(status == 'aborted') {
  19198. module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
  19199. settings.onAbort.call(context, status, $module, xhr);
  19200. return true;
  19201. }
  19202. else if(status == 'invalid') {
  19203. module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
  19204. }
  19205. else if(status == 'error') {
  19206. if(xhr !== undefined) {
  19207. module.debug('XHR produced a server error', status, httpMessage);
  19208. // make sure we have an error to display to console
  19209. if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
  19210. module.error(error.statusMessage + httpMessage, ajaxSettings.url);
  19211. }
  19212. settings.onError.call(context, errorMessage, $module, xhr);
  19213. }
  19214. }
  19215. if(settings.errorDuration && status !== 'aborted') {
  19216. module.debug('Adding error state');
  19217. module.set.error();
  19218. if( module.should.removeError() ) {
  19219. setTimeout(module.remove.error, settings.errorDuration);
  19220. }
  19221. }
  19222. module.debug('API Request failed', errorMessage, xhr);
  19223. settings.onFailure.call(context, response, $module, xhr);
  19224. }
  19225. }
  19226. },
  19227. create: {
  19228. request: function() {
  19229. // api request promise
  19230. return $.Deferred()
  19231. .always(module.event.request.complete)
  19232. .done(module.event.request.done)
  19233. .fail(module.event.request.fail)
  19234. ;
  19235. },
  19236. mockedXHR: function () {
  19237. var
  19238. // xhr does not simulate these properties of xhr but must return them
  19239. textStatus = false,
  19240. status = false,
  19241. httpMessage = false,
  19242. responder = settings.mockResponse || settings.response,
  19243. asyncResponder = settings.mockResponseAsync || settings.responseAsync,
  19244. asyncCallback,
  19245. response,
  19246. mockedXHR
  19247. ;
  19248. mockedXHR = $.Deferred()
  19249. .always(module.event.xhr.complete)
  19250. .done(module.event.xhr.done)
  19251. .fail(module.event.xhr.fail)
  19252. ;
  19253. if(responder) {
  19254. if( $.isFunction(responder) ) {
  19255. module.debug('Using specified synchronous callback', responder);
  19256. response = responder.call(context, requestSettings);
  19257. }
  19258. else {
  19259. module.debug('Using settings specified response', responder);
  19260. response = responder;
  19261. }
  19262. // simulating response
  19263. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  19264. }
  19265. else if( $.isFunction(asyncResponder) ) {
  19266. asyncCallback = function(response) {
  19267. module.debug('Async callback returned response', response);
  19268. if(response) {
  19269. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  19270. }
  19271. else {
  19272. mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
  19273. }
  19274. };
  19275. module.debug('Using specified async response callback', asyncResponder);
  19276. asyncResponder.call(context, requestSettings, asyncCallback);
  19277. }
  19278. return mockedXHR;
  19279. },
  19280. xhr: function() {
  19281. var
  19282. xhr
  19283. ;
  19284. // ajax request promise
  19285. xhr = $.ajax(ajaxSettings)
  19286. .always(module.event.xhr.always)
  19287. .done(module.event.xhr.done)
  19288. .fail(module.event.xhr.fail)
  19289. ;
  19290. module.verbose('Created server request', xhr, ajaxSettings);
  19291. return xhr;
  19292. }
  19293. },
  19294. set: {
  19295. error: function() {
  19296. module.verbose('Adding error state to element', $context);
  19297. $context.addClass(className.error);
  19298. },
  19299. loading: function() {
  19300. module.verbose('Adding loading state to element', $context);
  19301. $context.addClass(className.loading);
  19302. requestStartTime = new Date().getTime();
  19303. }
  19304. },
  19305. remove: {
  19306. error: function() {
  19307. module.verbose('Removing error state from element', $context);
  19308. $context.removeClass(className.error);
  19309. },
  19310. loading: function() {
  19311. module.verbose('Removing loading state from element', $context);
  19312. $context.removeClass(className.loading);
  19313. }
  19314. },
  19315. get: {
  19316. responseFromXHR: function(xhr) {
  19317. return $.isPlainObject(xhr)
  19318. ? (module.is.expectingJSON())
  19319. ? module.decode.json(xhr.responseText)
  19320. : xhr.responseText
  19321. : false
  19322. ;
  19323. },
  19324. errorFromRequest: function(response, status, httpMessage) {
  19325. return ($.isPlainObject(response) && response.error !== undefined)
  19326. ? response.error // use json error message
  19327. : (settings.error[status] !== undefined) // use server error message
  19328. ? settings.error[status]
  19329. : httpMessage
  19330. ;
  19331. },
  19332. request: function() {
  19333. return module.request || false;
  19334. },
  19335. xhr: function() {
  19336. return module.xhr || false;
  19337. },
  19338. settings: function() {
  19339. var
  19340. runSettings
  19341. ;
  19342. runSettings = settings.beforeSend.call(context, settings);
  19343. if(runSettings) {
  19344. if(runSettings.success !== undefined) {
  19345. module.debug('Legacy success callback detected', runSettings);
  19346. module.error(error.legacyParameters, runSettings.success);
  19347. runSettings.onSuccess = runSettings.success;
  19348. }
  19349. if(runSettings.failure !== undefined) {
  19350. module.debug('Legacy failure callback detected', runSettings);
  19351. module.error(error.legacyParameters, runSettings.failure);
  19352. runSettings.onFailure = runSettings.failure;
  19353. }
  19354. if(runSettings.complete !== undefined) {
  19355. module.debug('Legacy complete callback detected', runSettings);
  19356. module.error(error.legacyParameters, runSettings.complete);
  19357. runSettings.onComplete = runSettings.complete;
  19358. }
  19359. }
  19360. if(runSettings === undefined) {
  19361. module.error(error.noReturnedValue);
  19362. }
  19363. if(runSettings === false) {
  19364. return runSettings;
  19365. }
  19366. return (runSettings !== undefined)
  19367. ? $.extend(true, {}, runSettings)
  19368. : $.extend(true, {}, settings)
  19369. ;
  19370. },
  19371. urlEncodedValue: function(value) {
  19372. var
  19373. decodedValue = window.decodeURIComponent(value),
  19374. encodedValue = window.encodeURIComponent(value),
  19375. alreadyEncoded = (decodedValue !== value)
  19376. ;
  19377. if(alreadyEncoded) {
  19378. module.debug('URL value is already encoded, avoiding double encoding', value);
  19379. return value;
  19380. }
  19381. module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
  19382. return encodedValue;
  19383. },
  19384. defaultData: function() {
  19385. var
  19386. data = {}
  19387. ;
  19388. if( !$.isWindow(element) ) {
  19389. if( module.is.input() ) {
  19390. data.value = $module.val();
  19391. }
  19392. else if( module.is.form() ) {
  19393. }
  19394. else {
  19395. data.text = $module.text();
  19396. }
  19397. }
  19398. return data;
  19399. },
  19400. event: function() {
  19401. if( $.isWindow(element) || settings.on == 'now' ) {
  19402. module.debug('API called without element, no events attached');
  19403. return false;
  19404. }
  19405. else if(settings.on == 'auto') {
  19406. if( $module.is('input') ) {
  19407. return (element.oninput !== undefined)
  19408. ? 'input'
  19409. : (element.onpropertychange !== undefined)
  19410. ? 'propertychange'
  19411. : 'keyup'
  19412. ;
  19413. }
  19414. else if( $module.is('form') ) {
  19415. return 'submit';
  19416. }
  19417. else {
  19418. return 'click';
  19419. }
  19420. }
  19421. else {
  19422. return settings.on;
  19423. }
  19424. },
  19425. templatedURL: function(action) {
  19426. action = action || $module.data(metadata.action) || settings.action || false;
  19427. url = $module.data(metadata.url) || settings.url || false;
  19428. if(url) {
  19429. module.debug('Using specified url', url);
  19430. return url;
  19431. }
  19432. if(action) {
  19433. module.debug('Looking up url for action', action, settings.api);
  19434. if(settings.api[action] === undefined && !module.is.mocked()) {
  19435. module.error(error.missingAction, settings.action, settings.api);
  19436. return;
  19437. }
  19438. url = settings.api[action];
  19439. }
  19440. else if( module.is.form() ) {
  19441. url = $module.attr('action') || $context.attr('action') || false;
  19442. module.debug('No url or action specified, defaulting to form action', url);
  19443. }
  19444. return url;
  19445. }
  19446. },
  19447. abort: function() {
  19448. var
  19449. xhr = module.get.xhr()
  19450. ;
  19451. if( xhr && xhr.state() !== 'resolved') {
  19452. module.debug('Cancelling API request');
  19453. xhr.abort();
  19454. }
  19455. },
  19456. // reset state
  19457. reset: function() {
  19458. module.remove.error();
  19459. module.remove.loading();
  19460. },
  19461. setting: function(name, value) {
  19462. module.debug('Changing setting', name, value);
  19463. if( $.isPlainObject(name) ) {
  19464. $.extend(true, settings, name);
  19465. }
  19466. else if(value !== undefined) {
  19467. if($.isPlainObject(settings[name])) {
  19468. $.extend(true, settings[name], value);
  19469. }
  19470. else {
  19471. settings[name] = value;
  19472. }
  19473. }
  19474. else {
  19475. return settings[name];
  19476. }
  19477. },
  19478. internal: function(name, value) {
  19479. if( $.isPlainObject(name) ) {
  19480. $.extend(true, module, name);
  19481. }
  19482. else if(value !== undefined) {
  19483. module[name] = value;
  19484. }
  19485. else {
  19486. return module[name];
  19487. }
  19488. },
  19489. debug: function() {
  19490. if(!settings.silent && settings.debug) {
  19491. if(settings.performance) {
  19492. module.performance.log(arguments);
  19493. }
  19494. else {
  19495. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19496. module.debug.apply(console, arguments);
  19497. }
  19498. }
  19499. },
  19500. verbose: function() {
  19501. if(!settings.silent && settings.verbose && settings.debug) {
  19502. if(settings.performance) {
  19503. module.performance.log(arguments);
  19504. }
  19505. else {
  19506. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19507. module.verbose.apply(console, arguments);
  19508. }
  19509. }
  19510. },
  19511. error: function() {
  19512. if(!settings.silent) {
  19513. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  19514. module.error.apply(console, arguments);
  19515. }
  19516. },
  19517. performance: {
  19518. log: function(message) {
  19519. var
  19520. currentTime,
  19521. executionTime,
  19522. previousTime
  19523. ;
  19524. if(settings.performance) {
  19525. currentTime = new Date().getTime();
  19526. previousTime = time || currentTime;
  19527. executionTime = currentTime - previousTime;
  19528. time = currentTime;
  19529. performance.push({
  19530. 'Name' : message[0],
  19531. 'Arguments' : [].slice.call(message, 1) || '',
  19532. //'Element' : element,
  19533. 'Execution Time' : executionTime
  19534. });
  19535. }
  19536. clearTimeout(module.performance.timer);
  19537. module.performance.timer = setTimeout(module.performance.display, 500);
  19538. },
  19539. display: function() {
  19540. var
  19541. title = settings.name + ':',
  19542. totalTime = 0
  19543. ;
  19544. time = false;
  19545. clearTimeout(module.performance.timer);
  19546. $.each(performance, function(index, data) {
  19547. totalTime += data['Execution Time'];
  19548. });
  19549. title += ' ' + totalTime + 'ms';
  19550. if(moduleSelector) {
  19551. title += ' \'' + moduleSelector + '\'';
  19552. }
  19553. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  19554. console.groupCollapsed(title);
  19555. if(console.table) {
  19556. console.table(performance);
  19557. }
  19558. else {
  19559. $.each(performance, function(index, data) {
  19560. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  19561. });
  19562. }
  19563. console.groupEnd();
  19564. }
  19565. performance = [];
  19566. }
  19567. },
  19568. invoke: function(query, passedArguments, context) {
  19569. var
  19570. object = instance,
  19571. maxDepth,
  19572. found,
  19573. response
  19574. ;
  19575. passedArguments = passedArguments || queryArguments;
  19576. context = element || context;
  19577. if(typeof query == 'string' && object !== undefined) {
  19578. query = query.split(/[\. ]/);
  19579. maxDepth = query.length - 1;
  19580. $.each(query, function(depth, value) {
  19581. var camelCaseValue = (depth != maxDepth)
  19582. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  19583. : query
  19584. ;
  19585. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  19586. object = object[camelCaseValue];
  19587. }
  19588. else if( object[camelCaseValue] !== undefined ) {
  19589. found = object[camelCaseValue];
  19590. return false;
  19591. }
  19592. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  19593. object = object[value];
  19594. }
  19595. else if( object[value] !== undefined ) {
  19596. found = object[value];
  19597. return false;
  19598. }
  19599. else {
  19600. module.error(error.method, query);
  19601. return false;
  19602. }
  19603. });
  19604. }
  19605. if ( $.isFunction( found ) ) {
  19606. response = found.apply(context, passedArguments);
  19607. }
  19608. else if(found !== undefined) {
  19609. response = found;
  19610. }
  19611. if($.isArray(returnedValue)) {
  19612. returnedValue.push(response);
  19613. }
  19614. else if(returnedValue !== undefined) {
  19615. returnedValue = [returnedValue, response];
  19616. }
  19617. else if(response !== undefined) {
  19618. returnedValue = response;
  19619. }
  19620. return found;
  19621. }
  19622. };
  19623. if(methodInvoked) {
  19624. if(instance === undefined) {
  19625. module.initialize();
  19626. }
  19627. module.invoke(query);
  19628. }
  19629. else {
  19630. if(instance !== undefined) {
  19631. instance.invoke('destroy');
  19632. }
  19633. module.initialize();
  19634. }
  19635. })
  19636. ;
  19637. return (returnedValue !== undefined)
  19638. ? returnedValue
  19639. : this
  19640. ;
  19641. };
  19642. $.api.settings = {
  19643. name : 'API',
  19644. namespace : 'api',
  19645. debug : false,
  19646. verbose : false,
  19647. performance : true,
  19648. // object containing all templates endpoints
  19649. api : {},
  19650. // whether to cache responses
  19651. cache : true,
  19652. // whether new requests should abort previous requests
  19653. interruptRequests : true,
  19654. // event binding
  19655. on : 'auto',
  19656. // context for applying state classes
  19657. stateContext : false,
  19658. // duration for loading state
  19659. loadingDuration : 0,
  19660. // whether to hide errors after a period of time
  19661. hideError : 'auto',
  19662. // duration for error state
  19663. errorDuration : 2000,
  19664. // whether parameters should be encoded with encodeURIComponent
  19665. encodeParameters : true,
  19666. // API action to use
  19667. action : false,
  19668. // templated URL to use
  19669. url : false,
  19670. // base URL to apply to all endpoints
  19671. base : '',
  19672. // data that will
  19673. urlData : {},
  19674. // whether to add default data to url data
  19675. defaultData : true,
  19676. // whether to serialize closest form
  19677. serializeForm : false,
  19678. // how long to wait before request should occur
  19679. throttle : 0,
  19680. // whether to throttle first request or only repeated
  19681. throttleFirstRequest : true,
  19682. // standard ajax settings
  19683. method : 'get',
  19684. data : {},
  19685. dataType : 'json',
  19686. // mock response
  19687. mockResponse : false,
  19688. mockResponseAsync : false,
  19689. // aliases for mock
  19690. response : false,
  19691. responseAsync : false,
  19692. // callbacks before request
  19693. beforeSend : function(settings) { return settings; },
  19694. beforeXHR : function(xhr) {},
  19695. onRequest : function(promise, xhr) {},
  19696. // after request
  19697. onResponse : false, // function(response) { },
  19698. // response was successful, if JSON passed validation
  19699. onSuccess : function(response, $module) {},
  19700. // request finished without aborting
  19701. onComplete : function(response, $module) {},
  19702. // failed JSON success test
  19703. onFailure : function(response, $module) {},
  19704. // server error
  19705. onError : function(errorMessage, $module) {},
  19706. // request aborted
  19707. onAbort : function(errorMessage, $module) {},
  19708. successTest : false,
  19709. // errors
  19710. error : {
  19711. beforeSend : 'The before send function has aborted the request',
  19712. error : 'There was an error with your request',
  19713. exitConditions : 'API Request Aborted. Exit conditions met',
  19714. JSONParse : 'JSON could not be parsed during error handling',
  19715. legacyParameters : 'You are using legacy API success callback names',
  19716. method : 'The method you called is not defined',
  19717. missingAction : 'API action used but no url was defined',
  19718. missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
  19719. missingURL : 'No URL specified for api event',
  19720. noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
  19721. noStorage : 'Caching responses locally requires session storage',
  19722. parseError : 'There was an error parsing your request',
  19723. requiredParameter : 'Missing a required URL parameter: ',
  19724. statusMessage : 'Server gave an error: ',
  19725. timeout : 'Your request timed out'
  19726. },
  19727. regExp : {
  19728. required : /\{\$*[A-z0-9]+\}/g,
  19729. optional : /\{\/\$*[A-z0-9]+\}/g,
  19730. },
  19731. className: {
  19732. loading : 'loading',
  19733. error : 'error'
  19734. },
  19735. selector: {
  19736. disabled : '.disabled',
  19737. form : 'form'
  19738. },
  19739. metadata: {
  19740. action : 'action',
  19741. url : 'url'
  19742. }
  19743. };
  19744. })( jQuery, window, document );
  19745. /*!
  19746. * # Semantic UI 2.4.1 - Visibility
  19747. * http://github.com/semantic-org/semantic-ui/
  19748. *
  19749. *
  19750. * Released under the MIT license
  19751. * http://opensource.org/licenses/MIT
  19752. *
  19753. */
  19754. ;(function ($, window, document, undefined) {
  19755. 'use strict';
  19756. window = (typeof window != 'undefined' && window.Math == Math)
  19757. ? window
  19758. : (typeof self != 'undefined' && self.Math == Math)
  19759. ? self
  19760. : Function('return this')()
  19761. ;
  19762. $.fn.visibility = function(parameters) {
  19763. var
  19764. $allModules = $(this),
  19765. moduleSelector = $allModules.selector || '',
  19766. time = new Date().getTime(),
  19767. performance = [],
  19768. query = arguments[0],
  19769. methodInvoked = (typeof query == 'string'),
  19770. queryArguments = [].slice.call(arguments, 1),
  19771. returnedValue,
  19772. moduleCount = $allModules.length,
  19773. loadedCount = 0
  19774. ;
  19775. $allModules
  19776. .each(function() {
  19777. var
  19778. settings = ( $.isPlainObject(parameters) )
  19779. ? $.extend(true, {}, $.fn.visibility.settings, parameters)
  19780. : $.extend({}, $.fn.visibility.settings),
  19781. className = settings.className,
  19782. namespace = settings.namespace,
  19783. error = settings.error,
  19784. metadata = settings.metadata,
  19785. eventNamespace = '.' + namespace,
  19786. moduleNamespace = 'module-' + namespace,
  19787. $window = $(window),
  19788. $module = $(this),
  19789. $context = $(settings.context),
  19790. $placeholder,
  19791. selector = $module.selector || '',
  19792. instance = $module.data(moduleNamespace),
  19793. requestAnimationFrame = window.requestAnimationFrame
  19794. || window.mozRequestAnimationFrame
  19795. || window.webkitRequestAnimationFrame
  19796. || window.msRequestAnimationFrame
  19797. || function(callback) { setTimeout(callback, 0); },
  19798. element = this,
  19799. disabled = false,
  19800. contextObserver,
  19801. observer,
  19802. module
  19803. ;
  19804. module = {
  19805. initialize: function() {
  19806. module.debug('Initializing', settings);
  19807. module.setup.cache();
  19808. if( module.should.trackChanges() ) {
  19809. if(settings.type == 'image') {
  19810. module.setup.image();
  19811. }
  19812. if(settings.type == 'fixed') {
  19813. module.setup.fixed();
  19814. }
  19815. if(settings.observeChanges) {
  19816. module.observeChanges();
  19817. }
  19818. module.bind.events();
  19819. }
  19820. module.save.position();
  19821. if( !module.is.visible() ) {
  19822. module.error(error.visible, $module);
  19823. }
  19824. if(settings.initialCheck) {
  19825. module.checkVisibility();
  19826. }
  19827. module.instantiate();
  19828. },
  19829. instantiate: function() {
  19830. module.debug('Storing instance', module);
  19831. $module
  19832. .data(moduleNamespace, module)
  19833. ;
  19834. instance = module;
  19835. },
  19836. destroy: function() {
  19837. module.verbose('Destroying previous module');
  19838. if(observer) {
  19839. observer.disconnect();
  19840. }
  19841. if(contextObserver) {
  19842. contextObserver.disconnect();
  19843. }
  19844. $window
  19845. .off('load' + eventNamespace, module.event.load)
  19846. .off('resize' + eventNamespace, module.event.resize)
  19847. ;
  19848. $context
  19849. .off('scroll' + eventNamespace, module.event.scroll)
  19850. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  19851. ;
  19852. if(settings.type == 'fixed') {
  19853. module.resetFixed();
  19854. module.remove.placeholder();
  19855. }
  19856. $module
  19857. .off(eventNamespace)
  19858. .removeData(moduleNamespace)
  19859. ;
  19860. },
  19861. observeChanges: function() {
  19862. if('MutationObserver' in window) {
  19863. contextObserver = new MutationObserver(module.event.contextChanged);
  19864. observer = new MutationObserver(module.event.changed);
  19865. contextObserver.observe(document, {
  19866. childList : true,
  19867. subtree : true
  19868. });
  19869. observer.observe(element, {
  19870. childList : true,
  19871. subtree : true
  19872. });
  19873. module.debug('Setting up mutation observer', observer);
  19874. }
  19875. },
  19876. bind: {
  19877. events: function() {
  19878. module.verbose('Binding visibility events to scroll and resize');
  19879. if(settings.refreshOnLoad) {
  19880. $window
  19881. .on('load' + eventNamespace, module.event.load)
  19882. ;
  19883. }
  19884. $window
  19885. .on('resize' + eventNamespace, module.event.resize)
  19886. ;
  19887. // pub/sub pattern
  19888. $context
  19889. .off('scroll' + eventNamespace)
  19890. .on('scroll' + eventNamespace, module.event.scroll)
  19891. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  19892. ;
  19893. }
  19894. },
  19895. event: {
  19896. changed: function(mutations) {
  19897. module.verbose('DOM tree modified, updating visibility calculations');
  19898. module.timer = setTimeout(function() {
  19899. module.verbose('DOM tree modified, updating sticky menu');
  19900. module.refresh();
  19901. }, 100);
  19902. },
  19903. contextChanged: function(mutations) {
  19904. [].forEach.call(mutations, function(mutation) {
  19905. if(mutation.removedNodes) {
  19906. [].forEach.call(mutation.removedNodes, function(node) {
  19907. if(node == element || $(node).find(element).length > 0) {
  19908. module.debug('Element removed from DOM, tearing down events');
  19909. module.destroy();
  19910. }
  19911. });
  19912. }
  19913. });
  19914. },
  19915. resize: function() {
  19916. module.debug('Window resized');
  19917. if(settings.refreshOnResize) {
  19918. requestAnimationFrame(module.refresh);
  19919. }
  19920. },
  19921. load: function() {
  19922. module.debug('Page finished loading');
  19923. requestAnimationFrame(module.refresh);
  19924. },
  19925. // publishes scrollchange event on one scroll
  19926. scroll: function() {
  19927. if(settings.throttle) {
  19928. clearTimeout(module.timer);
  19929. module.timer = setTimeout(function() {
  19930. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  19931. }, settings.throttle);
  19932. }
  19933. else {
  19934. requestAnimationFrame(function() {
  19935. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  19936. });
  19937. }
  19938. },
  19939. // subscribes to scrollchange
  19940. scrollchange: function(event, scrollPosition) {
  19941. module.checkVisibility(scrollPosition);
  19942. },
  19943. },
  19944. precache: function(images, callback) {
  19945. if (!(images instanceof Array)) {
  19946. images = [images];
  19947. }
  19948. var
  19949. imagesLength = images.length,
  19950. loadedCounter = 0,
  19951. cache = [],
  19952. cacheImage = document.createElement('img'),
  19953. handleLoad = function() {
  19954. loadedCounter++;
  19955. if (loadedCounter >= images.length) {
  19956. if ($.isFunction(callback)) {
  19957. callback();
  19958. }
  19959. }
  19960. }
  19961. ;
  19962. while (imagesLength--) {
  19963. cacheImage = document.createElement('img');
  19964. cacheImage.onload = handleLoad;
  19965. cacheImage.onerror = handleLoad;
  19966. cacheImage.src = images[imagesLength];
  19967. cache.push(cacheImage);
  19968. }
  19969. },
  19970. enableCallbacks: function() {
  19971. module.debug('Allowing callbacks to occur');
  19972. disabled = false;
  19973. },
  19974. disableCallbacks: function() {
  19975. module.debug('Disabling all callbacks temporarily');
  19976. disabled = true;
  19977. },
  19978. should: {
  19979. trackChanges: function() {
  19980. if(methodInvoked) {
  19981. module.debug('One time query, no need to bind events');
  19982. return false;
  19983. }
  19984. module.debug('Callbacks being attached');
  19985. return true;
  19986. }
  19987. },
  19988. setup: {
  19989. cache: function() {
  19990. module.cache = {
  19991. occurred : {},
  19992. screen : {},
  19993. element : {},
  19994. };
  19995. },
  19996. image: function() {
  19997. var
  19998. src = $module.data(metadata.src)
  19999. ;
  20000. if(src) {
  20001. module.verbose('Lazy loading image', src);
  20002. settings.once = true;
  20003. settings.observeChanges = false;
  20004. // show when top visible
  20005. settings.onOnScreen = function() {
  20006. module.debug('Image on screen', element);
  20007. module.precache(src, function() {
  20008. module.set.image(src, function() {
  20009. loadedCount++;
  20010. if(loadedCount == moduleCount) {
  20011. settings.onAllLoaded.call(this);
  20012. }
  20013. settings.onLoad.call(this);
  20014. });
  20015. });
  20016. };
  20017. }
  20018. },
  20019. fixed: function() {
  20020. module.debug('Setting up fixed');
  20021. settings.once = false;
  20022. settings.observeChanges = false;
  20023. settings.initialCheck = true;
  20024. settings.refreshOnLoad = true;
  20025. if(!parameters.transition) {
  20026. settings.transition = false;
  20027. }
  20028. module.create.placeholder();
  20029. module.debug('Added placeholder', $placeholder);
  20030. settings.onTopPassed = function() {
  20031. module.debug('Element passed, adding fixed position', $module);
  20032. module.show.placeholder();
  20033. module.set.fixed();
  20034. if(settings.transition) {
  20035. if($.fn.transition !== undefined) {
  20036. $module.transition(settings.transition, settings.duration);
  20037. }
  20038. }
  20039. };
  20040. settings.onTopPassedReverse = function() {
  20041. module.debug('Element returned to position, removing fixed', $module);
  20042. module.hide.placeholder();
  20043. module.remove.fixed();
  20044. };
  20045. }
  20046. },
  20047. create: {
  20048. placeholder: function() {
  20049. module.verbose('Creating fixed position placeholder');
  20050. $placeholder = $module
  20051. .clone(false)
  20052. .css('display', 'none')
  20053. .addClass(className.placeholder)
  20054. .insertAfter($module)
  20055. ;
  20056. }
  20057. },
  20058. show: {
  20059. placeholder: function() {
  20060. module.verbose('Showing placeholder');
  20061. $placeholder
  20062. .css('display', 'block')
  20063. .css('visibility', 'hidden')
  20064. ;
  20065. }
  20066. },
  20067. hide: {
  20068. placeholder: function() {
  20069. module.verbose('Hiding placeholder');
  20070. $placeholder
  20071. .css('display', 'none')
  20072. .css('visibility', '')
  20073. ;
  20074. }
  20075. },
  20076. set: {
  20077. fixed: function() {
  20078. module.verbose('Setting element to fixed position');
  20079. $module
  20080. .addClass(className.fixed)
  20081. .css({
  20082. position : 'fixed',
  20083. top : settings.offset + 'px',
  20084. left : 'auto',
  20085. zIndex : settings.zIndex
  20086. })
  20087. ;
  20088. settings.onFixed.call(element);
  20089. },
  20090. image: function(src, callback) {
  20091. $module
  20092. .attr('src', src)
  20093. ;
  20094. if(settings.transition) {
  20095. if( $.fn.transition !== undefined) {
  20096. if($module.hasClass(className.visible)) {
  20097. module.debug('Transition already occurred on this image, skipping animation');
  20098. return;
  20099. }
  20100. $module.transition(settings.transition, settings.duration, callback);
  20101. }
  20102. else {
  20103. $module.fadeIn(settings.duration, callback);
  20104. }
  20105. }
  20106. else {
  20107. $module.show();
  20108. }
  20109. }
  20110. },
  20111. is: {
  20112. onScreen: function() {
  20113. var
  20114. calculations = module.get.elementCalculations()
  20115. ;
  20116. return calculations.onScreen;
  20117. },
  20118. offScreen: function() {
  20119. var
  20120. calculations = module.get.elementCalculations()
  20121. ;
  20122. return calculations.offScreen;
  20123. },
  20124. visible: function() {
  20125. if(module.cache && module.cache.element) {
  20126. return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
  20127. }
  20128. return false;
  20129. },
  20130. verticallyScrollableContext: function() {
  20131. var
  20132. overflowY = ($context.get(0) !== window)
  20133. ? $context.css('overflow-y')
  20134. : false
  20135. ;
  20136. return (overflowY == 'auto' || overflowY == 'scroll');
  20137. },
  20138. horizontallyScrollableContext: function() {
  20139. var
  20140. overflowX = ($context.get(0) !== window)
  20141. ? $context.css('overflow-x')
  20142. : false
  20143. ;
  20144. return (overflowX == 'auto' || overflowX == 'scroll');
  20145. }
  20146. },
  20147. refresh: function() {
  20148. module.debug('Refreshing constants (width/height)');
  20149. if(settings.type == 'fixed') {
  20150. module.resetFixed();
  20151. }
  20152. module.reset();
  20153. module.save.position();
  20154. if(settings.checkOnRefresh) {
  20155. module.checkVisibility();
  20156. }
  20157. settings.onRefresh.call(element);
  20158. },
  20159. resetFixed: function () {
  20160. module.remove.fixed();
  20161. module.remove.occurred();
  20162. },
  20163. reset: function() {
  20164. module.verbose('Resetting all cached values');
  20165. if( $.isPlainObject(module.cache) ) {
  20166. module.cache.screen = {};
  20167. module.cache.element = {};
  20168. }
  20169. },
  20170. checkVisibility: function(scroll) {
  20171. module.verbose('Checking visibility of element', module.cache.element);
  20172. if( !disabled && module.is.visible() ) {
  20173. // save scroll position
  20174. module.save.scroll(scroll);
  20175. // update calculations derived from scroll
  20176. module.save.calculations();
  20177. // percentage
  20178. module.passed();
  20179. // reverse (must be first)
  20180. module.passingReverse();
  20181. module.topVisibleReverse();
  20182. module.bottomVisibleReverse();
  20183. module.topPassedReverse();
  20184. module.bottomPassedReverse();
  20185. // one time
  20186. module.onScreen();
  20187. module.offScreen();
  20188. module.passing();
  20189. module.topVisible();
  20190. module.bottomVisible();
  20191. module.topPassed();
  20192. module.bottomPassed();
  20193. // on update callback
  20194. if(settings.onUpdate) {
  20195. settings.onUpdate.call(element, module.get.elementCalculations());
  20196. }
  20197. }
  20198. },
  20199. passed: function(amount, newCallback) {
  20200. var
  20201. calculations = module.get.elementCalculations(),
  20202. amountInPixels
  20203. ;
  20204. // assign callback
  20205. if(amount && newCallback) {
  20206. settings.onPassed[amount] = newCallback;
  20207. }
  20208. else if(amount !== undefined) {
  20209. return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
  20210. }
  20211. else if(calculations.passing) {
  20212. $.each(settings.onPassed, function(amount, callback) {
  20213. if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
  20214. module.execute(callback, amount);
  20215. }
  20216. else if(!settings.once) {
  20217. module.remove.occurred(callback);
  20218. }
  20219. });
  20220. }
  20221. },
  20222. onScreen: function(newCallback) {
  20223. var
  20224. calculations = module.get.elementCalculations(),
  20225. callback = newCallback || settings.onOnScreen,
  20226. callbackName = 'onScreen'
  20227. ;
  20228. if(newCallback) {
  20229. module.debug('Adding callback for onScreen', newCallback);
  20230. settings.onOnScreen = newCallback;
  20231. }
  20232. if(calculations.onScreen) {
  20233. module.execute(callback, callbackName);
  20234. }
  20235. else if(!settings.once) {
  20236. module.remove.occurred(callbackName);
  20237. }
  20238. if(newCallback !== undefined) {
  20239. return calculations.onOnScreen;
  20240. }
  20241. },
  20242. offScreen: function(newCallback) {
  20243. var
  20244. calculations = module.get.elementCalculations(),
  20245. callback = newCallback || settings.onOffScreen,
  20246. callbackName = 'offScreen'
  20247. ;
  20248. if(newCallback) {
  20249. module.debug('Adding callback for offScreen', newCallback);
  20250. settings.onOffScreen = newCallback;
  20251. }
  20252. if(calculations.offScreen) {
  20253. module.execute(callback, callbackName);
  20254. }
  20255. else if(!settings.once) {
  20256. module.remove.occurred(callbackName);
  20257. }
  20258. if(newCallback !== undefined) {
  20259. return calculations.onOffScreen;
  20260. }
  20261. },
  20262. passing: function(newCallback) {
  20263. var
  20264. calculations = module.get.elementCalculations(),
  20265. callback = newCallback || settings.onPassing,
  20266. callbackName = 'passing'
  20267. ;
  20268. if(newCallback) {
  20269. module.debug('Adding callback for passing', newCallback);
  20270. settings.onPassing = newCallback;
  20271. }
  20272. if(calculations.passing) {
  20273. module.execute(callback, callbackName);
  20274. }
  20275. else if(!settings.once) {
  20276. module.remove.occurred(callbackName);
  20277. }
  20278. if(newCallback !== undefined) {
  20279. return calculations.passing;
  20280. }
  20281. },
  20282. topVisible: function(newCallback) {
  20283. var
  20284. calculations = module.get.elementCalculations(),
  20285. callback = newCallback || settings.onTopVisible,
  20286. callbackName = 'topVisible'
  20287. ;
  20288. if(newCallback) {
  20289. module.debug('Adding callback for top visible', newCallback);
  20290. settings.onTopVisible = newCallback;
  20291. }
  20292. if(calculations.topVisible) {
  20293. module.execute(callback, callbackName);
  20294. }
  20295. else if(!settings.once) {
  20296. module.remove.occurred(callbackName);
  20297. }
  20298. if(newCallback === undefined) {
  20299. return calculations.topVisible;
  20300. }
  20301. },
  20302. bottomVisible: function(newCallback) {
  20303. var
  20304. calculations = module.get.elementCalculations(),
  20305. callback = newCallback || settings.onBottomVisible,
  20306. callbackName = 'bottomVisible'
  20307. ;
  20308. if(newCallback) {
  20309. module.debug('Adding callback for bottom visible', newCallback);
  20310. settings.onBottomVisible = newCallback;
  20311. }
  20312. if(calculations.bottomVisible) {
  20313. module.execute(callback, callbackName);
  20314. }
  20315. else if(!settings.once) {
  20316. module.remove.occurred(callbackName);
  20317. }
  20318. if(newCallback === undefined) {
  20319. return calculations.bottomVisible;
  20320. }
  20321. },
  20322. topPassed: function(newCallback) {
  20323. var
  20324. calculations = module.get.elementCalculations(),
  20325. callback = newCallback || settings.onTopPassed,
  20326. callbackName = 'topPassed'
  20327. ;
  20328. if(newCallback) {
  20329. module.debug('Adding callback for top passed', newCallback);
  20330. settings.onTopPassed = newCallback;
  20331. }
  20332. if(calculations.topPassed) {
  20333. module.execute(callback, callbackName);
  20334. }
  20335. else if(!settings.once) {
  20336. module.remove.occurred(callbackName);
  20337. }
  20338. if(newCallback === undefined) {
  20339. return calculations.topPassed;
  20340. }
  20341. },
  20342. bottomPassed: function(newCallback) {
  20343. var
  20344. calculations = module.get.elementCalculations(),
  20345. callback = newCallback || settings.onBottomPassed,
  20346. callbackName = 'bottomPassed'
  20347. ;
  20348. if(newCallback) {
  20349. module.debug('Adding callback for bottom passed', newCallback);
  20350. settings.onBottomPassed = newCallback;
  20351. }
  20352. if(calculations.bottomPassed) {
  20353. module.execute(callback, callbackName);
  20354. }
  20355. else if(!settings.once) {
  20356. module.remove.occurred(callbackName);
  20357. }
  20358. if(newCallback === undefined) {
  20359. return calculations.bottomPassed;
  20360. }
  20361. },
  20362. passingReverse: function(newCallback) {
  20363. var
  20364. calculations = module.get.elementCalculations(),
  20365. callback = newCallback || settings.onPassingReverse,
  20366. callbackName = 'passingReverse'
  20367. ;
  20368. if(newCallback) {
  20369. module.debug('Adding callback for passing reverse', newCallback);
  20370. settings.onPassingReverse = newCallback;
  20371. }
  20372. if(!calculations.passing) {
  20373. if(module.get.occurred('passing')) {
  20374. module.execute(callback, callbackName);
  20375. }
  20376. }
  20377. else if(!settings.once) {
  20378. module.remove.occurred(callbackName);
  20379. }
  20380. if(newCallback !== undefined) {
  20381. return !calculations.passing;
  20382. }
  20383. },
  20384. topVisibleReverse: function(newCallback) {
  20385. var
  20386. calculations = module.get.elementCalculations(),
  20387. callback = newCallback || settings.onTopVisibleReverse,
  20388. callbackName = 'topVisibleReverse'
  20389. ;
  20390. if(newCallback) {
  20391. module.debug('Adding callback for top visible reverse', newCallback);
  20392. settings.onTopVisibleReverse = newCallback;
  20393. }
  20394. if(!calculations.topVisible) {
  20395. if(module.get.occurred('topVisible')) {
  20396. module.execute(callback, callbackName);
  20397. }
  20398. }
  20399. else if(!settings.once) {
  20400. module.remove.occurred(callbackName);
  20401. }
  20402. if(newCallback === undefined) {
  20403. return !calculations.topVisible;
  20404. }
  20405. },
  20406. bottomVisibleReverse: function(newCallback) {
  20407. var
  20408. calculations = module.get.elementCalculations(),
  20409. callback = newCallback || settings.onBottomVisibleReverse,
  20410. callbackName = 'bottomVisibleReverse'
  20411. ;
  20412. if(newCallback) {
  20413. module.debug('Adding callback for bottom visible reverse', newCallback);
  20414. settings.onBottomVisibleReverse = newCallback;
  20415. }
  20416. if(!calculations.bottomVisible) {
  20417. if(module.get.occurred('bottomVisible')) {
  20418. module.execute(callback, callbackName);
  20419. }
  20420. }
  20421. else if(!settings.once) {
  20422. module.remove.occurred(callbackName);
  20423. }
  20424. if(newCallback === undefined) {
  20425. return !calculations.bottomVisible;
  20426. }
  20427. },
  20428. topPassedReverse: function(newCallback) {
  20429. var
  20430. calculations = module.get.elementCalculations(),
  20431. callback = newCallback || settings.onTopPassedReverse,
  20432. callbackName = 'topPassedReverse'
  20433. ;
  20434. if(newCallback) {
  20435. module.debug('Adding callback for top passed reverse', newCallback);
  20436. settings.onTopPassedReverse = newCallback;
  20437. }
  20438. if(!calculations.topPassed) {
  20439. if(module.get.occurred('topPassed')) {
  20440. module.execute(callback, callbackName);
  20441. }
  20442. }
  20443. else if(!settings.once) {
  20444. module.remove.occurred(callbackName);
  20445. }
  20446. if(newCallback === undefined) {
  20447. return !calculations.onTopPassed;
  20448. }
  20449. },
  20450. bottomPassedReverse: function(newCallback) {
  20451. var
  20452. calculations = module.get.elementCalculations(),
  20453. callback = newCallback || settings.onBottomPassedReverse,
  20454. callbackName = 'bottomPassedReverse'
  20455. ;
  20456. if(newCallback) {
  20457. module.debug('Adding callback for bottom passed reverse', newCallback);
  20458. settings.onBottomPassedReverse = newCallback;
  20459. }
  20460. if(!calculations.bottomPassed) {
  20461. if(module.get.occurred('bottomPassed')) {
  20462. module.execute(callback, callbackName);
  20463. }
  20464. }
  20465. else if(!settings.once) {
  20466. module.remove.occurred(callbackName);
  20467. }
  20468. if(newCallback === undefined) {
  20469. return !calculations.bottomPassed;
  20470. }
  20471. },
  20472. execute: function(callback, callbackName) {
  20473. var
  20474. calculations = module.get.elementCalculations(),
  20475. screen = module.get.screenCalculations()
  20476. ;
  20477. callback = callback || false;
  20478. if(callback) {
  20479. if(settings.continuous) {
  20480. module.debug('Callback being called continuously', callbackName, calculations);
  20481. callback.call(element, calculations, screen);
  20482. }
  20483. else if(!module.get.occurred(callbackName)) {
  20484. module.debug('Conditions met', callbackName, calculations);
  20485. callback.call(element, calculations, screen);
  20486. }
  20487. }
  20488. module.save.occurred(callbackName);
  20489. },
  20490. remove: {
  20491. fixed: function() {
  20492. module.debug('Removing fixed position');
  20493. $module
  20494. .removeClass(className.fixed)
  20495. .css({
  20496. position : '',
  20497. top : '',
  20498. left : '',
  20499. zIndex : ''
  20500. })
  20501. ;
  20502. settings.onUnfixed.call(element);
  20503. },
  20504. placeholder: function() {
  20505. module.debug('Removing placeholder content');
  20506. if($placeholder) {
  20507. $placeholder.remove();
  20508. }
  20509. },
  20510. occurred: function(callback) {
  20511. if(callback) {
  20512. var
  20513. occurred = module.cache.occurred
  20514. ;
  20515. if(occurred[callback] !== undefined && occurred[callback] === true) {
  20516. module.debug('Callback can now be called again', callback);
  20517. module.cache.occurred[callback] = false;
  20518. }
  20519. }
  20520. else {
  20521. module.cache.occurred = {};
  20522. }
  20523. }
  20524. },
  20525. save: {
  20526. calculations: function() {
  20527. module.verbose('Saving all calculations necessary to determine positioning');
  20528. module.save.direction();
  20529. module.save.screenCalculations();
  20530. module.save.elementCalculations();
  20531. },
  20532. occurred: function(callback) {
  20533. if(callback) {
  20534. if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
  20535. module.verbose('Saving callback occurred', callback);
  20536. module.cache.occurred[callback] = true;
  20537. }
  20538. }
  20539. },
  20540. scroll: function(scrollPosition) {
  20541. scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
  20542. module.cache.scroll = scrollPosition;
  20543. },
  20544. direction: function() {
  20545. var
  20546. scroll = module.get.scroll(),
  20547. lastScroll = module.get.lastScroll(),
  20548. direction
  20549. ;
  20550. if(scroll > lastScroll && lastScroll) {
  20551. direction = 'down';
  20552. }
  20553. else if(scroll < lastScroll && lastScroll) {
  20554. direction = 'up';
  20555. }
  20556. else {
  20557. direction = 'static';
  20558. }
  20559. module.cache.direction = direction;
  20560. return module.cache.direction;
  20561. },
  20562. elementPosition: function() {
  20563. var
  20564. element = module.cache.element,
  20565. screen = module.get.screenSize()
  20566. ;
  20567. module.verbose('Saving element position');
  20568. // (quicker than $.extend)
  20569. element.fits = (element.height < screen.height);
  20570. element.offset = $module.offset();
  20571. element.width = $module.outerWidth();
  20572. element.height = $module.outerHeight();
  20573. // compensate for scroll in context
  20574. if(module.is.verticallyScrollableContext()) {
  20575. element.offset.top += $context.scrollTop() - $context.offset().top;
  20576. }
  20577. if(module.is.horizontallyScrollableContext()) {
  20578. element.offset.left += $context.scrollLeft - $context.offset().left;
  20579. }
  20580. // store
  20581. module.cache.element = element;
  20582. return element;
  20583. },
  20584. elementCalculations: function() {
  20585. var
  20586. screen = module.get.screenCalculations(),
  20587. element = module.get.elementPosition()
  20588. ;
  20589. // offset
  20590. if(settings.includeMargin) {
  20591. element.margin = {};
  20592. element.margin.top = parseInt($module.css('margin-top'), 10);
  20593. element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
  20594. element.top = element.offset.top - element.margin.top;
  20595. element.bottom = element.offset.top + element.height + element.margin.bottom;
  20596. }
  20597. else {
  20598. element.top = element.offset.top;
  20599. element.bottom = element.offset.top + element.height;
  20600. }
  20601. // visibility
  20602. element.topPassed = (screen.top >= element.top);
  20603. element.bottomPassed = (screen.top >= element.bottom);
  20604. element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
  20605. element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
  20606. element.pixelsPassed = 0;
  20607. element.percentagePassed = 0;
  20608. // meta calculations
  20609. element.onScreen = ((element.topVisible || element.passing) && !element.bottomPassed);
  20610. element.passing = (element.topPassed && !element.bottomPassed);
  20611. element.offScreen = (!element.onScreen);
  20612. // passing calculations
  20613. if(element.passing) {
  20614. element.pixelsPassed = (screen.top - element.top);
  20615. element.percentagePassed = (screen.top - element.top) / element.height;
  20616. }
  20617. module.cache.element = element;
  20618. module.verbose('Updated element calculations', element);
  20619. return element;
  20620. },
  20621. screenCalculations: function() {
  20622. var
  20623. scroll = module.get.scroll()
  20624. ;
  20625. module.save.direction();
  20626. module.cache.screen.top = scroll;
  20627. module.cache.screen.bottom = scroll + module.cache.screen.height;
  20628. return module.cache.screen;
  20629. },
  20630. screenSize: function() {
  20631. module.verbose('Saving window position');
  20632. module.cache.screen = {
  20633. height: $context.height()
  20634. };
  20635. },
  20636. position: function() {
  20637. module.save.screenSize();
  20638. module.save.elementPosition();
  20639. }
  20640. },
  20641. get: {
  20642. pixelsPassed: function(amount) {
  20643. var
  20644. element = module.get.elementCalculations()
  20645. ;
  20646. if(amount.search('%') > -1) {
  20647. return ( element.height * (parseInt(amount, 10) / 100) );
  20648. }
  20649. return parseInt(amount, 10);
  20650. },
  20651. occurred: function(callback) {
  20652. return (module.cache.occurred !== undefined)
  20653. ? module.cache.occurred[callback] || false
  20654. : false
  20655. ;
  20656. },
  20657. direction: function() {
  20658. if(module.cache.direction === undefined) {
  20659. module.save.direction();
  20660. }
  20661. return module.cache.direction;
  20662. },
  20663. elementPosition: function() {
  20664. if(module.cache.element === undefined) {
  20665. module.save.elementPosition();
  20666. }
  20667. return module.cache.element;
  20668. },
  20669. elementCalculations: function() {
  20670. if(module.cache.element === undefined) {
  20671. module.save.elementCalculations();
  20672. }
  20673. return module.cache.element;
  20674. },
  20675. screenCalculations: function() {
  20676. if(module.cache.screen === undefined) {
  20677. module.save.screenCalculations();
  20678. }
  20679. return module.cache.screen;
  20680. },
  20681. screenSize: function() {
  20682. if(module.cache.screen === undefined) {
  20683. module.save.screenSize();
  20684. }
  20685. return module.cache.screen;
  20686. },
  20687. scroll: function() {
  20688. if(module.cache.scroll === undefined) {
  20689. module.save.scroll();
  20690. }
  20691. return module.cache.scroll;
  20692. },
  20693. lastScroll: function() {
  20694. if(module.cache.screen === undefined) {
  20695. module.debug('First scroll event, no last scroll could be found');
  20696. return false;
  20697. }
  20698. return module.cache.screen.top;
  20699. }
  20700. },
  20701. setting: function(name, value) {
  20702. if( $.isPlainObject(name) ) {
  20703. $.extend(true, settings, name);
  20704. }
  20705. else if(value !== undefined) {
  20706. settings[name] = value;
  20707. }
  20708. else {
  20709. return settings[name];
  20710. }
  20711. },
  20712. internal: function(name, value) {
  20713. if( $.isPlainObject(name) ) {
  20714. $.extend(true, module, name);
  20715. }
  20716. else if(value !== undefined) {
  20717. module[name] = value;
  20718. }
  20719. else {
  20720. return module[name];
  20721. }
  20722. },
  20723. debug: function() {
  20724. if(!settings.silent && settings.debug) {
  20725. if(settings.performance) {
  20726. module.performance.log(arguments);
  20727. }
  20728. else {
  20729. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20730. module.debug.apply(console, arguments);
  20731. }
  20732. }
  20733. },
  20734. verbose: function() {
  20735. if(!settings.silent && settings.verbose && settings.debug) {
  20736. if(settings.performance) {
  20737. module.performance.log(arguments);
  20738. }
  20739. else {
  20740. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  20741. module.verbose.apply(console, arguments);
  20742. }
  20743. }
  20744. },
  20745. error: function() {
  20746. if(!settings.silent) {
  20747. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  20748. module.error.apply(console, arguments);
  20749. }
  20750. },
  20751. performance: {
  20752. log: function(message) {
  20753. var
  20754. currentTime,
  20755. executionTime,
  20756. previousTime
  20757. ;
  20758. if(settings.performance) {
  20759. currentTime = new Date().getTime();
  20760. previousTime = time || currentTime;
  20761. executionTime = currentTime - previousTime;
  20762. time = currentTime;
  20763. performance.push({
  20764. 'Name' : message[0],
  20765. 'Arguments' : [].slice.call(message, 1) || '',
  20766. 'Element' : element,
  20767. 'Execution Time' : executionTime
  20768. });
  20769. }
  20770. clearTimeout(module.performance.timer);
  20771. module.performance.timer = setTimeout(module.performance.display, 500);
  20772. },
  20773. display: function() {
  20774. var
  20775. title = settings.name + ':',
  20776. totalTime = 0
  20777. ;
  20778. time = false;
  20779. clearTimeout(module.performance.timer);
  20780. $.each(performance, function(index, data) {
  20781. totalTime += data['Execution Time'];
  20782. });
  20783. title += ' ' + totalTime + 'ms';
  20784. if(moduleSelector) {
  20785. title += ' \'' + moduleSelector + '\'';
  20786. }
  20787. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  20788. console.groupCollapsed(title);
  20789. if(console.table) {
  20790. console.table(performance);
  20791. }
  20792. else {
  20793. $.each(performance, function(index, data) {
  20794. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  20795. });
  20796. }
  20797. console.groupEnd();
  20798. }
  20799. performance = [];
  20800. }
  20801. },
  20802. invoke: function(query, passedArguments, context) {
  20803. var
  20804. object = instance,
  20805. maxDepth,
  20806. found,
  20807. response
  20808. ;
  20809. passedArguments = passedArguments || queryArguments;
  20810. context = element || context;
  20811. if(typeof query == 'string' && object !== undefined) {
  20812. query = query.split(/[\. ]/);
  20813. maxDepth = query.length - 1;
  20814. $.each(query, function(depth, value) {
  20815. var camelCaseValue = (depth != maxDepth)
  20816. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  20817. : query
  20818. ;
  20819. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  20820. object = object[camelCaseValue];
  20821. }
  20822. else if( object[camelCaseValue] !== undefined ) {
  20823. found = object[camelCaseValue];
  20824. return false;
  20825. }
  20826. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  20827. object = object[value];
  20828. }
  20829. else if( object[value] !== undefined ) {
  20830. found = object[value];
  20831. return false;
  20832. }
  20833. else {
  20834. module.error(error.method, query);
  20835. return false;
  20836. }
  20837. });
  20838. }
  20839. if ( $.isFunction( found ) ) {
  20840. response = found.apply(context, passedArguments);
  20841. }
  20842. else if(found !== undefined) {
  20843. response = found;
  20844. }
  20845. if($.isArray(returnedValue)) {
  20846. returnedValue.push(response);
  20847. }
  20848. else if(returnedValue !== undefined) {
  20849. returnedValue = [returnedValue, response];
  20850. }
  20851. else if(response !== undefined) {
  20852. returnedValue = response;
  20853. }
  20854. return found;
  20855. }
  20856. };
  20857. if(methodInvoked) {
  20858. if(instance === undefined) {
  20859. module.initialize();
  20860. }
  20861. instance.save.scroll();
  20862. instance.save.calculations();
  20863. module.invoke(query);
  20864. }
  20865. else {
  20866. if(instance !== undefined) {
  20867. instance.invoke('destroy');
  20868. }
  20869. module.initialize();
  20870. }
  20871. })
  20872. ;
  20873. return (returnedValue !== undefined)
  20874. ? returnedValue
  20875. : this
  20876. ;
  20877. };
  20878. $.fn.visibility.settings = {
  20879. name : 'Visibility',
  20880. namespace : 'visibility',
  20881. debug : false,
  20882. verbose : false,
  20883. performance : true,
  20884. // whether to use mutation observers to follow changes
  20885. observeChanges : true,
  20886. // check position immediately on init
  20887. initialCheck : true,
  20888. // whether to refresh calculations after all page images load
  20889. refreshOnLoad : true,
  20890. // whether to refresh calculations after page resize event
  20891. refreshOnResize : true,
  20892. // should call callbacks on refresh event (resize, etc)
  20893. checkOnRefresh : true,
  20894. // callback should only occur one time
  20895. once : true,
  20896. // callback should fire continuously whe evaluates to true
  20897. continuous : false,
  20898. // offset to use with scroll top
  20899. offset : 0,
  20900. // whether to include margin in elements position
  20901. includeMargin : false,
  20902. // scroll context for visibility checks
  20903. context : window,
  20904. // visibility check delay in ms (defaults to animationFrame)
  20905. throttle : false,
  20906. // special visibility type (image, fixed)
  20907. type : false,
  20908. // z-index to use with visibility 'fixed'
  20909. zIndex : '10',
  20910. // image only animation settings
  20911. transition : 'fade in',
  20912. duration : 1000,
  20913. // array of callbacks for percentage
  20914. onPassed : {},
  20915. // standard callbacks
  20916. onOnScreen : false,
  20917. onOffScreen : false,
  20918. onPassing : false,
  20919. onTopVisible : false,
  20920. onBottomVisible : false,
  20921. onTopPassed : false,
  20922. onBottomPassed : false,
  20923. // reverse callbacks
  20924. onPassingReverse : false,
  20925. onTopVisibleReverse : false,
  20926. onBottomVisibleReverse : false,
  20927. onTopPassedReverse : false,
  20928. onBottomPassedReverse : false,
  20929. // special callbacks for image
  20930. onLoad : function() {},
  20931. onAllLoaded : function() {},
  20932. // special callbacks for fixed position
  20933. onFixed : function() {},
  20934. onUnfixed : function() {},
  20935. // utility callbacks
  20936. onUpdate : false, // disabled by default for performance
  20937. onRefresh : function(){},
  20938. metadata : {
  20939. src: 'src'
  20940. },
  20941. className: {
  20942. fixed : 'fixed',
  20943. placeholder : 'placeholder',
  20944. visible : 'visible'
  20945. },
  20946. error : {
  20947. method : 'The method you called is not defined.',
  20948. visible : 'Element is hidden, you must call refresh after element becomes visible'
  20949. }
  20950. };
  20951. })( jQuery, window, document );