zui.js 207 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448
  1. /*!
  2. * ZUI - v1.4.0 - 2016-01-26
  3. * http://zui.sexy
  4. * GitHub: https://github.com/easysoft/zui.git
  5. * Copyright (c) 2016 cnezsoft.com; Licensed MIT
  6. */
  7. /* Some code copy from Bootstrap v3.0.0 by @fat and @mdo. (Copyright 2013 Twitter, Inc. Licensed under http://www.apache.org/licenses/)*/
  8. /* ========================================================================
  9. * ZUI: jquery.extensions.js
  10. * http://zui.sexy
  11. * ========================================================================
  12. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  13. * ======================================================================== */
  14. (function($, window) {
  15. 'use strict';
  16. /* Check jquery */
  17. if(typeof($) === 'undefined') throw new Error('ZUI requires jQuery');
  18. // ZUI shared object
  19. if(!$.zui) $.zui = function(obj) {
  20. if($.isPlainObject(obj)) {
  21. $.extend($.zui, obj);
  22. }
  23. };
  24. var lastUuidAmend = 0;
  25. $.zui({
  26. uuid: function() {
  27. return(new Date()).getTime() * 1000 + (lastUuidAmend++) % 1000;
  28. },
  29. callEvent: function(func, event, proxy) {
  30. if($.isFunction(func)) {
  31. if(proxy !== undefined) {
  32. func = $.proxy(func, proxy);
  33. }
  34. var result = func(event);
  35. if(event) event.result = result;
  36. return !(result !== undefined && (!result));
  37. }
  38. return 1;
  39. },
  40. clientLang: function() {
  41. var lang;
  42. var config = window.config;
  43. if(typeof(config) != 'undefined' && config.clientLang) {
  44. lang = config.clientLang;
  45. } else {
  46. var hl = $('html').attr('lang');
  47. lang = hl ? hl : (navigator.userLanguage || navigator.userLanguage || 'zh_cn');
  48. }
  49. return lang.replace('-', '_').toLowerCase();
  50. }
  51. });
  52. $.fn.callEvent = function(name, event, model) {
  53. var $this = $(this);
  54. var dotIndex = name.indexOf('.zui.');
  55. var shortName = name;
  56. if(dotIndex < 0 && model && model.name) {
  57. name += '.' + model.name;
  58. } else {
  59. shortName = name.substring(0, dotIndex);
  60. }
  61. var e = $.Event(name, event);
  62. if((model === undefined) && dotIndex > 0) {
  63. model = $this.data(name.substring(dotIndex + 1));
  64. }
  65. if(model && model.options) {
  66. var func = model.options[shortName];
  67. if($.isFunction(func)) {
  68. $.zui.callEvent(model.options[shortName], e, model);
  69. }
  70. }
  71. return e;
  72. };
  73. }(jQuery, window));
  74. /* ========================================================================
  75. * Bootstrap: button.js v3.0.3
  76. * http://getbootstrap.com/javascript/#buttons
  77. * ========================================================================
  78. * Copyright 2011-2014 Twitter, Inc.
  79. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  80. * ======================================================================== */
  81. + function($) {
  82. 'use strict';
  83. // BUTTON PUBLIC CLASS DEFINITION
  84. // ==============================
  85. var Button = function(element, options) {
  86. this.$element = $(element)
  87. this.options = $.extend({}, Button.DEFAULTS, options)
  88. this.isLoading = false
  89. }
  90. Button.DEFAULTS = {
  91. loadingText: 'loading...'
  92. }
  93. Button.prototype.setState = function(state) {
  94. var d = 'disabled'
  95. var $el = this.$element
  96. var val = $el.is('input') ? 'val' : 'html'
  97. var data = $el.data()
  98. state = state + 'Text'
  99. if(!data.resetText) $el.data('resetText', $el[val]())
  100. $el[val](data[state] || this.options[state])
  101. // push to event loop to allow forms to submit
  102. setTimeout($.proxy(function() {
  103. if(state == 'loadingText') {
  104. this.isLoading = true
  105. $el.addClass(d).attr(d, d)
  106. } else if(this.isLoading) {
  107. this.isLoading = false
  108. $el.removeClass(d).removeAttr(d)
  109. }
  110. }, this), 0)
  111. }
  112. Button.prototype.toggle = function() {
  113. var changed = true
  114. var $parent = this.$element.closest('[data-toggle="buttons"]')
  115. if($parent.length) {
  116. var $input = this.$element.find('input')
  117. if($input.prop('type') == 'radio') {
  118. if($input.prop('checked') && this.$element.hasClass('active')) changed = false
  119. else $parent.find('.active').removeClass('active')
  120. }
  121. if(changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
  122. }
  123. if(changed) this.$element.toggleClass('active')
  124. }
  125. // BUTTON PLUGIN DEFINITION
  126. // ========================
  127. var old = $.fn.button
  128. $.fn.button = function(option) {
  129. return this.each(function() {
  130. var $this = $(this)
  131. var data = $this.data('zui.button')
  132. var options = typeof option == 'object' && option
  133. if(!data) $this.data('zui.button', (data = new Button(this, options)))
  134. if(option == 'toggle') data.toggle()
  135. else if(option) data.setState(option)
  136. })
  137. }
  138. $.fn.button.Constructor = Button
  139. // BUTTON NO CONFLICT
  140. // ==================
  141. $.fn.button.noConflict = function() {
  142. $.fn.button = old
  143. return this
  144. }
  145. // BUTTON DATA-API
  146. // ===============
  147. $(document).on('click.zui.button.data-api', '[data-toggle^=button]', function(e) {
  148. var $btn = $(e.target)
  149. if(!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
  150. $btn.button('toggle')
  151. e.preventDefault()
  152. })
  153. }(jQuery);
  154. /* ========================================================================
  155. * Bootstrap: alert.js v3.0.0
  156. * http://twbs.github.com/bootstrap/javascript.html#alerts
  157. * ========================================================================
  158. * Copyright 2013 Twitter, Inc.
  159. *
  160. * Licensed under the Apache License, Version 2.0 (the "License");
  161. * you may not use this file except in compliance with the License.
  162. * You may obtain a copy of the License at
  163. *
  164. * http://www.apache.org/licenses/LICENSE-2.0
  165. *
  166. * Unless required by applicable law or agreed to in writing, software
  167. * distributed under the License is distributed on an "AS IS" BASIS,
  168. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  169. * See the License for the specific language governing permissions and
  170. * limitations under the License.
  171. * ======================================================================== */
  172. + function($) {
  173. 'use strict';
  174. // ALERT CLASS DEFINITION
  175. // ======================
  176. var dismiss = '[data-dismiss="alert"]'
  177. var zuiname = 'zui.alert';
  178. var Alert = function(el) {
  179. $(el).on('click', dismiss, this.close)
  180. }
  181. Alert.prototype.close = function(e) {
  182. var $this = $(this)
  183. var selector = $this.attr('data-target')
  184. if(!selector) {
  185. selector = $this.attr('href')
  186. selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  187. }
  188. var $parent = $(selector)
  189. if(e) e.preventDefault()
  190. if(!$parent.length) {
  191. $parent = $this.hasClass('alert') ? $this : $this.parent()
  192. }
  193. $parent.trigger(e = $.Event('close.' + zuiname))
  194. if(e.isDefaultPrevented()) return
  195. $parent.removeClass('in')
  196. function removeElement() {
  197. $parent.trigger('closed.' + zuiname).remove()
  198. }
  199. $.support.transition && $parent.hasClass('fade') ?
  200. $parent
  201. .one($.support.transition.end, removeElement)
  202. .emulateTransitionEnd(150) :
  203. removeElement()
  204. }
  205. // ALERT PLUGIN DEFINITION
  206. // =======================
  207. var old = $.fn.alert
  208. $.fn.alert = function(option) {
  209. return this.each(function() {
  210. var $this = $(this)
  211. var data = $this.data(zuiname)
  212. if(!data) $this.data(zuiname, (data = new Alert(this)))
  213. if(typeof option == 'string') data[option].call($this)
  214. })
  215. }
  216. $.fn.alert.Constructor = Alert
  217. // ALERT NO CONFLICT
  218. // =================
  219. $.fn.alert.noConflict = function() {
  220. $.fn.alert = old
  221. return this
  222. }
  223. // ALERT DATA-API
  224. // ==============
  225. $(document).on('click.' + zuiname + '.data-api', dismiss, Alert.prototype.close)
  226. }(window.jQuery);
  227. /* ========================================================================
  228. * Bootstrap: tab.js v3.0.0
  229. * http://twbs.github.com/bootstrap/javascript.html#tabs
  230. * ========================================================================
  231. * Copyright 2012 Twitter, Inc.
  232. *
  233. * Licensed under the Apache License, Version 2.0 (the "License");
  234. * you may not use this file except in compliance with the License.
  235. * You may obtain a copy of the License at
  236. *
  237. * http://www.apache.org/licenses/LICENSE-2.0
  238. *
  239. * Unless required by applicable law or agreed to in writing, software
  240. * distributed under the License is distributed on an "AS IS" BASIS,
  241. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  242. * See the License for the specific language governing permissions and
  243. * limitations under the License.
  244. * ======================================================================== */
  245. + function($) {
  246. 'use strict';
  247. // TAB CLASS DEFINITION
  248. // ====================
  249. var zuiname = 'zui.tab'
  250. var Tab = function(element) {
  251. this.element = $(element)
  252. }
  253. Tab.prototype.show = function() {
  254. var $this = this.element
  255. var $ul = $this.closest('ul:not(.dropdown-menu)')
  256. var selector = $this.attr('data-target')
  257. if(!selector) {
  258. selector = $this.attr('href')
  259. selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
  260. }
  261. if($this.parent('li').hasClass('active')) return
  262. var previous = $ul.find('.active:last a')[0]
  263. var e = $.Event('show.' + zuiname, {
  264. relatedTarget: previous
  265. })
  266. $this.trigger(e)
  267. if(e.isDefaultPrevented()) return
  268. var $target = $(selector)
  269. this.activate($this.parent('li'), $ul)
  270. this.activate($target, $target.parent(), function() {
  271. $this.trigger({
  272. type: 'shown.' + zuiname,
  273. relatedTarget: previous
  274. })
  275. })
  276. }
  277. Tab.prototype.activate = function(element, container, callback) {
  278. var $active = container.find('> .active')
  279. var transition = callback && $.support.transition && $active.hasClass('fade')
  280. function next() {
  281. $active
  282. .removeClass('active')
  283. .find('> .dropdown-menu > .active')
  284. .removeClass('active')
  285. element.addClass('active')
  286. if(transition) {
  287. element[0].offsetWidth // reflow for transition
  288. element.addClass('in')
  289. } else {
  290. element.removeClass('fade')
  291. }
  292. if(element.parent('.dropdown-menu')) {
  293. element.closest('li.dropdown').addClass('active')
  294. }
  295. callback && callback()
  296. }
  297. transition ?
  298. $active
  299. .one($.support.transition.end, next)
  300. .emulateTransitionEnd(150) :
  301. next()
  302. $active.removeClass('in')
  303. }
  304. // TAB PLUGIN DEFINITION
  305. // =====================
  306. var old = $.fn.tab
  307. $.fn.tab = function(option) {
  308. return this.each(function() {
  309. var $this = $(this)
  310. var data = $this.data(zuiname)
  311. if(!data) $this.data(zuiname, (data = new Tab(this)))
  312. if(typeof option == 'string') data[option]()
  313. })
  314. }
  315. $.fn.tab.Constructor = Tab
  316. // TAB NO CONFLICT
  317. // ===============
  318. $.fn.tab.noConflict = function() {
  319. $.fn.tab = old
  320. return this
  321. }
  322. // TAB DATA-API
  323. // ============
  324. $(document).on('click.zui.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function(e) {
  325. e.preventDefault()
  326. $(this).tab('show')
  327. })
  328. }(window.jQuery);
  329. /* ========================================================================
  330. * Bootstrap: transition.js v3.2.0
  331. * http://getbootstrap.com/javascript/#transitions
  332. * ========================================================================
  333. * Copyright 2011-2014 Twitter, Inc.
  334. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  335. * ======================================================================== */
  336. + function($) {
  337. 'use strict';
  338. // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  339. // ============================================================
  340. function transitionEnd() {
  341. var el = document.createElement('bootstrap')
  342. var transEndEventNames = {
  343. WebkitTransition: 'webkitTransitionEnd',
  344. MozTransition: 'transitionend',
  345. OTransition: 'oTransitionEnd otransitionend',
  346. transition: 'transitionend'
  347. }
  348. for(var name in transEndEventNames) {
  349. if(el.style[name] !== undefined) {
  350. return {
  351. end: transEndEventNames[name]
  352. }
  353. }
  354. }
  355. return false // explicit for ie8 ( ._.)
  356. }
  357. // http://blog.alexmaccaw.com/css-transitions
  358. $.fn.emulateTransitionEnd = function(duration) {
  359. var called = false
  360. var $el = this
  361. $(this).one('bsTransitionEnd', function() {
  362. called = true
  363. })
  364. var callback = function() {
  365. if(!called) $($el).trigger($.support.transition.end)
  366. }
  367. setTimeout(callback, duration)
  368. return this
  369. }
  370. $(function() {
  371. $.support.transition = transitionEnd()
  372. if(!$.support.transition) return
  373. $.event.special.bsTransitionEnd = {
  374. bindType: $.support.transition.end,
  375. delegateType: $.support.transition.end,
  376. handle: function(e) {
  377. if($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
  378. }
  379. }
  380. })
  381. }(jQuery);
  382. /* ========================================================================
  383. * Bootstrap: collapse.js v3.0.0
  384. * http://twbs.github.com/bootstrap/javascript.html#collapse
  385. * ========================================================================
  386. * Copyright 2012 Twitter, Inc.
  387. *
  388. * Licensed under the Apache License, Version 2.0 (the "License");
  389. * you may not use this file except in compliance with the License.
  390. * You may obtain a copy of the License at
  391. *
  392. * http://www.apache.org/licenses/LICENSE-2.0
  393. *
  394. * Unless required by applicable law or agreed to in writing, software
  395. * distributed under the License is distributed on an "AS IS" BASIS,
  396. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  397. * See the License for the specific language governing permissions and
  398. * limitations under the License.
  399. * ======================================================================== */
  400. + function($) {
  401. 'use strict';
  402. var zuiname = 'zui.collapse'
  403. // COLLAPSE PUBLIC CLASS DEFINITION
  404. // ================================
  405. var Collapse = function(element, options) {
  406. this.$element = $(element)
  407. this.options = $.extend({}, Collapse.DEFAULTS, options)
  408. this.transitioning = null
  409. if(this.options.parent) this.$parent = $(this.options.parent)
  410. if(this.options.toggle) this.toggle()
  411. }
  412. Collapse.DEFAULTS = {
  413. toggle: true
  414. }
  415. Collapse.prototype.dimension = function() {
  416. var hasWidth = this.$element.hasClass('width')
  417. return hasWidth ? 'width' : 'height'
  418. }
  419. Collapse.prototype.show = function() {
  420. if(this.transitioning || this.$element.hasClass('in')) return
  421. var startEvent = $.Event('show.' + zuiname)
  422. this.$element.trigger(startEvent)
  423. if(startEvent.isDefaultPrevented()) return
  424. var actives = this.$parent && this.$parent.find('> .panel > .in')
  425. if(actives && actives.length) {
  426. var hasData = actives.data(zuiname)
  427. if(hasData && hasData.transitioning) return
  428. actives.collapse('hide')
  429. hasData || actives.data(zuiname, null)
  430. }
  431. var dimension = this.dimension()
  432. this.$element
  433. .removeClass('collapse')
  434. .addClass('collapsing')[dimension](0)
  435. this.transitioning = 1
  436. var complete = function() {
  437. this.$element
  438. .removeClass('collapsing')
  439. .addClass('in')[dimension]('auto')
  440. this.transitioning = 0
  441. this.$element.trigger('shown.' + zuiname)
  442. }
  443. if(!$.support.transition) return complete.call(this)
  444. var scrollSize = $.camelCase(['scroll', dimension].join('-'))
  445. this.$element
  446. .one($.support.transition.end, $.proxy(complete, this))
  447. .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
  448. }
  449. Collapse.prototype.hide = function() {
  450. if(this.transitioning || !this.$element.hasClass('in')) return
  451. var startEvent = $.Event('hide.' + zuiname)
  452. this.$element.trigger(startEvent)
  453. if(startEvent.isDefaultPrevented()) return
  454. var dimension = this.dimension()
  455. this.$element[dimension](this.$element[dimension]())[0].offsetHeight
  456. this.$element
  457. .addClass('collapsing')
  458. .removeClass('collapse')
  459. .removeClass('in')
  460. this.transitioning = 1
  461. var complete = function() {
  462. this.transitioning = 0
  463. this.$element
  464. .trigger('hidden.' + zuiname)
  465. .removeClass('collapsing')
  466. .addClass('collapse')
  467. }
  468. if(!$.support.transition) return complete.call(this)
  469. this.$element[dimension](0)
  470. .one($.support.transition.end, $.proxy(complete, this))
  471. .emulateTransitionEnd(350)
  472. }
  473. Collapse.prototype.toggle = function() {
  474. this[this.$element.hasClass('in') ? 'hide' : 'show']()
  475. }
  476. // COLLAPSE PLUGIN DEFINITION
  477. // ==========================
  478. var old = $.fn.collapse
  479. $.fn.collapse = function(option) {
  480. return this.each(function() {
  481. var $this = $(this)
  482. var data = $this.data(zuiname)
  483. var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
  484. if(!data) $this.data(zuiname, (data = new Collapse(this, options)))
  485. if(typeof option == 'string') data[option]()
  486. })
  487. }
  488. $.fn.collapse.Constructor = Collapse
  489. // COLLAPSE NO CONFLICT
  490. // ====================
  491. $.fn.collapse.noConflict = function() {
  492. $.fn.collapse = old
  493. return this
  494. }
  495. // COLLAPSE DATA-API
  496. // =================
  497. $(document).on('click.' + zuiname + '.data-api', '[data-toggle=collapse]', function(e) {
  498. var $this = $(this),
  499. href
  500. var target = $this.attr('data-target') || e.preventDefault() || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
  501. var $target = $(target)
  502. var data = $target.data(zuiname)
  503. var option = data ? 'toggle' : $this.data()
  504. var parent = $this.attr('data-parent')
  505. var $parent = parent && $(parent)
  506. if(!data || !data.transitioning) {
  507. if($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed')
  508. $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
  509. }
  510. $target.collapse(option)
  511. })
  512. }(window.jQuery);
  513. /* ========================================================================
  514. * ZUI: device.js
  515. * http://zui.sexy
  516. * ========================================================================
  517. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  518. * ======================================================================== */
  519. (function(window, $) {
  520. 'use strict';
  521. var desktopLg = 1200,
  522. desktop = 992,
  523. tablet = 768,
  524. cssNames = {
  525. desktop: 'screen-desktop',
  526. desktopLg: 'screen-desktop-wide',
  527. tablet: 'screen-tablet',
  528. phone: 'screen-phone',
  529. isMobile: 'device-mobile',
  530. isDesktop: 'device-desktop'
  531. };
  532. var $window = $(window);
  533. var resetCssClass = function() {
  534. var width = $window.width();
  535. $('html').toggleClass(cssNames.desktop, width >= desktop && width < desktopLg)
  536. .toggleClass(cssNames.desktopLg, width >= desktopLg)
  537. .toggleClass(cssNames.tablet, width >= tablet && width < desktop)
  538. .toggleClass(cssNames.phone, width < tablet)
  539. .toggleClass(cssNames.isMobile, width < desktop)
  540. .toggleClass(cssNames.isDesktop, width >= desktop);
  541. };
  542. $window.resize(resetCssClass);
  543. resetCssClass();
  544. }(window, jQuery));
  545. /* ========================================================================
  546. * ZUI: browser.js
  547. * http://zui.sexy
  548. * ========================================================================
  549. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  550. * ======================================================================== */
  551. (function($) {
  552. 'use strict';
  553. var browseHappyTip = {
  554. 'zh_cn': '您的浏览器版本过低,无法体验所有功能,建议升级或者更换浏览器。 <a href="http://browsehappy.com/" target="_blank" class="alert-link">了解更多...</a>',
  555. 'zh_tw': '您的瀏覽器版本過低,無法體驗所有功能,建議升級或者更换瀏覽器。<a href="http://browsehappy.com/" target="_blank" class="alert-link">了解更多...</a>',
  556. 'en': 'Your browser is too old, it has been unable to experience the colorful internet. We strongly recommend that you upgrade a better one. <a href="http://browsehappy.com/" target="_blank" class="alert-link">Learn more...</a>'
  557. };
  558. // The browser modal class
  559. var Browser = function() {
  560. var ie = this.isIE() || this.isIE10() || false;
  561. if(ie) {
  562. for(var i = 10; i > 5; i--) {
  563. if(this.isIE(i)) {
  564. ie = i;
  565. break;
  566. }
  567. }
  568. }
  569. this.ie = ie;
  570. this.cssHelper();
  571. };
  572. // Append CSS class to html tag
  573. Browser.prototype.cssHelper = function() {
  574. var ie = this.ie,
  575. $html = $('html');
  576. $html.toggleClass('ie', ie)
  577. .removeClass('ie-6 ie-7 ie-8 ie-9 ie-10');
  578. if(ie) {
  579. $html.addClass('ie-' + ie)
  580. .toggleClass('gt-ie-7 gte-ie-8 support-ie', ie >= 8)
  581. .toggleClass('lte-ie-7 lt-ie-8 outdated-ie', ie < 8)
  582. .toggleClass('gt-ie-8 gte-ie-9', ie >= 9)
  583. .toggleClass('lte-ie-8 lt-ie-9', ie < 9)
  584. .toggleClass('gt-ie-9 gte-ie-10', ie >= 10)
  585. .toggleClass('lte-ie-9 lt-ie-10', ie < 10);
  586. }
  587. };
  588. // Show browse happy tip
  589. Browser.prototype.tip = function(showCoontent) {
  590. var $browseHappy = $('#browseHappyTip');
  591. if(!$browseHappy.length) {
  592. $browseHappy = $('<div id="browseHappyTip" class="alert alert-dismissable alert-danger-inverse alert-block" style="position: relative; z-index: 99999"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button><div class="container"><div class="content text-center"></div></div></div>');
  593. $browseHappy.prependTo('body');
  594. }
  595. $browseHappy.find('.content').html(showCoontent || this.browseHappyTip || browseHappyTip[$.zui.clientLang() || 'zh_cn']);
  596. };
  597. // Detect it is IE, can given a version
  598. Browser.prototype.isIE = function(version) {
  599. if(version === 10) return this.isIE10();
  600. var b = document.createElement('b');
  601. b.innerHTML = '<!--[if IE ' + (version || '') + ']><i></i><![endif]-->';
  602. return b.getElementsByTagName('i').length === 1;
  603. };
  604. // Detect ie 10 with hack
  605. Browser.prototype.isIE10 = function() {
  606. return (/*@cc_on!@*/false);
  607. };
  608. $.zui({
  609. browser: new Browser()
  610. });
  611. $(function() {
  612. if(!$('body').hasClass('disabled-browser-tip')) {
  613. if($.zui.browser.ie && $.zui.browser.ie < 8) {
  614. $.zui.browser.tip();
  615. }
  616. }
  617. });
  618. }(jQuery));
  619. /* ========================================================================
  620. * ZUI: date.js
  621. * http://zui.sexy
  622. * ========================================================================
  623. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  624. * ======================================================================== */
  625. (function() {
  626. 'use strict';
  627. /**
  628. * Ticks of a whole day
  629. * @type {number}
  630. */
  631. Date.ONEDAY_TICKS = 24 * 3600 * 1000;
  632. /**
  633. * Format date to a string
  634. *
  635. * @param string format
  636. * @return string
  637. */
  638. if(!Date.prototype.format) {
  639. Date.prototype.format = function(format) {
  640. var date = {
  641. 'M+': this.getMonth() + 1,
  642. 'd+': this.getDate(),
  643. 'h+': this.getHours(),
  644. 'm+': this.getMinutes(),
  645. 's+': this.getSeconds(),
  646. 'q+': Math.floor((this.getMonth() + 3) / 3),
  647. 'S+': this.getMilliseconds()
  648. };
  649. if(/(y+)/i.test(format)) {
  650. format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
  651. }
  652. for(var k in date) {
  653. if(new RegExp('(' + k + ')').test(format)) {
  654. format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? date[k] : ('00' + date[k]).substr(('' + date[k]).length));
  655. }
  656. }
  657. return format;
  658. };
  659. }
  660. /**
  661. * Add milliseconds to the date
  662. * @param {number} value
  663. */
  664. if(!Date.prototype.addMilliseconds) {
  665. Date.prototype.addMilliseconds = function(value) {
  666. this.setTime(this.getTime() + value);
  667. return this;
  668. };
  669. }
  670. /**
  671. * Add days to the date
  672. * @param {number} days
  673. */
  674. if(!Date.prototype.addDays) {
  675. Date.prototype.addDays = function(days) {
  676. this.addMilliseconds(days * Date.ONEDAY_TICKS);
  677. return this;
  678. };
  679. }
  680. /**
  681. * Clone a new date instane from the date
  682. * @return {Date}
  683. */
  684. if(!Date.prototype.clone) {
  685. Date.prototype.clone = function() {
  686. var date = new Date();
  687. date.setTime(this.getTime());
  688. return date;
  689. };
  690. }
  691. /**
  692. * Judge the year is in a leap year
  693. * @param {integer} year
  694. * @return {Boolean}
  695. */
  696. if(!Date.isLeapYear) {
  697. Date.isLeapYear = function(year) {
  698. return(((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
  699. };
  700. }
  701. if(!Date.getDaysInMonth) {
  702. /**
  703. * Get days number of the date
  704. * @param {integer} year
  705. * @param {integer} month
  706. * @return {integer}
  707. */
  708. Date.getDaysInMonth = function(year, month) {
  709. return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
  710. };
  711. }
  712. /**
  713. * Judge the date is in a leap year
  714. * @return {Boolean}
  715. */
  716. if(!Date.prototype.isLeapYear) {
  717. Date.prototype.isLeapYear = function() {
  718. return Date.isLeapYear(this.getFullYear());
  719. };
  720. }
  721. /**
  722. * Clear time part of the date
  723. * @return {date}
  724. */
  725. if(!Date.prototype.clearTime) {
  726. Date.prototype.clearTime = function() {
  727. this.setHours(0);
  728. this.setMinutes(0);
  729. this.setSeconds(0);
  730. this.setMilliseconds(0);
  731. return this;
  732. };
  733. }
  734. /**
  735. * Get days of this month of the date
  736. * @return {integer}
  737. */
  738. if(!Date.prototype.getDaysInMonth) {
  739. Date.prototype.getDaysInMonth = function() {
  740. return Date.getDaysInMonth(this.getFullYear(), this.getMonth());
  741. };
  742. }
  743. /**
  744. * Add months to the date
  745. * @param {date} value
  746. */
  747. if(!Date.prototype.addMonths) {
  748. Date.prototype.addMonths = function(value) {
  749. var n = this.getDate();
  750. this.setDate(1);
  751. this.setMonth(this.getMonth() + value);
  752. this.setDate(Math.min(n, this.getDaysInMonth()));
  753. return this;
  754. };
  755. }
  756. /**
  757. * Get last week day of the date
  758. * @param {integer} day
  759. * @return {date}
  760. */
  761. if(!Date.prototype.getLastWeekday) {
  762. Date.prototype.getLastWeekday = function(day) {
  763. day = day || 1;
  764. var d = this.clone();
  765. while(d.getDay() != day) {
  766. d.addDays(-1);
  767. }
  768. d.clearTime();
  769. return d;
  770. };
  771. }
  772. /**
  773. * Judge the date is same day as another date
  774. * @param {date} date
  775. * @return {Boolean}
  776. */
  777. if(!Date.prototype.isSameDay) {
  778. Date.prototype.isSameDay = function(date) {
  779. return date.toDateString() === this.toDateString();
  780. };
  781. }
  782. /**
  783. * Judge the date is in same week as another date
  784. * @param {date} date
  785. * @return {Boolean}
  786. */
  787. if(!Date.prototype.isSameWeek) {
  788. Date.prototype.isSameWeek = function(date) {
  789. var weekStart = this.getLastWeekday();
  790. var weekEnd = weekStart.clone().addDays(7);
  791. return date >= weekStart && date < weekEnd;
  792. };
  793. }
  794. /**
  795. * Judge the date is in same year as another date
  796. * @param {date} date
  797. * @return {Boolean}
  798. */
  799. if(!Date.prototype.isSameYear) {
  800. Date.prototype.isSameYear = function(date) {
  801. return this.getFullYear() === date.getFullYear();
  802. };
  803. }
  804. }());
  805. /* ========================================================================
  806. * ZUI: string.js
  807. * http://zui.sexy
  808. * ========================================================================
  809. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  810. * ======================================================================== */
  811. (function() {
  812. 'use strict';
  813. if(!String.prototype.format) {
  814. String.prototype.format = function(args) {
  815. var result = this;
  816. if(arguments.length > 0) {
  817. var reg;
  818. if(arguments.length == 1 && typeof(args) == "object") {
  819. for(var key in args) {
  820. if(args[key] !== undefined) {
  821. reg = new RegExp("({" + key + "})", "g");
  822. result = result.replace(reg, args[key]);
  823. }
  824. }
  825. } else {
  826. for(var i = 0; i < arguments.length; i++) {
  827. if(arguments[i] !== undefined) {
  828. reg = new RegExp("({[" + i + "]})", "g");
  829. result = result.replace(reg, arguments[i]);
  830. }
  831. }
  832. }
  833. }
  834. return result;
  835. };
  836. }
  837. /**
  838. * Judge the string is a integer number
  839. *
  840. * @access public
  841. * @return bool
  842. */
  843. if(!String.prototype.isNum) {
  844. String.prototype.isNum = function(s) {
  845. if(s !== null) {
  846. var r, re;
  847. re = /\d*/i;
  848. r = s.match(re);
  849. return(r == s) ? true : false;
  850. }
  851. return false;
  852. };
  853. }
  854. })();
  855. /*!
  856. * jQuery resize event - v1.1 - 3/14/2010
  857. * http://benalman.com/projects/jquery-resize-plugin/
  858. *
  859. * Copyright (c) 2010 "Cowboy" Ben Alman
  860. * Dual licensed under the MIT and GPL licenses.
  861. * http://benalman.com/about/license/
  862. */
  863. // Script: jQuery resize event
  864. //
  865. // *Version: 1.1, Last updated: 3/14/2010*
  866. //
  867. // Project Home - http://benalman.com/projects/jquery-resize-plugin/
  868. // GitHub - http://github.com/cowboy/jquery-resize/
  869. // Source - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.js
  870. // (Minified) - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.min.js (1.0kb)
  871. //
  872. // About: License
  873. //
  874. // Copyright (c) 2010 "Cowboy" Ben Alman,
  875. // Dual licensed under the MIT and GPL licenses.
  876. // http://benalman.com/about/license/
  877. //
  878. // About: Examples
  879. //
  880. // This working example, complete with fully commented code, illustrates a few
  881. // ways in which this plugin can be used.
  882. //
  883. // resize event - http://benalman.com/code/projects/jquery-resize/examples/resize/
  884. //
  885. // About: Support and Testing
  886. //
  887. // Information about what version or versions of jQuery this plugin has been
  888. // tested with, what browsers it has been tested in, and where the unit tests
  889. // reside (so you can test it yourself).
  890. //
  891. // jQuery Versions - 1.3.2, 1.4.1, 1.4.2
  892. // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome, Opera 9.6-10.1.
  893. // Unit Tests - http://benalman.com/code/projects/jquery-resize/unit/
  894. //
  895. // About: Release History
  896. //
  897. // 1.1 - (3/14/2010) Fixed a minor bug that was causing the event to trigger
  898. // immediately after bind in some circumstances. Also changed $.fn.data
  899. // to $.data to improve performance.
  900. // 1.0 - (2/10/2010) Initial release
  901. (function($, window, undefined) {
  902. '$:nomunge'; // Used by YUI compressor.
  903. // A jQuery object containing all non-window elements to which the resize
  904. // event is bound.
  905. var elems = $([]),
  906. // Extend $.resize if it already exists, otherwise create it.
  907. jq_resize = $.resize = $.extend($.resize, {}),
  908. timeout_id,
  909. // Reused strings.
  910. str_setTimeout = 'setTimeout',
  911. str_resize = 'resize',
  912. str_data = str_resize + '-special-event',
  913. str_delay = 'delay',
  914. str_throttle = 'throttleWindow';
  915. // Property: jQuery.resize.delay
  916. //
  917. // The numeric interval (in milliseconds) at which the resize event polling
  918. // loop executes. Defaults to 250.
  919. jq_resize[str_delay] = 250;
  920. // Property: jQuery.resize.throttleWindow
  921. //
  922. // Throttle the native window object resize event to fire no more than once
  923. // every <jQuery.resize.delay> milliseconds. Defaults to true.
  924. //
  925. // Because the window object has its own resize event, it doesn't need to be
  926. // provided by this plugin, and its execution can be left entirely up to the
  927. // browser. However, since certain browsers fire the resize event continuously
  928. // while others do not, enabling this will throttle the window resize event,
  929. // making event behavior consistent across all elements in all browsers.
  930. //
  931. // While setting this property to false will disable window object resize
  932. // event throttling, please note that this property must be changed before any
  933. // window object resize event callbacks are bound.
  934. jq_resize[str_throttle] = true;
  935. // Event: resize event
  936. //
  937. // Fired when an element's width or height changes. Because browsers only
  938. // provide this event for the window element, for other elements a polling
  939. // loop is initialized, running every <jQuery.resize.delay> milliseconds
  940. // to see if elements' dimensions have changed. You may bind with either
  941. // .resize( fn ) or .bind( "resize", fn ), and unbind with .unbind( "resize" ).
  942. //
  943. // Usage:
  944. //
  945. // > jQuery('selector').bind( 'resize', function(e) {
  946. // > // element's width or height has changed!
  947. // > ...
  948. // > });
  949. //
  950. // Additional Notes:
  951. //
  952. // * The polling loop is not created until at least one callback is actually
  953. // bound to the 'resize' event, and this single polling loop is shared
  954. // across all elements.
  955. //
  956. // Double firing issue in jQuery 1.3.2:
  957. //
  958. // While this plugin works in jQuery 1.3.2, if an element's event callbacks
  959. // are manually triggered via .trigger( 'resize' ) or .resize() those
  960. // callbacks may double-fire, due to limitations in the jQuery 1.3.2 special
  961. // events system. This is not an issue when using jQuery 1.4+.
  962. //
  963. // > // While this works in jQuery 1.4+
  964. // > $(elem).css({ width: new_w, height: new_h }).resize();
  965. // >
  966. // > // In jQuery 1.3.2, you need to do this:
  967. // > var elem = $(elem);
  968. // > elem.css({ width: new_w, height: new_h });
  969. // > elem.data( 'resize-special-event', { width: elem.width(), height: elem.height() } );
  970. // > elem.resize();
  971. $.event.special[str_resize] = {
  972. // Called only when the first 'resize' event callback is bound per element.
  973. setup: function() {
  974. // Since window has its own native 'resize' event, return false so that
  975. // jQuery will bind the event using DOM methods. Since only 'window'
  976. // objects have a .setTimeout method, this should be a sufficient test.
  977. // Unless, of course, we're throttling the 'resize' event for window.
  978. if(!jq_resize[str_throttle] && this[str_setTimeout]) {
  979. return false;
  980. }
  981. var elem = $(this);
  982. // Add this element to the list of internal elements to monitor.
  983. elems = elems.add(elem);
  984. // Initialize data store on the element.
  985. $.data(this, str_data, {
  986. w: elem.width(),
  987. h: elem.height()
  988. });
  989. // If this is the first element added, start the polling loop.
  990. if(elems.length === 1) {
  991. loopy();
  992. }
  993. },
  994. // Called only when the last 'resize' event callback is unbound per element.
  995. teardown: function() {
  996. // Since window has its own native 'resize' event, return false so that
  997. // jQuery will unbind the event using DOM methods. Since only 'window'
  998. // objects have a .setTimeout method, this should be a sufficient test.
  999. // Unless, of course, we're throttling the 'resize' event for window.
  1000. if(!jq_resize[str_throttle] && this[str_setTimeout]) {
  1001. return false;
  1002. }
  1003. var elem = $(this);
  1004. // Remove this element from the list of internal elements to monitor.
  1005. elems = elems.not(elem);
  1006. // Remove any data stored on the element.
  1007. elem.removeData(str_data);
  1008. // If this is the last element removed, stop the polling loop.
  1009. if(!elems.length) {
  1010. clearTimeout(timeout_id);
  1011. }
  1012. },
  1013. // Called every time a 'resize' event callback is bound per element (new in
  1014. // jQuery 1.4).
  1015. add: function(handleObj) {
  1016. // Since window has its own native 'resize' event, return false so that
  1017. // jQuery doesn't modify the event object. Unless, of course, we're
  1018. // throttling the 'resize' event for window.
  1019. if(!jq_resize[str_throttle] && this[str_setTimeout]) {
  1020. return false;
  1021. }
  1022. var old_handler;
  1023. // The new_handler function is executed every time the event is triggered.
  1024. // This is used to update the internal element data store with the width
  1025. // and height when the event is triggered manually, to avoid double-firing
  1026. // of the event callback. See the "Double firing issue in jQuery 1.3.2"
  1027. // comments above for more information.
  1028. function new_handler(e, w, h) {
  1029. var elem = $(this),
  1030. data = $.data(this, str_data) || {};
  1031. // If called from the polling loop, w and h will be passed in as
  1032. // arguments. If called manually, via .trigger( 'resize' ) or .resize(),
  1033. // those values will need to be computed.
  1034. data.w = w !== undefined ? w : elem.width();
  1035. data.h = h !== undefined ? h : elem.height();
  1036. old_handler.apply(this, arguments);
  1037. };
  1038. // This may seem a little complicated, but it normalizes the special event
  1039. // .add method between jQuery 1.4/1.4.1 and 1.4.2+
  1040. if($.isFunction(handleObj)) {
  1041. // 1.4, 1.4.1
  1042. old_handler = handleObj;
  1043. return new_handler;
  1044. } else {
  1045. // 1.4.2+
  1046. old_handler = handleObj.handler;
  1047. handleObj.handler = new_handler;
  1048. }
  1049. }
  1050. };
  1051. function loopy() {
  1052. // Start the polling loop, asynchronously.
  1053. timeout_id = window[str_setTimeout](function() {
  1054. // Iterate over all elements to which the 'resize' event is bound.
  1055. elems.each(function() {
  1056. var elem = $(this),
  1057. width = elem.width(),
  1058. height = elem.height(),
  1059. data = $.data(this, str_data);
  1060. // If element size has changed since the last time, update the element
  1061. // data store and trigger the 'resize' event.
  1062. if(width !== data.w || height !== data.h) {
  1063. elem.trigger(str_resize, [data.w = width, data.h = height]);
  1064. }
  1065. });
  1066. // Loop.
  1067. loopy();
  1068. }, jq_resize[str_delay]);
  1069. };
  1070. })(jQuery, this);
  1071. /* ========================================================================
  1072. * Bootstrap: scrollspy.js v3.0.3
  1073. * http://getbootstrap.com/javascript/#scrollspy
  1074. * ========================================================================
  1075. * Copyright 2011-2014 Twitter, Inc.
  1076. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1077. * ======================================================================== */
  1078. + function($) {
  1079. 'use strict';
  1080. // SCROLLSPY CLASS DEFINITION
  1081. // ==========================
  1082. var zuiname = 'zui.scrollspy'
  1083. function ScrollSpy(element, options) {
  1084. var href
  1085. var process = $.proxy(this.process, this)
  1086. this.$element = $(element).is('body') ? $(window) : $(element)
  1087. this.$body = $('body')
  1088. this.$scrollElement = this.$element.on('scroll.' + zuiname + '.data-api', process)
  1089. this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
  1090. if(!this.selector) this.selector = (this.options.target || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
  1091. || '') + ' .nav li > a'
  1092. this.offsets = $([])
  1093. this.targets = $([])
  1094. this.activeTarget = null
  1095. this.refresh()
  1096. this.process()
  1097. }
  1098. ScrollSpy.DEFAULTS = {
  1099. offset: 10
  1100. }
  1101. ScrollSpy.prototype.refresh = function() {
  1102. var offsetMethod = this.$element[0] == window ? 'offset' : 'position'
  1103. this.offsets = $([])
  1104. this.targets = $([])
  1105. var self = this
  1106. var $targets = this.$body
  1107. .find(this.selector)
  1108. .map(function() {
  1109. var $el = $(this)
  1110. var href = $el.data('target') || $el.attr('href')
  1111. var $href = /^#./.test(href) && $(href)
  1112. return($href && $href.length && $href.is(':visible') && [
  1113. [$href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href]
  1114. ]) || null
  1115. })
  1116. .sort(function(a, b) {
  1117. return a[0] - b[0]
  1118. })
  1119. .each(function() {
  1120. self.offsets.push(this[0])
  1121. self.targets.push(this[1])
  1122. })
  1123. }
  1124. ScrollSpy.prototype.process = function() {
  1125. var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
  1126. var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
  1127. var maxScroll = scrollHeight - this.$scrollElement.height()
  1128. var offsets = this.offsets
  1129. var targets = this.targets
  1130. var activeTarget = this.activeTarget
  1131. var i
  1132. if(scrollTop >= maxScroll) {
  1133. return activeTarget != (i = targets.last()[0]) && this.activate(i)
  1134. }
  1135. if(activeTarget && scrollTop <= offsets[0]) {
  1136. return activeTarget != (i = targets[0]) && this.activate(i)
  1137. }
  1138. for(i = offsets.length; i--;) {
  1139. activeTarget != targets[i] && scrollTop >= offsets[i] && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) && this.activate(targets[i])
  1140. }
  1141. }
  1142. ScrollSpy.prototype.activate = function(target) {
  1143. this.activeTarget = target
  1144. $(this.selector)
  1145. .parentsUntil(this.options.target, '.active')
  1146. .removeClass('active')
  1147. var selector = this.selector +
  1148. '[data-target="' + target + '"],' +
  1149. this.selector + '[href="' + target + '"]'
  1150. var active = $(selector)
  1151. .parents('li')
  1152. .addClass('active')
  1153. if(active.parent('.dropdown-menu').length) {
  1154. active = active
  1155. .closest('li.dropdown')
  1156. .addClass('active')
  1157. }
  1158. active.trigger('activate.' + zuiname)
  1159. }
  1160. // SCROLLSPY PLUGIN DEFINITION
  1161. // ===========================
  1162. var old = $.fn.scrollspy
  1163. $.fn.scrollspy = function(option) {
  1164. return this.each(function() {
  1165. var $this = $(this)
  1166. var data = $this.data(zuiname)
  1167. var options = typeof option == 'object' && option
  1168. if(!data) $this.data(zuiname, (data = new ScrollSpy(this, options)))
  1169. if(typeof option == 'string') data[option]()
  1170. })
  1171. }
  1172. $.fn.scrollspy.Constructor = ScrollSpy
  1173. // SCROLLSPY NO CONFLICT
  1174. // =====================
  1175. $.fn.scrollspy.noConflict = function() {
  1176. $.fn.scrollspy = old
  1177. return this
  1178. }
  1179. // SCROLLSPY DATA-API
  1180. // ==================
  1181. $(window).on('load', function() {
  1182. $('[data-spy="scroll"]').each(function() {
  1183. var $spy = $(this)
  1184. $spy.scrollspy($spy.data())
  1185. })
  1186. })
  1187. }(jQuery);
  1188. /* ========================================================================
  1189. * ZUI: storeb.js
  1190. * http://zui.sexy
  1191. * ========================================================================
  1192. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  1193. * ======================================================================== */
  1194. (function(window, $) {
  1195. 'use strict';
  1196. var lsName = 'localStorage';
  1197. var storage = window[lsName],
  1198. old = window.store,
  1199. pageName = 'page_' + window.location.pathname + window.location.search;
  1200. /* The Store object */
  1201. var Store = function() {
  1202. this.slience = true;
  1203. this.enable = (lsName in window) && window[lsName] && window[lsName].setItem;
  1204. this.storage = storage;
  1205. this.page = this.get(pageName, {});
  1206. };
  1207. /* Save page data */
  1208. Store.prototype.pageSave = function() {
  1209. if($.isEmptyObject(this.page)) {
  1210. this.remove(pageName);
  1211. } else {
  1212. var forDeletes = [],
  1213. i;
  1214. for(i in this.page) {
  1215. var val = this.page[i];
  1216. if(val === null)
  1217. forDeletes.push(i);
  1218. }
  1219. for(i = forDeletes.length - 1; i >= 0; i--) {
  1220. delete this.page[forDeletes[i]];
  1221. }
  1222. this.set(pageName, this.page);
  1223. }
  1224. };
  1225. /* Remove page data item */
  1226. Store.prototype.pageRemove = function(key) {
  1227. if(typeof this.page[key] != 'undefined') {
  1228. this.page[key] = null;
  1229. this.pageSave();
  1230. }
  1231. };
  1232. /* Clear page data */
  1233. Store.prototype.pageClear = function() {
  1234. this.page = {};
  1235. this.pageSave();
  1236. };
  1237. /* Get page data */
  1238. Store.prototype.pageGet = function(key, defaultValue) {
  1239. var val = this.page[key];
  1240. return(defaultValue !== undefined && (val === null || val === undefined)) ? defaultValue : val;
  1241. };
  1242. /* Set page data */
  1243. Store.prototype.pageSet = function(objOrKey, val) {
  1244. if($.isPlainObject(objOrKey)) {
  1245. $.extend(true, this.page, objOrKey);
  1246. } else {
  1247. this.page[this.serialize(objOrKey)] = val;
  1248. }
  1249. this.pageSave();
  1250. };
  1251. /* Check enable status */
  1252. Store.prototype.check = function() {
  1253. if(!this.enable) {
  1254. if(!this.slience) throw new Error('Browser not support localStorage or enable status been set true.');
  1255. }
  1256. return this.enable;
  1257. };
  1258. /* Get length */
  1259. Store.prototype.length = function() {
  1260. if(this.check()) {
  1261. return storage.getLength ? storage.getLength() : storage.length;
  1262. }
  1263. return 0;
  1264. };
  1265. /* Remove item with browser localstorage native method */
  1266. Store.prototype.removeItem = function(key) {
  1267. storage.removeItem(key);
  1268. return this;
  1269. };
  1270. /* Remove item with browser localstorage native method, same as removeItem */
  1271. Store.prototype.remove = function(key) {
  1272. return this.removeItem(key);
  1273. };
  1274. /* Get item value with browser localstorage native method, and without deserialize */
  1275. Store.prototype.getItem = function(key) {
  1276. return storage.getItem(key);
  1277. };
  1278. /* Get item value and deserialize it, if value is null and defaultValue been given then return defaultValue */
  1279. Store.prototype.get = function(key, defaultValue) {
  1280. var val = this.deserialize(this.getItem(key));
  1281. if(typeof val === 'undefined' || val === null) {
  1282. if(typeof defaultValue !== 'undefined') {
  1283. return defaultValue;
  1284. }
  1285. }
  1286. return val;
  1287. };
  1288. /* Get item key by index and deserialize it */
  1289. Store.prototype.key = function(index) {
  1290. return storage.key(index);
  1291. };
  1292. /* Set item value with browser localstorage native method, and without serialize filter */
  1293. Store.prototype.setItem = function(key, val) {
  1294. storage.setItem(key, val);
  1295. return this;
  1296. };
  1297. /* Set item value, serialize it if the given value is not an string */
  1298. Store.prototype.set = function(key, val) {
  1299. if(val === undefined) return this.remove(key);
  1300. this.setItem(key, this.serialize(val));
  1301. return this;
  1302. };
  1303. /* Clear all items with browser localstorage native method */
  1304. Store.prototype.clear = function() {
  1305. storage.clear();
  1306. return this;
  1307. };
  1308. /* Iterate all items with callback */
  1309. Store.prototype.forEach = function(callback) {
  1310. for(var i = storage.length - 1; i >= 0; i--) {
  1311. var key = storage.key(i);
  1312. callback(key, this.get(key));
  1313. }
  1314. return this;
  1315. };
  1316. /* Get all items and set value in an object. */
  1317. Store.prototype.getAll = function() {
  1318. var all = {};
  1319. this.forEach(function(key, val) {
  1320. all[key] = val;
  1321. });
  1322. return all;
  1323. };
  1324. /* Serialize value with JSON.stringify */
  1325. Store.prototype.serialize = function(value) {
  1326. if(typeof value === 'string') return value;
  1327. return JSON.stringify(value);
  1328. };
  1329. /* Deserialize value, with JSON.parse if the given value is not a string */
  1330. Store.prototype.deserialize = function(value) {
  1331. if(typeof value !== 'string') return undefined;
  1332. try {
  1333. return JSON.parse(value);
  1334. } catch(e) {
  1335. return value || undefined;
  1336. }
  1337. };
  1338. $.zui({
  1339. store: new Store()
  1340. });
  1341. }(window, jQuery));
  1342. /* ========================================================================
  1343. * ZUI: draggable.js
  1344. * http://zui.sexy
  1345. * ========================================================================
  1346. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  1347. * ======================================================================== */
  1348. (function($) {
  1349. 'use strict';
  1350. var Draggable = function(element, options) {
  1351. this.$ = $(element);
  1352. this.options = this.getOptions(options);
  1353. this.init();
  1354. };
  1355. Draggable.DEFAULTS = {
  1356. container: 'body',
  1357. move: true
  1358. };
  1359. Draggable.prototype.getOptions = function(options) {
  1360. options = $.extend({}, Draggable.DEFAULTS, this.$.data(), options);
  1361. return options;
  1362. };
  1363. Draggable.prototype.init = function() {
  1364. this.handleMouseEvents();
  1365. };
  1366. Draggable.prototype.handleMouseEvents = function() {
  1367. var $e = this.$,
  1368. BEFORE = 'before',
  1369. DRAG = 'drag',
  1370. FINISH = 'finish',
  1371. setting = this.options,
  1372. startPos, cPos, startOffset, mousePos, moved;
  1373. var mouseDown = function(event) {
  1374. if(setting.hasOwnProperty(BEFORE) && $.isFunction(setting[BEFORE])) {
  1375. var isSure = setting[BEFORE]({
  1376. event: event,
  1377. element: $e
  1378. });
  1379. if(isSure !== undefined && (!isSure)) return;
  1380. }
  1381. var $container = $(setting.container),
  1382. pos = $e.offset();
  1383. cPos = $container.offset();
  1384. startPos = {
  1385. x: event.pageX,
  1386. y: event.pageY
  1387. };
  1388. startOffset = {
  1389. x: event.pageX - pos.left + cPos.left,
  1390. y: event.pageY - pos.top + cPos.top
  1391. };
  1392. mousePos = $.extend({}, startPos);
  1393. moved = false;
  1394. $e.addClass('drag-ready');
  1395. $(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp);
  1396. event.preventDefault();
  1397. if(setting.stopPropagation) {
  1398. event.stopPropagation();
  1399. }
  1400. };
  1401. var mouseMove = function(event) {
  1402. moved = true;
  1403. var mX = event.pageX,
  1404. mY = event.pageY;
  1405. var dragPos = {
  1406. left: mX - startOffset.x,
  1407. top: mY - startOffset.y
  1408. };
  1409. $e.removeClass('drag-ready').addClass('dragging');
  1410. if(setting.move) {
  1411. $e.css(dragPos);
  1412. }
  1413. if(setting.hasOwnProperty(DRAG) && $.isFunction(setting[DRAG])) {
  1414. setting[DRAG]({
  1415. event: event,
  1416. element: $e,
  1417. startOffset: startOffset,
  1418. pos: dragPos,
  1419. offset: {
  1420. x: mX - startPos.x,
  1421. y: mY - startPos.y
  1422. },
  1423. smallOffset: {
  1424. x: mX - mousePos.x,
  1425. y: mY - mousePos.y
  1426. }
  1427. });
  1428. }
  1429. mousePos.x = mX;
  1430. mousePos.y = mY;
  1431. if(setting.stopPropagation) {
  1432. event.stopPropagation();
  1433. }
  1434. };
  1435. var mouseUp = function(event) {
  1436. $(document).unbind('mousemove', mouseMove).unbind('mouseup', mouseUp);
  1437. if(!moved) {
  1438. $e.removeClass('drag-ready');
  1439. return;
  1440. }
  1441. var endPos = {
  1442. left: event.pageX - startOffset.x,
  1443. top: event.pageY - startOffset.y
  1444. };
  1445. $e.removeClass('drag-ready').removeClass('dragging');
  1446. if(setting.move) {
  1447. $e.css(endPos);
  1448. }
  1449. if(setting.hasOwnProperty(FINISH) && $.isFunction(setting[FINISH])) {
  1450. setting[FINISH]({
  1451. event: event,
  1452. element: $e,
  1453. pos: endPos,
  1454. offset: {
  1455. x: event.pageX - startPos.x,
  1456. y: event.pageY - startPos.y
  1457. },
  1458. smallOffset: {
  1459. x: event.pageX - mousePos.x,
  1460. y: event.pageY - mousePos.y
  1461. }
  1462. });
  1463. }
  1464. event.preventDefault();
  1465. if(setting.stopPropagation) {
  1466. event.stopPropagation();
  1467. }
  1468. };
  1469. if(setting.handle) {
  1470. $e.on('mousedown', setting.handle, mouseDown);
  1471. } else {
  1472. $e.on('mousedown', mouseDown);
  1473. }
  1474. };
  1475. $.fn.draggable = function(option) {
  1476. return this.each(function() {
  1477. var $this = $(this);
  1478. var data = $this.data('zui.draggable');
  1479. var options = typeof option == 'object' && option;
  1480. if(!data) $this.data('zui.draggable', (data = new Draggable(this, options)));
  1481. if(typeof option == 'string') data[option]();
  1482. });
  1483. };
  1484. $.fn.draggable.Constructor = Draggable;
  1485. }(jQuery));
  1486. /* ========================================================================
  1487. * ZUI: droppable.js
  1488. * http://zui.sexy
  1489. * ========================================================================
  1490. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  1491. * ======================================================================== */
  1492. (function($, document, Math) {
  1493. 'use strict';
  1494. var Droppable = function(element, options) {
  1495. this.$ = $(element);
  1496. this.options = this.getOptions(options);
  1497. this.init();
  1498. };
  1499. Droppable.DEFAULTS = {
  1500. container: 'body',
  1501. // flex: false,
  1502. // nested: false,
  1503. deviation: 5,
  1504. sensorOffsetX: 0,
  1505. sensorOffsetY: 0
  1506. };
  1507. Droppable.prototype.getOptions = function(options) {
  1508. options = $.extend({}, Droppable.DEFAULTS, this.$.data(), options);
  1509. return options;
  1510. };
  1511. Droppable.prototype.callEvent = function(name, params) {
  1512. return $.zui.callEvent(this.options[name], params, this);
  1513. };
  1514. Droppable.prototype.init = function() {
  1515. this.handleMouseEvents();
  1516. };
  1517. Droppable.prototype.handleMouseEvents = function() {
  1518. var $e = this.$,
  1519. self = this,
  1520. setting = this.options,
  1521. BEFORE = 'before';
  1522. this.$triggerTarget = (setting.trigger ? ($.isFunction(setting.trigger) ? setting.trigger($e) : $e.find(setting.trigger)).first() : $e);
  1523. this.$triggerTarget.on('mousedown', function(event) {
  1524. if(setting.hasOwnProperty(BEFORE) && $.isFunction(setting[BEFORE])) {
  1525. var isSure = setting[BEFORE]({
  1526. event: event,
  1527. element: $e
  1528. });
  1529. if(isSure !== undefined && (!isSure)) return;
  1530. }
  1531. var $targets = $.isFunction(setting.target) ? setting.target($e) : $(setting.target),
  1532. target = null,
  1533. shadow = null,
  1534. $container = $(setting.container).first(),
  1535. isIn = false,
  1536. isSelf = true,
  1537. oldCssPosition,
  1538. startOffset = $e.offset(),
  1539. startMouseOffset = {
  1540. left: event.pageX,
  1541. top: event.pageY
  1542. };
  1543. var containerOffset = $container.offset();
  1544. var clickOffset = {
  1545. left: startMouseOffset.left - startOffset.left,
  1546. top: startMouseOffset.top - startOffset.top
  1547. };
  1548. var lastMouseOffset = {
  1549. left: startMouseOffset.left,
  1550. top: startMouseOffset.top
  1551. };
  1552. $e.addClass('drag-from');
  1553. $(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp);
  1554. event.preventDefault();
  1555. function mouseMove(event) {
  1556. var mouseOffset = {
  1557. left: event.pageX,
  1558. top: event.pageY
  1559. };
  1560. // ignore small move
  1561. if(Math.abs(mouseOffset.left - startMouseOffset.left) < setting.deviation && Math.abs(mouseOffset.top - startMouseOffset.top) < setting.deviation) return;
  1562. if(shadow === null) // create shadow
  1563. {
  1564. var cssPosition = $container.css('position');
  1565. if(cssPosition != 'absolute' && cssPosition != 'relative' && cssPosition != 'fixed') {
  1566. oldCssPosition = cssPosition;
  1567. $container.css('position', 'relative');
  1568. }
  1569. shadow = $e.clone().removeClass('drag-from').addClass('drag-shadow').css({
  1570. position: 'absolute',
  1571. width: $e.outerWidth(),
  1572. transition: 'none'
  1573. }).appendTo($container);
  1574. $e.addClass('dragging');
  1575. self.callEvent('start', {
  1576. event: event,
  1577. element: $e
  1578. });
  1579. }
  1580. var offset = {
  1581. left: mouseOffset.left - clickOffset.left,
  1582. top: mouseOffset.top - clickOffset.top
  1583. };
  1584. var position = {
  1585. left: offset.left - containerOffset.left,
  1586. top: offset.top - containerOffset.top
  1587. };
  1588. shadow.css(position);
  1589. lastMouseOffset.left = mouseOffset.left;
  1590. lastMouseOffset.top = mouseOffset.top;
  1591. var isNew = false;
  1592. isIn = false;
  1593. if(!setting.flex) {
  1594. $targets.removeClass('drop-to');
  1595. }
  1596. var newTarget = null;
  1597. $targets.each(function() {
  1598. var t = $(this);
  1599. var tPos = t.offset();
  1600. var tW = t.outerWidth(),
  1601. tH = t.outerHeight(),
  1602. tX = tPos.left + setting.sensorOffsetX,
  1603. tY = tPos.top + setting.sensorOffsetY;
  1604. if(mouseOffset.left > tX && mouseOffset.top > tY && mouseOffset.left < (tX + tW) && mouseOffset.top < (tY + tH)) {
  1605. if(newTarget) newTarget.removeClass('drop-to');
  1606. newTarget = t;
  1607. if(!setting.nested) return false;
  1608. }
  1609. });
  1610. if(newTarget) {
  1611. isIn = true;
  1612. var id = newTarget.data('id');
  1613. if($e.data('id') != id) isSelf = false;
  1614. if(target === null || (target.data('id') !== id && (!isSelf))) isNew = true;
  1615. target = newTarget;
  1616. if(setting.flex) {
  1617. $targets.removeClass('drop-to');
  1618. }
  1619. target.addClass('drop-to');
  1620. }
  1621. if(!setting.flex) {
  1622. $e.toggleClass('drop-in', isIn);
  1623. shadow.toggleClass('drop-in', isIn);
  1624. } else if(target !== null && target.length) {
  1625. isIn = true;
  1626. }
  1627. self.callEvent('drag', {
  1628. event: event,
  1629. isIn: isIn,
  1630. target: target,
  1631. element: $e,
  1632. isNew: isNew,
  1633. selfTarget: isSelf,
  1634. clickOffset: clickOffset,
  1635. offset: offset,
  1636. position: {
  1637. left: offset.left - containerOffset.left,
  1638. top: offset.top - containerOffset.top
  1639. },
  1640. mouseOffset: mouseOffset
  1641. });
  1642. event.preventDefault();
  1643. }
  1644. function mouseUp(event) {
  1645. if(oldCssPosition) {
  1646. $container.css('position', oldCssPosition);
  1647. }
  1648. if(shadow === null) {
  1649. $e.removeClass('drag-from');
  1650. $(document).unbind('mousemove', mouseMove).unbind('mouseup', mouseUp);
  1651. self.callEvent('always', {
  1652. event: event,
  1653. cancel: true
  1654. });
  1655. return;
  1656. }
  1657. if(!isIn) target = null;
  1658. var isSure = true,
  1659. mouseOffset = {
  1660. left: event.pageX,
  1661. top: event.pageY
  1662. };
  1663. var offset = {
  1664. left: mouseOffset.left - clickOffset.left,
  1665. top: mouseOffset.top - clickOffset.top
  1666. };
  1667. var moveOffset = {
  1668. left: mouseOffset.left - lastMouseOffset.left,
  1669. top: mouseOffset.top - lastMouseOffset.top
  1670. };
  1671. lastMouseOffset.left = mouseOffset.left;
  1672. lastMouseOffset.top = mouseOffset.top;
  1673. var eventOptions = {
  1674. event: event,
  1675. isIn: isIn,
  1676. target: target,
  1677. element: $e,
  1678. isNew: (!isSelf) && target !== null,
  1679. selfTarget: isSelf,
  1680. offset: offset,
  1681. mouseOffset: mouseOffset,
  1682. position: {
  1683. left: offset.left - containerOffset.left,
  1684. top: offset.top - containerOffset.top
  1685. },
  1686. lastMouseOffset: lastMouseOffset,
  1687. moveOffset: moveOffset
  1688. };
  1689. isSure = self.callEvent('beforeDrop', eventOptions);
  1690. if(isSure && isIn) {
  1691. self.callEvent('drop', eventOptions);
  1692. }
  1693. $(document).unbind('mousemove', mouseMove).unbind('mouseup', mouseUp);
  1694. $targets.removeClass('drop-to');
  1695. $e.removeClass('dragging').removeClass('drag-from');
  1696. shadow.remove();
  1697. self.callEvent('finish', eventOptions);
  1698. self.callEvent('always', eventOptions);
  1699. event.preventDefault();
  1700. }
  1701. });
  1702. };
  1703. Droppable.prototype.reset = function() {
  1704. this.$triggerTarget.off('mousedown');
  1705. this.handleMouseEvents();
  1706. };
  1707. $.fn.droppable = function(option) {
  1708. return this.each(function() {
  1709. var $this = $(this);
  1710. var data = $this.data('zui.droppable');
  1711. var options = typeof option == 'object' && option;
  1712. if(!data) $this.data('zui.droppable', (data = new Droppable(this, options)));
  1713. if(typeof option == 'string') data[option]();
  1714. });
  1715. };
  1716. $.fn.droppable.Constructor = Droppable;
  1717. }(jQuery, document, Math));
  1718. /* ========================================================================
  1719. * ZUI: sortable.js
  1720. * http://zui.sexy
  1721. * ========================================================================
  1722. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  1723. * ======================================================================== */
  1724. + function($, window, document, Math) {
  1725. 'use strict';
  1726. var Sortable = function(element, options) {
  1727. this.$ = $(element);
  1728. this.options = this.getOptions(options);
  1729. this.init();
  1730. };
  1731. Sortable.DEFAULTS = {
  1732. selector: 'li, div',
  1733. dragCssClass: 'invisible'
  1734. }; // default options
  1735. Sortable.prototype.getOptions = function(options) {
  1736. options = $.extend({}, Sortable.DEFAULTS, this.$.data(), options);
  1737. return options;
  1738. };
  1739. Sortable.prototype.init = function() {
  1740. this.bindEventToList(this.$.children(this.options.selector));
  1741. };
  1742. Sortable.prototype.reset = function() {
  1743. var that = this,
  1744. order = 0;
  1745. var $list = this.$.children(this.options.selector).not('.drag-shadow');
  1746. $list.each(function() {
  1747. var $this = $(this);
  1748. if($this.data('zui.droppable')) {
  1749. $this.data('zui.droppable').options.target = $list;
  1750. $this.droppable('reset');
  1751. } else {
  1752. that.bindEventToList($list);
  1753. return false;
  1754. }
  1755. });
  1756. };
  1757. Sortable.prototype.bindEventToList = function($list) {
  1758. var self = this.$,
  1759. options = this.options;
  1760. var isReverse = options.reverse;
  1761. markOrders($list);
  1762. $list.droppable({
  1763. trigger: options.trigger,
  1764. target: self.children(options.selector),
  1765. container: self,
  1766. always: options.always,
  1767. flex: true,
  1768. before: options.before,
  1769. start: function(e) {
  1770. if(options.dragCssClass) e.element.addClass(options.dragCssClass);
  1771. $.zui.callEvent(options['start']);
  1772. },
  1773. drag: function(e) {
  1774. self.addClass('sortable-sorting');
  1775. if(e.isIn) {
  1776. var $ele = e.element,
  1777. $target = e.target;
  1778. var eleOrder = $ele.attr('data-order'),
  1779. targetOrder = $target.attr('data-order');
  1780. if(eleOrder == targetOrder) return;
  1781. else if(eleOrder > targetOrder) {
  1782. $target[isReverse ? 'after' : 'before']($ele);
  1783. } else {
  1784. $target[isReverse ? 'before' : 'after']($ele);
  1785. }
  1786. var list = self.children(options.selector).not('.drag-shadow');
  1787. markOrders(list);
  1788. $.zui.callEvent(options['order'], {
  1789. list: list,
  1790. element: $ele
  1791. });
  1792. }
  1793. },
  1794. finish: function(e) {
  1795. if(options.dragCssClass && e.element) e.element.removeClass(options.dragCssClass);
  1796. $.zui.callEvent(options['finish'], {
  1797. list: self.children(options.selector),
  1798. element: e.element
  1799. });
  1800. self.removeClass('sortable-sorting');
  1801. }
  1802. });
  1803. function markOrders(list) {
  1804. var orders = [];
  1805. list.each(function() {
  1806. var thisOrder = $(this).data('order');
  1807. if(typeof thisOrder === 'number') {
  1808. orders.push(thisOrder);
  1809. }
  1810. });
  1811. orders.sort(function(a, b) {
  1812. return a - b;
  1813. });
  1814. var listSize = list.length;
  1815. while(orders.length < listSize) {
  1816. orders.push(orders.length ? (orders[orders.length - 1] + 1) : 0);
  1817. }
  1818. if(isReverse) {
  1819. orders.reverse();
  1820. }
  1821. var listIndex = 0
  1822. list.each(function() {
  1823. $(this).attr('data-order', orders[listIndex++]);
  1824. });
  1825. }
  1826. };
  1827. $.fn.sortable = function(option) {
  1828. return this.each(function() {
  1829. var $this = $(this);
  1830. var data = $this.data('zui.sortable');
  1831. var options = typeof option == 'object' && option;
  1832. if(!data) $this.data('zui.sortable', (data = new Sortable(this, options)));
  1833. else if(typeof option == 'object') data.reset();
  1834. if(typeof option == 'string') data[option]();
  1835. })
  1836. };
  1837. $.fn.sortable.Constructor = Sortable;
  1838. }(jQuery, window, document, Math);
  1839. /* ========================================================================
  1840. * Bootstrap: modal.js v3.2.0
  1841. * http://getbootstrap.com/javascript/#modals
  1842. * ========================================================================
  1843. * Copyright 2011-2014 Twitter, Inc.
  1844. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1845. * ========================================================================
  1846. * Updates in ZUI:
  1847. * 1. changed event namespace to *.zui.modal
  1848. * 2. added position option to ajust poisition of modal
  1849. * 3. added event 'escaping.zui.modal' with an param 'esc' to judge the esc
  1850. * key down
  1851. * 4. get moveable options value from '.modal-moveable' on '.modal-dialog'
  1852. * 5. add setMoveable method to make modal dialog moveable
  1853. * ======================================================================== */
  1854. + function($) {
  1855. 'use strict';
  1856. // MODAL CLASS DEFINITION
  1857. // ======================
  1858. var zuiname = 'zui.modal'
  1859. var Modal = function(element, options) {
  1860. this.options = options
  1861. this.$body = $(document.body)
  1862. this.$element = $(element)
  1863. this.$backdrop =
  1864. this.isShown = null
  1865. this.scrollbarWidth = 0
  1866. if(typeof this.options.moveable === 'undefined') {
  1867. this.options.moveable = this.$element.hasClass('modal-moveable');
  1868. }
  1869. if(this.options.remote) {
  1870. this.$element
  1871. .find('.modal-content')
  1872. .load(this.options.remote, $.proxy(function() {
  1873. this.$element.trigger('loaded.' + zuiname)
  1874. }, this))
  1875. }
  1876. }
  1877. Modal.VERSION = '3.2.0'
  1878. Modal.TRANSITION_DURATION = 300
  1879. Modal.BACKDROP_TRANSITION_DURATION = 150
  1880. Modal.DEFAULTS = {
  1881. backdrop: true,
  1882. keyboard: true,
  1883. show: true,
  1884. // rememberPos: false,
  1885. // moveable: false,
  1886. position: 'fit' // 'center' or '40px' or '10%'
  1887. }
  1888. Modal.prototype.toggle = function(_relatedTarget, position) {
  1889. return this.isShown ? this.hide() : this.show(_relatedTarget, position)
  1890. }
  1891. Modal.prototype.ajustPosition = function(position) {
  1892. if(typeof position === 'undefined') position = this.options.position;
  1893. if(typeof position === 'undefined') return;
  1894. var $dialog = this.$element.find('.modal-dialog');
  1895. // if($dialog.hasClass('modal-dragged')) return;
  1896. var half = Math.max(0, ($(window).height() - $dialog.outerHeight()) / 2);
  1897. var topPos = position == 'fit' ? (half * 2 / 3) : (position == 'center' ? half : position);
  1898. if($dialog.hasClass('modal-moveable')) {
  1899. var pos = null;
  1900. if(this.options.rememberPos) {
  1901. if(this.options.rememberPos === true) {
  1902. pos = this.$element.data('modal-pos');
  1903. } else if($.zui.store) {
  1904. pos = $.zui.store.pageGet(zuiname + '.rememberPos');
  1905. }
  1906. }
  1907. if(!pos) {
  1908. pos = {
  1909. left: Math.max(0, ($(window).width() - $dialog.outerWidth()) / 2),
  1910. top: topPos
  1911. };
  1912. }
  1913. $dialog.css(pos);
  1914. } else {
  1915. $dialog.css('margin-top', topPos);
  1916. }
  1917. }
  1918. Modal.prototype.setMoveale = function() {
  1919. var that = this;
  1920. var options = that.options;
  1921. var $dialog = that.$element.find('.modal-dialog').removeClass('modal-dragged');
  1922. $dialog.toggleClass('modal-moveable', options.moveable);
  1923. if(!that.$element.data('modal-moveable-setup')) {
  1924. $dialog.draggable({
  1925. container: that.$element,
  1926. handle: '.modal-header',
  1927. before: function() {
  1928. $dialog.css('margin-top', '').addClass('modal-dragged');
  1929. },
  1930. finish: function(e) {
  1931. if(options.rememberPos) {
  1932. that.$element.data('modal-pos', e.pos);
  1933. if($.zui.store && options.rememberPos !== true) {
  1934. $.zui.store.pageSet(zuiname + '.rememberPos', e.pos);
  1935. }
  1936. }
  1937. }
  1938. });
  1939. }
  1940. }
  1941. Modal.prototype.show = function(_relatedTarget, position) {
  1942. var that = this
  1943. var e = $.Event('show.' + zuiname, {
  1944. relatedTarget: _relatedTarget
  1945. })
  1946. that.$element.trigger(e)
  1947. if(that.isShown || e.isDefaultPrevented()) return
  1948. that.isShown = true
  1949. if(that.options.moveable) that.setMoveale();
  1950. that.checkScrollbar()
  1951. that.$body.addClass('modal-open')
  1952. that.setScrollbar()
  1953. that.escape()
  1954. that.$element.on('click.dismiss.' + zuiname, '[data-dismiss="modal"]', $.proxy(that.hide, that))
  1955. that.backdrop(function() {
  1956. var transition = $.support.transition && that.$element.hasClass('fade')
  1957. if(!that.$element.parent().length) {
  1958. that.$element.appendTo(that.$body) // don't move modals dom position
  1959. }
  1960. that.$element
  1961. .show()
  1962. .scrollTop(0)
  1963. if(transition) {
  1964. that.$element[0].offsetWidth // force reflow
  1965. }
  1966. that.$element
  1967. .addClass('in')
  1968. .attr('aria-hidden', false)
  1969. that.ajustPosition(position);
  1970. that.enforceFocus()
  1971. var e = $.Event('shown.' + zuiname, {
  1972. relatedTarget: _relatedTarget
  1973. })
  1974. transition ?
  1975. that.$element.find('.modal-dialog') // wait for modal to slide in
  1976. .one('bsTransitionEnd', function() {
  1977. that.$element.trigger('focus').trigger(e)
  1978. })
  1979. .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  1980. that.$element.trigger('focus').trigger(e)
  1981. })
  1982. }
  1983. Modal.prototype.hide = function(e) {
  1984. if(e) e.preventDefault()
  1985. e = $.Event('hide.' + zuiname)
  1986. this.$element.trigger(e)
  1987. if(!this.isShown || e.isDefaultPrevented()) return
  1988. this.isShown = false
  1989. this.$body.removeClass('modal-open')
  1990. this.resetScrollbar()
  1991. this.escape()
  1992. $(document).off('focusin.' + zuiname)
  1993. this.$element
  1994. .removeClass('in')
  1995. .attr('aria-hidden', true)
  1996. .off('click.dismiss.' + zuiname)
  1997. $.support.transition && this.$element.hasClass('fade') ?
  1998. this.$element
  1999. .one('bsTransitionEnd', $.proxy(this.hideModal, this))
  2000. .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  2001. this.hideModal()
  2002. }
  2003. Modal.prototype.enforceFocus = function() {
  2004. $(document)
  2005. .off('focusin.' + zuiname) // guard against infinite focus loop
  2006. .on('focusin.' + zuiname, $.proxy(function(e) {
  2007. if(this.$element[0] !== e.target && !this.$element.has(e.target).length) {
  2008. this.$element.trigger('focus')
  2009. }
  2010. }, this))
  2011. }
  2012. Modal.prototype.escape = function() {
  2013. if(this.isShown && this.options.keyboard) {
  2014. $(document).on('keydown.dismiss.' + zuiname, $.proxy(function(e) {
  2015. if(e.which == 27) {
  2016. var et = $.Event('escaping.' + zuiname)
  2017. var result = this.$element.triggerHandler(et, 'esc')
  2018. if(result != undefined && (!result)) return
  2019. this.hide()
  2020. }
  2021. }, this))
  2022. } else if(!this.isShown) {
  2023. $(document).off('keydown.dismiss.' + zuiname)
  2024. }
  2025. }
  2026. Modal.prototype.hideModal = function() {
  2027. var that = this
  2028. this.$element.hide()
  2029. this.backdrop(function() {
  2030. that.$element.trigger('hidden.' + zuiname)
  2031. })
  2032. }
  2033. Modal.prototype.removeBackdrop = function() {
  2034. this.$backdrop && this.$backdrop.remove()
  2035. this.$backdrop = null
  2036. }
  2037. Modal.prototype.backdrop = function(callback) {
  2038. var that = this
  2039. var animate = this.$element.hasClass('fade') ? 'fade' : ''
  2040. if(this.isShown && this.options.backdrop) {
  2041. var doAnimate = $.support.transition && animate
  2042. this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
  2043. .appendTo(this.$body)
  2044. this.$element.on('mousedown.dismiss.' + zuiname, $.proxy(function(e) {
  2045. if(e.target !== e.currentTarget) return
  2046. this.options.backdrop == 'static' ? this.$element[0].focus.call(this.$element[0]) : this.hide.call(this)
  2047. }, this))
  2048. if(doAnimate) this.$backdrop[0].offsetWidth // force reflow
  2049. this.$backdrop.addClass('in')
  2050. if(!callback) return
  2051. doAnimate ?
  2052. this.$backdrop
  2053. .one('bsTransitionEnd', callback)
  2054. .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  2055. callback()
  2056. } else if(!this.isShown && this.$backdrop) {
  2057. this.$backdrop.removeClass('in')
  2058. var callbackRemove = function() {
  2059. that.removeBackdrop()
  2060. callback && callback()
  2061. }
  2062. $.support.transition && this.$element.hasClass('fade') ?
  2063. this.$backdrop
  2064. .one('bsTransitionEnd', callbackRemove)
  2065. .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  2066. callbackRemove()
  2067. } else if(callback) {
  2068. callback()
  2069. }
  2070. }
  2071. Modal.prototype.checkScrollbar = function() {
  2072. if(document.body.clientWidth >= window.innerWidth) return
  2073. this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
  2074. }
  2075. Modal.prototype.setScrollbar = function() {
  2076. var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
  2077. if(this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
  2078. }
  2079. Modal.prototype.resetScrollbar = function() {
  2080. this.$body.css('padding-right', '')
  2081. }
  2082. Modal.prototype.measureScrollbar = function() { // thx walsh
  2083. var scrollDiv = document.createElement('div')
  2084. scrollDiv.className = 'modal-scrollbar-measure'
  2085. this.$body.append(scrollDiv)
  2086. var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
  2087. this.$body[0].removeChild(scrollDiv)
  2088. return scrollbarWidth
  2089. }
  2090. // MODAL PLUGIN DEFINITION
  2091. // =======================
  2092. function Plugin(option, _relatedTarget, position) {
  2093. return this.each(function() {
  2094. var $this = $(this)
  2095. var data = $this.data(zuiname)
  2096. var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
  2097. if(!data) $this.data(zuiname, (data = new Modal(this, options)))
  2098. if(typeof option == 'string') data[option](_relatedTarget, position)
  2099. else if(options.show) data.show(_relatedTarget, position)
  2100. })
  2101. }
  2102. var old = $.fn.modal
  2103. $.fn.modal = Plugin
  2104. $.fn.modal.Constructor = Modal
  2105. // MODAL NO CONFLICT
  2106. // =================
  2107. $.fn.modal.noConflict = function() {
  2108. $.fn.modal = old
  2109. return this
  2110. }
  2111. // MODAL DATA-API
  2112. // ==============
  2113. $(document).on('click.' + zuiname + '.data-api', '[data-toggle="modal"]', function(e) {
  2114. var $this = $(this)
  2115. var href = $this.attr('href')
  2116. var $target = null
  2117. try {
  2118. // strip for ie7
  2119. $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, '')));
  2120. } catch(ex) {
  2121. return
  2122. }
  2123. if(!$target.length) return;
  2124. var option = $target.data(zuiname) ? 'toggle' : $.extend({
  2125. remote: !/#/.test(href) && href
  2126. }, $target.data(), $this.data())
  2127. if($this.is('a')) e.preventDefault()
  2128. $target.one('show.' + zuiname, function(showEvent) {
  2129. // only register focus restorer if modal will actually get shown
  2130. if(showEvent.isDefaultPrevented()) return
  2131. $target.one('hidden.' + zuiname, function() {
  2132. $this.is(':visible') && $this.trigger('focus')
  2133. })
  2134. })
  2135. Plugin.call($target, option, this, $this.data('position'))
  2136. })
  2137. }(jQuery);
  2138. /* ========================================================================
  2139. * ZUI: modal.trigger.js v1.2.0
  2140. * http://zui.sexy/docs/javascript.html#modals
  2141. * Licensed under MIT
  2142. * ======================================================================== */
  2143. (function($, window) {
  2144. 'use strict';
  2145. if(!$.fn.modal) throw new Error('Modal trigger requires modal.js');
  2146. var NAME = 'zui.modaltrigger',
  2147. STR_AJAX = 'ajax',
  2148. ZUI_MODAL = '.zui.modal',
  2149. STR_STRING = 'string';
  2150. // MODAL TRIGGER CLASS DEFINITION
  2151. // ======================
  2152. var ModalTrigger = function(options, $trigger) {
  2153. options = $.extend({}, ModalTrigger.DEFAULTS, $.ModalTriggerDefaults, $trigger ? $trigger.data() : null, options);
  2154. this.isShown;
  2155. this.$trigger = $trigger;
  2156. this.options = options;
  2157. this.id = $.zui.uuid();
  2158. // todo: handle when: options.show = true
  2159. };
  2160. ModalTrigger.DEFAULTS = {
  2161. type: 'custom',
  2162. // width: null, // number, css definition
  2163. // size: null, // 'md', 'sm', 'lg', 'fullscreen'
  2164. height: 'auto',
  2165. // icon: null,
  2166. name: 'triggerModal',
  2167. fade: true,
  2168. position: 'fit',
  2169. showHeader: true,
  2170. delay: 0,
  2171. // iframeBodyClass: '',
  2172. // onlyIncreaseHeight: false,
  2173. // moveable: false,
  2174. // rememberPos: false,
  2175. backdrop: true,
  2176. keyboard: true,
  2177. waittime: 0,
  2178. loadingIcon: 'icon-spinner-indicator'
  2179. };
  2180. ModalTrigger.prototype.init = function(options) {
  2181. var that = this;
  2182. if(options.url) {
  2183. if(!options.type || (options.type != STR_AJAX && options.type != 'iframe')) {
  2184. options.type = STR_AJAX;
  2185. }
  2186. }
  2187. if(options.remote) {
  2188. options.type = STR_AJAX;
  2189. if(typeof options.remote === STR_STRING) options.url = options.remote;
  2190. } else if(options.iframe) {
  2191. options.type = 'iframe';
  2192. if(typeof options.iframe === STR_STRING) options.url = options.iframe;
  2193. } else if(options.custom) {
  2194. options.type = 'custom';
  2195. if(typeof options.custom === STR_STRING) {
  2196. var $doms;
  2197. try {
  2198. $doms = $(options.custom);
  2199. } catch(e) {}
  2200. if($doms && $doms.length) {
  2201. options.custom = $doms;
  2202. } else if($.isFunction(window[options.custom])) {
  2203. options.custom = window[options.custom];
  2204. }
  2205. }
  2206. }
  2207. var $modal = $('#' + options.name);
  2208. if($modal.length) {
  2209. if(!that.isShown) $modal.off(ZUI_MODAL);
  2210. $modal.remove();
  2211. }
  2212. $modal = $('<div id="' + options.name + '" class="modal modal-trigger">' + (typeof options.loadingIcon === 'string' && options.loadingIcon.indexOf('icon-') === 0 ? ('<div class="icon icon-spin loader ' + options.loadingIcon + '"></div>') : options.loadingIcon) + '<div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button class="close" data-dismiss="modal">×</button><h4 class="modal-title"><i class="modal-icon"></i> <span class="modal-title-name"></span></h4></div><div class="modal-body"></div></div></div></div>').appendTo('body').data(NAME, that);
  2213. var bindEvent = function(optonName, eventName) {
  2214. var handleFunc = options[optonName];
  2215. if($.isFunction(handleFunc)) $modal.on(eventName + ZUI_MODAL, handleFunc);
  2216. };
  2217. bindEvent('onShow', 'show');
  2218. bindEvent('shown', 'shown');
  2219. bindEvent('onHide', 'hide');
  2220. bindEvent('hidden', 'hidden');
  2221. bindEvent('loaded', 'loaded');
  2222. $modal.on('shown' + ZUI_MODAL, function() {
  2223. that.isShown = true;
  2224. }).on('hidden' + ZUI_MODAL, function() {
  2225. that.isShown = false;
  2226. });
  2227. this.$modal = $modal;
  2228. this.$dialog = $modal.find('.modal-dialog');
  2229. if(options.mergeOptions) this.options = options;
  2230. };
  2231. ModalTrigger.prototype.show = function(option) {
  2232. var options = $.extend({}, this.options, {url: this.$trigger ? (this.$trigger.attr('href') || this.$trigger.attr('data-url') || this.$trigger.data('url')) : this.options.url}, option);
  2233. this.init(options);
  2234. var that = this,
  2235. $modal = this.$modal,
  2236. $dialog = this.$dialog,
  2237. custom = options.custom;
  2238. var $body = $dialog.find('.modal-body').css('padding', ''),
  2239. $header = $dialog.find('.modal-header'),
  2240. $content = $dialog.find('.modal-content');
  2241. $modal.toggleClass('fade', options.fade)
  2242. .addClass(options.cssClass)
  2243. .toggleClass('modal-loading', !this.isShown);
  2244. $dialog.toggleClass('modal-md', options.size === 'md')
  2245. .toggleClass('modal-sm', options.size === 'sm')
  2246. .toggleClass('modal-lg', options.size === 'lg')
  2247. .toggleClass('modal-fullscreen', options.size === 'fullscreen');
  2248. $header.toggle(options.showHeader);
  2249. $header.find('.modal-icon').attr('class', 'modal-icon icon-' + options.icon);
  2250. $header.find('.modal-title-name').html(options.title || '');
  2251. if(options.size && options.size === 'fullscreen') {
  2252. options.width = '';
  2253. options.height = '';
  2254. }
  2255. var resizeDialog = function() {
  2256. clearTimeout(this.resizeTask);
  2257. this.resizeTask = setTimeout(function() {
  2258. that.ajustPosition();
  2259. }, 100);
  2260. };
  2261. var readyToShow = function(delay, callback) {
  2262. if(typeof delay === 'undefined') delay = options.delay;
  2263. return setTimeout(function() {
  2264. $dialog = $modal.find('.modal-dialog');
  2265. if(options.width && options.width != 'auto') {
  2266. $dialog.css('width', options.width);
  2267. }
  2268. if(options.height && options.height != 'auto') {
  2269. $dialog.css('height', options.height);
  2270. if(options.type === 'iframe') $body.css('height', $dialog.height() - $header.outerHeight());
  2271. }
  2272. that.ajustPosition(options.position);
  2273. $modal.removeClass('modal-loading');
  2274. if(options.type != 'iframe') {
  2275. $dialog.off('resize.' + NAME).on('resize.' + NAME, resizeDialog);
  2276. }
  2277. callback && callback();
  2278. }, delay);
  2279. };
  2280. if(options.type === 'custom' && custom) {
  2281. if($.isFunction(custom)) {
  2282. var customContent = custom({
  2283. modal: $modal,
  2284. options: options,
  2285. modalTrigger: that,
  2286. ready: readyToShow
  2287. });
  2288. if(typeof customContent === STR_STRING) {
  2289. $body.html(customContent);
  2290. readyToShow();
  2291. }
  2292. } else if(custom instanceof $) {
  2293. $body.html($('<div>').append(custom.clone()).html());
  2294. readyToShow();
  2295. } else {
  2296. $body.html(custom);
  2297. readyToShow();
  2298. }
  2299. } else if(options.url) {
  2300. var onLoadBroken = function() {
  2301. var brokenContent = $modal.callEvent('broken' + ZUI_MODAL, that, that);
  2302. if(brokenContent) {
  2303. $body.html(brokenContent);
  2304. }
  2305. };
  2306. $modal.attr('ref', options.url);
  2307. if(options.type === 'iframe') {
  2308. $modal.addClass('modal-iframe');
  2309. this.firstLoad = true;
  2310. var iframeName = 'iframe-' + options.name;
  2311. $header.detach();
  2312. $body.detach();
  2313. $content.empty().append($header).append($body);
  2314. $body.css('padding', 0)
  2315. .html('<iframe id="' + iframeName + '" name="' + iframeName + '" src="' + options.url + '" frameborder="no" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" allowtransparency="true" scrolling="auto" style="width: 100%; height: 100%; left: 0px;"></iframe>');
  2316. if(options.waittime > 0) {
  2317. that.waitTimeout = readyToShow(options.waittime, onLoadBroken);
  2318. }
  2319. var frame = document.getElementById(iframeName);
  2320. frame.onload = frame.onreadystatechange = function() {
  2321. if(that.firstLoad) $modal.addClass('modal-loading');
  2322. if(this.readyState && this.readyState != 'complete') return;
  2323. that.firstLoad = false;
  2324. if(options.waittime > 0) {
  2325. clearTimeout(that.waitTimeout);
  2326. }
  2327. try {
  2328. $modal.attr('ref', frame.contentWindow.location.href);
  2329. var frame$ = window.frames[iframeName].$;
  2330. if(frame$ && options.height === 'auto' && options.size != 'fullscreen') {
  2331. // todo: update iframe url to ref attribute
  2332. var $framebody = frame$('body').addClass('body-modal');
  2333. if(options.iframeBodyClass) $framebody.addClass(options.iframeBodyClass);
  2334. var ajustFrameSize = function(check) {
  2335. $modal.removeClass('fade');
  2336. var height = $framebody.outerHeight();
  2337. if(check === true && options.onlyIncreaseHeight) {
  2338. height = Math.max(height, $body.data('minModalHeight') || 0);
  2339. $body.data('minModalHeight', height);
  2340. }
  2341. $body.css('height', height);
  2342. if(options.fade) $modal.addClass('fade');
  2343. readyToShow();
  2344. };
  2345. $modal.callEvent('loaded' + ZUI_MODAL, {
  2346. modalType: 'iframe',
  2347. jQuery: frame$
  2348. }, that);
  2349. setTimeout(ajustFrameSize, 100);
  2350. $framebody.off('resize.' + NAME).on('resize.' + NAME, resizeDialog);
  2351. }
  2352. frame$.extend({
  2353. closeModal: window.closeModal
  2354. });
  2355. } catch(e) {
  2356. readyToShow();
  2357. }
  2358. };
  2359. } else {
  2360. $.get(options.url, function(data) {
  2361. try {
  2362. var $data = $(data);
  2363. if($data.hasClass('modal-dialog')) {
  2364. $dialog.replaceWith($data);
  2365. } else if($data.hasClass('modal-content')) {
  2366. $dialog.find('.modal-content').replaceWith($data);
  2367. } else {
  2368. $body.wrapInner($data);
  2369. }
  2370. } catch(e) {
  2371. $modal.html(data);
  2372. }
  2373. $modal.callEvent('loaded' + ZUI_MODAL, {
  2374. modalType: STR_AJAX
  2375. }, that);
  2376. readyToShow();
  2377. }).error(onLoadBroken);
  2378. }
  2379. }
  2380. $modal.modal({
  2381. show: 'show',
  2382. backdrop: options.backdrop,
  2383. moveable: options.moveable,
  2384. keyboard: options.keyboard
  2385. });
  2386. };
  2387. ModalTrigger.prototype.close = function(callback, redirect) {
  2388. if(callback || redirect) {
  2389. this.$modal.on('hidden' + ZUI_MODAL, function() {
  2390. if($.isFunction(callback)) callback();
  2391. if(typeof redirect === STR_STRING) {
  2392. if(redirect === 'this') window.location.reload();
  2393. else window.location = redirect;
  2394. }
  2395. });
  2396. }
  2397. this.$modal.modal('hide');
  2398. };
  2399. ModalTrigger.prototype.toggle = function(options) {
  2400. if(this.isShown) this.close();
  2401. else this.show(options);
  2402. };
  2403. ModalTrigger.prototype.ajustPosition = function(position) {
  2404. this.$modal.modal('ajustPosition', position || this.options.position);
  2405. };
  2406. $.zui({
  2407. ModalTrigger: ModalTrigger,
  2408. modalTrigger: new ModalTrigger()
  2409. });
  2410. $.fn.modalTrigger = function(option, settings) {
  2411. return $(this).each(function() {
  2412. var $this = $(this);
  2413. var data = $this.data(NAME),
  2414. options = $.extend({
  2415. title: $this.attr('title') || $this.text(),
  2416. url: $this.attr('href'),
  2417. type: $this.hasClass('iframe') ? 'iframe' : ''
  2418. }, $this.data(), $.isPlainObject(option) && option);
  2419. if(!data) $this.data(NAME, (data = new ModalTrigger(options, $this)));
  2420. if(typeof option == STR_STRING) data[option](settings);
  2421. else if(options.show) data.show(settings);
  2422. $this.on((options.trigger || 'click') + '.toggle.' + NAME, function(e) {
  2423. data.toggle(options);
  2424. if($this.is('a')) e.preventDefault();
  2425. });
  2426. });
  2427. };
  2428. var old = $.fn.modal;
  2429. $.fn.modal = function(option, settings) {
  2430. return $(this).each(function() {
  2431. var $this = $(this);
  2432. if($this.hasClass('modal')) old.call($this, option, settings);
  2433. else $this.modalTrigger(option, settings);
  2434. });
  2435. };
  2436. var getModal = function(modal) {
  2437. var modalType = typeof(modal);
  2438. if(modalType === 'undefined') {
  2439. modal = $('.modal.modal-trigger');
  2440. } else if(modalType === STR_STRING) {
  2441. modal = $(modal);
  2442. }
  2443. if(modal && (modal instanceof $)) return modal;
  2444. return null;
  2445. };
  2446. // callback, redirect, modal
  2447. var closeModal = function(modal, callback, redirect) {
  2448. if($.isFunction(modal)) {
  2449. var oldModal = redirect;
  2450. redirect = callback;
  2451. callback = modal;
  2452. modal = oldModal;
  2453. }
  2454. modal = getModal(modal);
  2455. if(modal && modal.length) {
  2456. modal.each(function() {
  2457. $(this).data(NAME).close(callback, redirect);
  2458. });
  2459. }
  2460. };
  2461. var ajustModalPosition = function(position, modal) {
  2462. modal = getModal(modal);
  2463. if(modal && modal.length) {
  2464. modal.modal('ajustPosition', position);
  2465. }
  2466. };
  2467. $.zui({
  2468. closeModal: closeModal,
  2469. ajustModalPosition: ajustModalPosition
  2470. });
  2471. $(document).on('click.' + NAME + '.data-api', '[data-toggle="modal"]', function(e) {
  2472. var $this = $(this);
  2473. var href = $this.attr('href');
  2474. var $target = null;
  2475. try {
  2476. $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, '')));
  2477. } catch(ex) {}
  2478. if(!$target || !$target.length) {
  2479. if(!$this.data(NAME)) {
  2480. $this.modalTrigger({
  2481. show: true,
  2482. });
  2483. } else {
  2484. $this.trigger('.toggle.' + NAME);
  2485. }
  2486. }
  2487. if($this.is('a')) {
  2488. e.preventDefault();
  2489. }
  2490. });
  2491. }(window.jQuery, window));
  2492. /* ========================================================================
  2493. * Bootstrap: tooltip.js v3.0.0
  2494. * http://twzui.github.com/bootstrap/javascript.html#tooltip
  2495. * Inspired by the original jQuery.tipsy by Jason Frame
  2496. * ========================================================================
  2497. * Copyright 2012 Twitter, Inc.
  2498. *
  2499. * Licensed under the Apache License, Version 2.0 (the "License");
  2500. * you may not use this file except in compliance with the License.
  2501. * You may obtain a copy of the License at
  2502. *
  2503. * http://www.apache.org/licenses/LICENSE-2.0
  2504. *
  2505. * Unless required by applicable law or agreed to in writing, software
  2506. * distributed under the License is distributed on an "AS IS" BASIS,
  2507. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2508. * See the License for the specific language governing permissions and
  2509. * limitations under the License.
  2510. * ======================================================================== */
  2511. + function($) {
  2512. 'use strict';
  2513. // TOOLTIP PUBLIC CLASS DEFINITION
  2514. // ===============================
  2515. var Tooltip = function(element, options) {
  2516. this.type =
  2517. this.options =
  2518. this.enabled =
  2519. this.timeout =
  2520. this.hoverState =
  2521. this.$element = null
  2522. this.init('tooltip', element, options)
  2523. }
  2524. Tooltip.DEFAULTS = {
  2525. animation: true,
  2526. placement: 'top',
  2527. selector: false,
  2528. template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
  2529. trigger: 'hover focus',
  2530. title: '',
  2531. delay: 0,
  2532. html: false,
  2533. container: false
  2534. }
  2535. Tooltip.prototype.init = function(type, element, options) {
  2536. this.enabled = true
  2537. this.type = type
  2538. this.$element = $(element)
  2539. this.options = this.getOptions(options)
  2540. var triggers = this.options.trigger.split(' ')
  2541. for(var i = triggers.length; i--;) {
  2542. var trigger = triggers[i]
  2543. if(trigger == 'click') {
  2544. this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
  2545. } else if(trigger != 'manual') {
  2546. var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
  2547. var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
  2548. this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
  2549. this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
  2550. }
  2551. }
  2552. this.options.selector ?
  2553. (this._options = $.extend({}, this.options, {
  2554. trigger: 'manual',
  2555. selector: ''
  2556. })) :
  2557. this.fixTitle()
  2558. }
  2559. Tooltip.prototype.getDefaults = function() {
  2560. return Tooltip.DEFAULTS
  2561. }
  2562. Tooltip.prototype.getOptions = function(options) {
  2563. options = $.extend({}, this.getDefaults(), this.$element.data(), options)
  2564. if(options.delay && typeof options.delay == 'number') {
  2565. options.delay = {
  2566. show: options.delay,
  2567. hide: options.delay
  2568. }
  2569. }
  2570. return options
  2571. }
  2572. Tooltip.prototype.getDelegateOptions = function() {
  2573. var options = {}
  2574. var defaults = this.getDefaults()
  2575. this._options && $.each(this._options, function(key, value) {
  2576. if(defaults[key] != value) options[key] = value
  2577. })
  2578. return options
  2579. }
  2580. Tooltip.prototype.enter = function(obj) {
  2581. var self = obj instanceof this.constructor ?
  2582. obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('zui.' + this.type)
  2583. clearTimeout(self.timeout)
  2584. self.hoverState = 'in'
  2585. if(!self.options.delay || !self.options.delay.show) return self.show()
  2586. self.timeout = setTimeout(function() {
  2587. if(self.hoverState == 'in') self.show()
  2588. }, self.options.delay.show)
  2589. }
  2590. Tooltip.prototype.leave = function(obj) {
  2591. var self = obj instanceof this.constructor ?
  2592. obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('zui.' + this.type)
  2593. clearTimeout(self.timeout)
  2594. self.hoverState = 'out'
  2595. if(!self.options.delay || !self.options.delay.hide) return self.hide()
  2596. self.timeout = setTimeout(function() {
  2597. if(self.hoverState == 'out') self.hide()
  2598. }, self.options.delay.hide)
  2599. }
  2600. Tooltip.prototype.show = function(content) {
  2601. var e = $.Event('show.zui.' + this.type)
  2602. if(this.hasContent() && this.enabled) {
  2603. this.$element.trigger(e)
  2604. if(e.isDefaultPrevented()) return
  2605. var $tip = this.tip()
  2606. this.setContent(content)
  2607. if(this.options.animation) $tip.addClass('fade')
  2608. var placement = typeof this.options.placement == 'function' ?
  2609. this.options.placement.call(this, $tip[0], this.$element[0]) :
  2610. this.options.placement
  2611. var autoToken = /\s?auto?\s?/i
  2612. var autoPlace = autoToken.test(placement)
  2613. if(autoPlace) placement = placement.replace(autoToken, '') || 'top'
  2614. $tip
  2615. .detach()
  2616. .css({
  2617. top: 0,
  2618. left: 0,
  2619. display: 'block'
  2620. })
  2621. .addClass(placement)
  2622. this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
  2623. var pos = this.getPosition()
  2624. var actualWidth = $tip[0].offsetWidth
  2625. var actualHeight = $tip[0].offsetHeight
  2626. if(autoPlace) {
  2627. var $parent = this.$element.parent()
  2628. var orgPlacement = placement
  2629. var docScroll = document.documentElement.scrollTop || document.body.scrollTop
  2630. var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
  2631. var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
  2632. var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left
  2633. placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
  2634. placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
  2635. placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
  2636. placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
  2637. placement
  2638. $tip
  2639. .removeClass(orgPlacement)
  2640. .addClass(placement)
  2641. }
  2642. var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
  2643. this.applyPlacement(calculatedOffset, placement)
  2644. this.$element.trigger('shown.zui.' + this.type)
  2645. }
  2646. }
  2647. Tooltip.prototype.applyPlacement = function(offset, placement) {
  2648. var replace
  2649. var $tip = this.tip()
  2650. var width = $tip[0].offsetWidth
  2651. var height = $tip[0].offsetHeight
  2652. // manually read margins because getBoundingClientRect includes difference
  2653. var marginTop = parseInt($tip.css('margin-top'), 10)
  2654. var marginLeft = parseInt($tip.css('margin-left'), 10)
  2655. // we must check for NaN for ie 8/9
  2656. if(isNaN(marginTop)) marginTop = 0
  2657. if(isNaN(marginLeft)) marginLeft = 0
  2658. offset.top = offset.top + marginTop
  2659. offset.left = offset.left + marginLeft
  2660. $tip
  2661. .offset(offset)
  2662. .addClass('in')
  2663. // check to see if placing tip in new offset caused the tip to resize itself
  2664. var actualWidth = $tip[0].offsetWidth
  2665. var actualHeight = $tip[0].offsetHeight
  2666. if(placement == 'top' && actualHeight != height) {
  2667. replace = true
  2668. offset.top = offset.top + height - actualHeight
  2669. }
  2670. if(/bottom|top/.test(placement)) {
  2671. var delta = 0
  2672. if(offset.left < 0) {
  2673. delta = offset.left * -2
  2674. offset.left = 0
  2675. $tip.offset(offset)
  2676. actualWidth = $tip[0].offsetWidth
  2677. actualHeight = $tip[0].offsetHeight
  2678. }
  2679. this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
  2680. } else {
  2681. this.replaceArrow(actualHeight - height, actualHeight, 'top')
  2682. }
  2683. if(replace) $tip.offset(offset)
  2684. }
  2685. Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
  2686. this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
  2687. }
  2688. Tooltip.prototype.setContent = function(content) {
  2689. var $tip = this.tip()
  2690. var title = content || this.getTitle()
  2691. if(this.options.tipId) $tip.attr('id', this.options.tipId)
  2692. if(this.options.tipClass) $tip.addClass(this.options.tipClass)
  2693. $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
  2694. $tip.removeClass('fade in top bottom left right')
  2695. }
  2696. Tooltip.prototype.hide = function() {
  2697. var that = this
  2698. var $tip = this.tip()
  2699. var e = $.Event('hide.zui.' + this.type)
  2700. function complete() {
  2701. if(that.hoverState != 'in') $tip.detach()
  2702. }
  2703. this.$element.trigger(e)
  2704. if(e.isDefaultPrevented()) return
  2705. $tip.removeClass('in')
  2706. $.support.transition && this.$tip.hasClass('fade') ?
  2707. $tip
  2708. .one($.support.transition.end, complete)
  2709. .emulateTransitionEnd(150) :
  2710. complete()
  2711. this.$element.trigger('hidden.zui.' + this.type)
  2712. return this
  2713. }
  2714. Tooltip.prototype.fixTitle = function() {
  2715. var $e = this.$element
  2716. if($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
  2717. $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
  2718. }
  2719. }
  2720. Tooltip.prototype.hasContent = function() {
  2721. return this.getTitle()
  2722. }
  2723. Tooltip.prototype.getPosition = function() {
  2724. var el = this.$element[0]
  2725. return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
  2726. width: el.offsetWidth,
  2727. height: el.offsetHeight
  2728. }, this.$element.offset())
  2729. }
  2730. Tooltip.prototype.getCalculatedOffset = function(placement, pos, actualWidth, actualHeight) {
  2731. return placement == 'bottom' ? {
  2732. top: pos.top + pos.height,
  2733. left: pos.left + pos.width / 2 - actualWidth / 2
  2734. } :
  2735. placement == 'top' ? {
  2736. top: pos.top - actualHeight,
  2737. left: pos.left + pos.width / 2 - actualWidth / 2
  2738. } :
  2739. placement == 'left' ? {
  2740. top: pos.top + pos.height / 2 - actualHeight / 2,
  2741. left: pos.left - actualWidth
  2742. } :
  2743. /* placement == 'right' */
  2744. {
  2745. top: pos.top + pos.height / 2 - actualHeight / 2,
  2746. left: pos.left + pos.width
  2747. }
  2748. }
  2749. Tooltip.prototype.getTitle = function() {
  2750. var title
  2751. var $e = this.$element
  2752. var o = this.options
  2753. title = $e.attr('data-original-title') || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
  2754. return title
  2755. }
  2756. Tooltip.prototype.tip = function() {
  2757. return this.$tip = this.$tip || $(this.options.template)
  2758. }
  2759. Tooltip.prototype.arrow = function() {
  2760. return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
  2761. }
  2762. Tooltip.prototype.validate = function() {
  2763. if(!this.$element[0].parentNode) {
  2764. this.hide()
  2765. this.$element = null
  2766. this.options = null
  2767. }
  2768. }
  2769. Tooltip.prototype.enable = function() {
  2770. this.enabled = true
  2771. }
  2772. Tooltip.prototype.disable = function() {
  2773. this.enabled = false
  2774. }
  2775. Tooltip.prototype.toggleEnabled = function() {
  2776. this.enabled = !this.enabled
  2777. }
  2778. Tooltip.prototype.toggle = function(e) {
  2779. var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('zui.' + this.type) : this
  2780. self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  2781. }
  2782. Tooltip.prototype.destroy = function() {
  2783. this.hide().$element.off('.' + this.type).removeData('zui.' + this.type)
  2784. }
  2785. // TOOLTIP PLUGIN DEFINITION
  2786. // =========================
  2787. var old = $.fn.tooltip
  2788. $.fn.tooltip = function(option, params) {
  2789. return this.each(function() {
  2790. var $this = $(this)
  2791. var data = $this.data('zui.tooltip')
  2792. var options = typeof option == 'object' && option
  2793. if(!data) $this.data('zui.tooltip', (data = new Tooltip(this, options)))
  2794. if(typeof option == 'string') data[option](params)
  2795. })
  2796. }
  2797. $.fn.tooltip.Constructor = Tooltip
  2798. // TOOLTIP NO CONFLICT
  2799. // ===================
  2800. $.fn.tooltip.noConflict = function() {
  2801. $.fn.tooltip = old
  2802. return this
  2803. }
  2804. }(window.jQuery);
  2805. /* ========================================================================
  2806. * Bootstrap: popover.js v3.0.0
  2807. * http://twbs.github.com/bootstrap/javascript.html#popovers
  2808. * ========================================================================
  2809. * Copyright 2012 Twitter, Inc.
  2810. *
  2811. * Licensed under the Apache License, Version 2.0 (the "License");
  2812. * you may not use this file except in compliance with the License.
  2813. * You may obtain a copy of the License at
  2814. *
  2815. * http://www.apache.org/licenses/LICENSE-2.0
  2816. *
  2817. * Unless required by applicable law or agreed to in writing, software
  2818. * distributed under the License is distributed on an "AS IS" BASIS,
  2819. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2820. * See the License for the specific language governing permissions and
  2821. * limitations under the License.
  2822. * ======================================================================== */
  2823. + function($) {
  2824. 'use strict';
  2825. // POPOVER PUBLIC CLASS DEFINITION
  2826. // ===============================
  2827. var Popover = function(element, options) {
  2828. this.init('popover', element, options)
  2829. }
  2830. if(!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
  2831. Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
  2832. placement: 'right',
  2833. trigger: 'click',
  2834. content: '',
  2835. template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  2836. })
  2837. // NOTE: POPOVER EXTENDS tooltip.js
  2838. // ================================
  2839. Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
  2840. Popover.prototype.constructor = Popover
  2841. Popover.prototype.getDefaults = function() {
  2842. return Popover.DEFAULTS
  2843. }
  2844. Popover.prototype.setContent = function() {
  2845. var $tip = this.tip()
  2846. var target = this.getTarget()
  2847. if(target) {
  2848. if(target.find('.arrow').length < 1)
  2849. $tip.addClass('no-arrow')
  2850. $tip.html(target.html())
  2851. return
  2852. }
  2853. var title = this.getTitle()
  2854. var content = this.getContent()
  2855. $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
  2856. $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
  2857. $tip.removeClass('fade top bottom left right in')
  2858. if(this.options.tipId) $tip.attr('id', this.options.tipId)
  2859. if(this.options.tipClass) $tip.addClass(this.options.tipClass)
  2860. // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
  2861. // this manually by checking the contents.
  2862. if(!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
  2863. }
  2864. Popover.prototype.hasContent = function() {
  2865. return this.getTarget() || this.getTitle() || this.getContent()
  2866. }
  2867. Popover.prototype.getContent = function() {
  2868. var $e = this.$element
  2869. var o = this.options
  2870. return $e.attr('data-content') || (typeof o.content == 'function' ?
  2871. o.content.call($e[0]) :
  2872. o.content)
  2873. }
  2874. Popover.prototype.getTarget = function() {
  2875. var $e = this.$element
  2876. var o = this.options
  2877. var target = $e.attr('data-target') || (typeof o.target == 'function' ?
  2878. o.target.call($e[0]) :
  2879. o.target)
  2880. return(target && true) ? (target == '$next' ? $e.next('.popover') : $(target)) : false
  2881. }
  2882. Popover.prototype.arrow = function() {
  2883. return this.$arrow = this.$arrow || this.tip().find('.arrow')
  2884. }
  2885. Popover.prototype.tip = function() {
  2886. if(!this.$tip) this.$tip = $(this.options.template)
  2887. return this.$tip
  2888. }
  2889. // POPOVER PLUGIN DEFINITION
  2890. // =========================
  2891. var old = $.fn.popover
  2892. $.fn.popover = function(option) {
  2893. return this.each(function() {
  2894. var $this = $(this)
  2895. var data = $this.data('zui.popover')
  2896. var options = typeof option == 'object' && option
  2897. if(!data) $this.data('zui.popover', (data = new Popover(this, options)))
  2898. if(typeof option == 'string') data[option]()
  2899. })
  2900. }
  2901. $.fn.popover.Constructor = Popover
  2902. // POPOVER NO CONFLICT
  2903. // ===================
  2904. $.fn.popover.noConflict = function() {
  2905. $.fn.popover = old
  2906. return this
  2907. }
  2908. }(window.jQuery);
  2909. /* ========================================================================
  2910. * Bootstrap: dropdown.js v3.0.0
  2911. * http://twbs.github.com/bootstrap/javascript.html#dropdowns
  2912. * ========================================================================
  2913. * Copyright 2012 Twitter, Inc.
  2914. *
  2915. * Licensed under the Apache License, Version 2.0 (the "License");
  2916. * you may not use this file except in compliance with the License.
  2917. * You may obtain a copy of the License at
  2918. *
  2919. * http://www.apache.org/licenses/LICENSE-2.0
  2920. *
  2921. * Unless required by applicable law or agreed to in writing, software
  2922. * distributed under the License is distributed on an "AS IS" BASIS,
  2923. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2924. * See the License for the specific language governing permissions and
  2925. * limitations under the License.
  2926. * ======================================================================== */
  2927. + function($) {
  2928. 'use strict';
  2929. // DROPDOWN CLASS DEFINITION
  2930. // =========================
  2931. var zuiname = 'zui.dropdown';
  2932. var backdrop = '.dropdown-backdrop'
  2933. var toggle = '[data-toggle=dropdown]'
  2934. var Dropdown = function(element) {
  2935. var $el = $(element).on('click.' + zuiname, this.toggle)
  2936. }
  2937. Dropdown.prototype.toggle = function(e) {
  2938. var $this = $(this)
  2939. if($this.is('.disabled, :disabled')) return
  2940. var $parent = getParent($this)
  2941. var isActive = $parent.hasClass('open')
  2942. clearMenus()
  2943. if(!isActive) {
  2944. if('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
  2945. // if mobile we we use a backdrop because click events don't delegate
  2946. $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
  2947. }
  2948. $parent.trigger(e = $.Event('show.' + zuiname))
  2949. if(e.isDefaultPrevented()) return
  2950. $parent
  2951. .toggleClass('open')
  2952. .trigger('shown.' + zuiname)
  2953. $this.focus()
  2954. }
  2955. return false
  2956. }
  2957. Dropdown.prototype.keydown = function(e) {
  2958. if(!/(38|40|27)/.test(e.keyCode)) return
  2959. var $this = $(this)
  2960. e.preventDefault()
  2961. e.stopPropagation()
  2962. if($this.is('.disabled, :disabled')) return
  2963. var $parent = getParent($this)
  2964. var isActive = $parent.hasClass('open')
  2965. if(!isActive || (isActive && e.keyCode == 27)) {
  2966. if(e.which == 27) $parent.find(toggle).focus()
  2967. return $this.click()
  2968. }
  2969. var $items = $('[role=menu] li:not(.divider):visible a', $parent)
  2970. if(!$items.length) return
  2971. var index = $items.index($items.filter(':focus'))
  2972. if(e.keyCode == 38 && index > 0) index-- // up
  2973. if(e.keyCode == 40 && index < $items.length - 1) index++ // down
  2974. if(!~index) index = 0
  2975. $items.eq(index).focus()
  2976. }
  2977. function clearMenus() {
  2978. $(backdrop).remove()
  2979. $(toggle).each(function(e) {
  2980. var $parent = getParent($(this))
  2981. if(!$parent.hasClass('open')) return
  2982. $parent.trigger(e = $.Event('hide.' + zuiname))
  2983. if(e.isDefaultPrevented()) return
  2984. $parent.removeClass('open').trigger('hidden.' + zuiname)
  2985. })
  2986. }
  2987. function getParent($this) {
  2988. var selector = $this.attr('data-target')
  2989. if(!selector) {
  2990. selector = $this.attr('href')
  2991. selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
  2992. }
  2993. var $parent = selector && $(selector)
  2994. return $parent && $parent.length ? $parent : $this.parent()
  2995. }
  2996. // DROPDOWN PLUGIN DEFINITION
  2997. // ==========================
  2998. var old = $.fn.dropdown
  2999. $.fn.dropdown = function(option) {
  3000. return this.each(function() {
  3001. var $this = $(this)
  3002. var data = $this.data('dropdown')
  3003. if(!data) $this.data('dropdown', (data = new Dropdown(this)))
  3004. if(typeof option == 'string') data[option].call($this)
  3005. })
  3006. }
  3007. $.fn.dropdown.Constructor = Dropdown
  3008. // DROPDOWN NO CONFLICT
  3009. // ====================
  3010. $.fn.dropdown.noConflict = function() {
  3011. $.fn.dropdown = old
  3012. return this
  3013. }
  3014. // APPLY TO STANDARD DROPDOWN ELEMENTS
  3015. // ===================================
  3016. var apiName = zuiname + '.data-api'
  3017. $(document)
  3018. .on('click.' + apiName, clearMenus)
  3019. .on('click.' + apiName, '.dropdown form', function(e) {
  3020. e.stopPropagation()
  3021. })
  3022. .on('click.' + apiName, toggle, Dropdown.prototype.toggle)
  3023. .on('keydown.' + apiName, toggle + ', [role=menu]', Dropdown.prototype.keydown)
  3024. }(window.jQuery);
  3025. /* ========================================================================
  3026. * Bootstrap: carousel.js v3.0.0
  3027. * http://twzui.github.com/bootstrap/javascript.html#carousel
  3028. * ========================================================================
  3029. * Copyright 2012 Twitter, Inc.
  3030. *
  3031. * Licensed under the Apache License, Version 2.0 (the "License");
  3032. * you may not use this file except in compliance with the License.
  3033. * You may obtain a copy of the License at
  3034. *
  3035. * http://www.apache.org/licenses/LICENSE-2.0
  3036. *
  3037. * Unless required by applicable law or agreed to in writing, software
  3038. * distributed under the License is distributed on an "AS IS" BASIS,
  3039. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  3040. * See the License for the specific language governing permissions and
  3041. * limitations under the License.
  3042. * ========================================================================
  3043. * Updates in ZUI:
  3044. * 1. support touch event for touchable devices
  3045. * ======================================================================== */
  3046. + function($) {
  3047. 'use strict';
  3048. // CAROUSEL CLASS DEFINITION
  3049. // =========================
  3050. var Carousel = function(element, options) {
  3051. this.$element = $(element)
  3052. this.$indicators = this.$element.find('.carousel-indicators')
  3053. this.options = options
  3054. this.paused =
  3055. this.sliding =
  3056. this.interval =
  3057. this.$active =
  3058. this.$items = null
  3059. this.options.pause == 'hover' && this.$element
  3060. .on('mouseenter', $.proxy(this.pause, this))
  3061. .on('mouseleave', $.proxy(this.cycle, this))
  3062. }
  3063. Carousel.DEFAULTS = {
  3064. interval: 5000,
  3065. pause: 'hover',
  3066. wrap: true,
  3067. touchable: true
  3068. }
  3069. Carousel.prototype.touchable = function() {
  3070. if(!this.options.touchable) return;
  3071. this.$element.on('touchstart touchmove touchend', touch);
  3072. var touchStartX, touchStartY;
  3073. /* listen the touch event */
  3074. function touch(event) {
  3075. var event = event || window.event;
  3076. if(event.originalEvent) event = event.originalEvent;
  3077. var carousel = $(this);
  3078. switch(event.type) {
  3079. case "touchstart":
  3080. touchStartX = event.touches[0].pageX;
  3081. touchStartY = event.touches[0].pageY;
  3082. break;
  3083. case "touchend":
  3084. var distanceX = event.changedTouches[0].pageX - touchStartX;
  3085. var distanceY = event.changedTouches[0].pageY - touchStartY;
  3086. if(Math.abs(distanceX) > Math.abs(distanceY)) {
  3087. handleCarousel(carousel, distanceX);
  3088. if(Math.abs(distanceX) > 10) {
  3089. event.preventDefault();
  3090. }
  3091. } else {
  3092. //var $w = $(window);
  3093. //$('body,html').animate({
  3094. // scrollTop: $w.scrollTop() - distanceY
  3095. //}, 400)
  3096. }
  3097. break;
  3098. }
  3099. }
  3100. function handleCarousel(carousel, distance) {
  3101. if(distance > 10) carousel.find('.left.carousel-control').click();
  3102. if(distance < -10) carousel.find('.right.carousel-control').click();
  3103. }
  3104. }
  3105. Carousel.prototype.cycle = function(e) {
  3106. e || (this.paused = false)
  3107. this.interval && clearInterval(this.interval)
  3108. this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
  3109. return this
  3110. }
  3111. Carousel.prototype.getActiveIndex = function() {
  3112. this.$active = this.$element.find('.item.active')
  3113. this.$items = this.$active.parent().children()
  3114. return this.$items.index(this.$active)
  3115. }
  3116. Carousel.prototype.to = function(pos) {
  3117. var that = this
  3118. var activeIndex = this.getActiveIndex()
  3119. if(pos > (this.$items.length - 1) || pos < 0) return
  3120. if(this.sliding) return this.$element.one('slid', function() {
  3121. that.to(pos)
  3122. })
  3123. if(activeIndex == pos) return this.pause().cycle()
  3124. return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
  3125. }
  3126. Carousel.prototype.pause = function(e) {
  3127. e || (this.paused = true)
  3128. if(this.$element.find('.next, .prev').length && $.support.transition.end) {
  3129. this.$element.trigger($.support.transition.end)
  3130. this.cycle(true)
  3131. }
  3132. this.interval = clearInterval(this.interval)
  3133. return this
  3134. }
  3135. Carousel.prototype.next = function() {
  3136. if(this.sliding) return
  3137. return this.slide('next')
  3138. }
  3139. Carousel.prototype.prev = function() {
  3140. if(this.sliding) return
  3141. return this.slide('prev')
  3142. }
  3143. Carousel.prototype.slide = function(type, next) {
  3144. var $active = this.$element.find('.item.active')
  3145. var $next = next || $active[type]()
  3146. var isCycling = this.interval
  3147. var direction = type == 'next' ? 'left' : 'right'
  3148. var fallback = type == 'next' ? 'first' : 'last'
  3149. var that = this
  3150. if(!$next.length) {
  3151. if(!this.options.wrap) return
  3152. $next = this.$element.find('.item')[fallback]()
  3153. }
  3154. this.sliding = true
  3155. isCycling && this.pause()
  3156. var e = $.Event('slide.zui.carousel', {
  3157. relatedTarget: $next[0],
  3158. direction: direction
  3159. })
  3160. if($next.hasClass('active')) return
  3161. if(this.$indicators.length) {
  3162. this.$indicators.find('.active').removeClass('active')
  3163. this.$element.one('slid', function() {
  3164. var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
  3165. $nextIndicator && $nextIndicator.addClass('active')
  3166. })
  3167. }
  3168. if($.support.transition && this.$element.hasClass('slide')) {
  3169. this.$element.trigger(e)
  3170. if(e.isDefaultPrevented()) return
  3171. $next.addClass(type)
  3172. $next[0].offsetWidth // force reflow
  3173. $active.addClass(direction)
  3174. $next.addClass(direction)
  3175. $active
  3176. .one($.support.transition.end, function() {
  3177. $next.removeClass([type, direction].join(' ')).addClass('active')
  3178. $active.removeClass(['active', direction].join(' '))
  3179. that.sliding = false
  3180. setTimeout(function() {
  3181. that.$element.trigger('slid')
  3182. }, 0)
  3183. })
  3184. .emulateTransitionEnd(600)
  3185. } else {
  3186. this.$element.trigger(e)
  3187. if(e.isDefaultPrevented()) return
  3188. $active.removeClass('active')
  3189. $next.addClass('active')
  3190. this.sliding = false
  3191. this.$element.trigger('slid')
  3192. }
  3193. isCycling && this.cycle()
  3194. return this
  3195. }
  3196. // CAROUSEL PLUGIN DEFINITION
  3197. // ==========================
  3198. var old = $.fn.carousel
  3199. $.fn.carousel = function(option) {
  3200. return this.each(function() {
  3201. var $this = $(this)
  3202. var data = $this.data('zui.carousel')
  3203. var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
  3204. var action = typeof option == 'string' ? option : options.slide
  3205. if(!data) $this.data('zui.carousel', (data = new Carousel(this, options)))
  3206. if(typeof option == 'number') data.to(option)
  3207. else if(action) data[action]()
  3208. else if(options.interval) data.pause().cycle()
  3209. if(options.touchable) data.touchable()
  3210. })
  3211. }
  3212. $.fn.carousel.Constructor = Carousel
  3213. // CAROUSEL NO CONFLICT
  3214. // ====================
  3215. $.fn.carousel.noConflict = function() {
  3216. $.fn.carousel = old
  3217. return this
  3218. }
  3219. // CAROUSEL DATA-API
  3220. // =================
  3221. $(document).on('click.zui.carousel.data-api', '[data-slide], [data-slide-to]', function(e) {
  3222. var $this = $(this),
  3223. href
  3224. var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
  3225. var options = $.extend({}, $target.data(), $this.data())
  3226. var slideIndex = $this.attr('data-slide-to')
  3227. if(slideIndex) options.interval = false
  3228. $target.carousel(options)
  3229. if(slideIndex = $this.attr('data-slide-to')) {
  3230. $target.data('zui.carousel').to(slideIndex)
  3231. }
  3232. e.preventDefault()
  3233. })
  3234. $(window).on('load', function() {
  3235. $('[data-ride="carousel"]').each(function() {
  3236. var $carousel = $(this)
  3237. $carousel.carousel($carousel.data())
  3238. })
  3239. })
  3240. }(window.jQuery);
  3241. /* ========================================================================
  3242. * image.ready.js
  3243. * http://www.planeart.cn/?p=1121
  3244. * ========================================================================
  3245. * @version 2011.05.27
  3246. * @author TangBin
  3247. * ======================================================================== */
  3248. (function($) {
  3249. 'use strict';
  3250. /**
  3251. * Image ready
  3252. * @param {String} image url
  3253. * @param {Function} callback on image ready
  3254. * @param {Function} callback on image load
  3255. * @param {Function} callback on error
  3256. * @example imgReady('image.png', function () {
  3257. alert('size ready: width=' + this.width + '; height=' + this.height);
  3258. });
  3259. */
  3260. $.zui.imgReady = (function() {
  3261. var list = [],
  3262. intervalId = null,
  3263. // 用来执行队列
  3264. tick = function() {
  3265. var i = 0;
  3266. for(; i < list.length; i++) {
  3267. list[i].end ? list.splice(i--, 1) : list[i]();
  3268. }!list.length && stop();
  3269. },
  3270. // 停止所有定时器队列
  3271. stop = function() {
  3272. clearInterval(intervalId);
  3273. intervalId = null;
  3274. };
  3275. return function(url, ready, load, error) {
  3276. var onready, width, height, newWidth, newHeight,
  3277. img = new Image();
  3278. img.src = url;
  3279. // 如果图片被缓存,则直接返回缓存数据
  3280. if(img.complete) {
  3281. ready.call(img);
  3282. load && load.call(img);
  3283. return;
  3284. }
  3285. width = img.width;
  3286. height = img.height;
  3287. // 加载错误后的事件
  3288. img.onerror = function() {
  3289. error && error.call(img);
  3290. onready.end = true;
  3291. img = img.onload = img.onerror = null;
  3292. };
  3293. // 图片尺寸就绪
  3294. onready = function() {
  3295. newWidth = img.width;
  3296. newHeight = img.height;
  3297. if(newWidth !== width || newHeight !== height ||
  3298. // 如果图片已经在其他地方加载可使用面积检测
  3299. newWidth * newHeight > 1024
  3300. ) {
  3301. ready.call(img);
  3302. onready.end = true;
  3303. }
  3304. };
  3305. onready();
  3306. // 完全加载完毕的事件
  3307. img.onload = function() {
  3308. // onload在定时器时间差范围内可能比onready快
  3309. // 这里进行检查并保证onready优先执行
  3310. !onready.end && onready();
  3311. load && load.call(img);
  3312. // IE gif动画会循环执行onload,置空onload即可
  3313. img = img.onload = img.onerror = null;
  3314. };
  3315. // 加入队列中定期执行
  3316. if(!onready.end) {
  3317. list.push(onready);
  3318. // 无论何时只允许出现一个定时器,减少浏览器性能损耗
  3319. if(intervalId === null) intervalId = setInterval(tick, 40);
  3320. }
  3321. };
  3322. })();
  3323. }(jQuery));
  3324. /* ========================================================================
  3325. * ZUI: lightbox.js
  3326. * http://zui.sexy
  3327. * ========================================================================
  3328. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  3329. * ======================================================================== */
  3330. (function($, window, Math) {
  3331. 'use strict';
  3332. if(!$.fn.modalTrigger) throw new Error('modal & modalTrigger requires for lightbox');
  3333. if(!$.zui.imgReady) throw new Error('imgReady requires for lightbox');
  3334. var Lightbox = function(element, options) {
  3335. this.$ = $(element);
  3336. this.options = this.getOptions(options);
  3337. this.init();
  3338. };
  3339. Lightbox.DEFAULTS = {
  3340. modalTeamplate: '<div class="icon-spinner icon-spin loader"></div><div class="modal-dialog"><button class="close" data-dismiss="modal" aria-hidden="true"><i class="icon-remove"></i></button><button class="controller prev"><i class="icon icon-chevron-left"></i></button><button class="controller next"><i class="icon icon-chevron-right"></i></button><img class="lightbox-img" src="{image}" alt="" data-dismiss="modal" /><div class="caption"><div class="content">{caption}<div></div></div>'
  3341. }; // default options
  3342. Lightbox.prototype.getOptions = function(options) {
  3343. var IMAGE = 'image';
  3344. options = $.extend({}, Lightbox.DEFAULTS, this.$.data(), options);
  3345. if(!options[IMAGE]) {
  3346. options[IMAGE] = this.$.attr('src') || this.$.attr('href') || this.$.find('img').attr('src');
  3347. this.$.data(IMAGE, options[IMAGE]);
  3348. }
  3349. return options;
  3350. };
  3351. Lightbox.prototype.init = function() {
  3352. this.bindEvents();
  3353. };
  3354. Lightbox.prototype.initGroups = function() {
  3355. var groups = this.$.data('groups');
  3356. if(!groups) {
  3357. groups = $('[data-toggle="lightbox"][data-group="' + this.options.group + '"], [data-lightbox-group="' + this.options.group + '"]');
  3358. this.$.data('groups', groups);
  3359. groups.each(function(index) {
  3360. $(this).attr('data-group-index', index);
  3361. });
  3362. }
  3363. this.groups = groups;
  3364. this.groupIndex = parseInt(this.$.data('group-index'));
  3365. };
  3366. Lightbox.prototype.bindEvents = function() {
  3367. var $e = this.$,
  3368. that = this;
  3369. var options = this.options;
  3370. if(!options.image) return false;
  3371. $e.modalTrigger({
  3372. type: 'custom',
  3373. name: 'lightboxModal',
  3374. position: 'center',
  3375. custom: function(e) {
  3376. that.initGroups();
  3377. var modal = e.modal,
  3378. groups = that.groups,
  3379. groupIndex = that.groupIndex;
  3380. modal.addClass('modal-lightbox')
  3381. .html(options.modalTeamplate.format(options))
  3382. .toggleClass('lightbox-with-caption', typeof options.caption == 'string')
  3383. .removeClass('lightbox-full')
  3384. .data('group-index', groupIndex);
  3385. var dialog = modal.find('.modal-dialog'),
  3386. winWidth = $(window).width();
  3387. $.zui.imgReady(options.image, function() {
  3388. dialog.css({
  3389. width: Math.min(winWidth, this.width)
  3390. });
  3391. if(winWidth < (this.width + 30)) modal.addClass('lightbox-full');
  3392. e.ready();
  3393. });
  3394. modal.find('.prev').toggleClass('show', groups.filter('[data-group-index="' + (groupIndex - 1) + '"]').length > 0);
  3395. modal.find('.next').toggleClass('show', groups.filter('[data-group-index="' + (groupIndex + 1) + '"]').length > 0);
  3396. modal.find('.controller').click(function() {
  3397. var $this = $(this);
  3398. var id = modal.data('group-index') + ($this.hasClass('prev') ? -1 : 1);
  3399. var $e = groups.filter('[data-group-index="' + id + '"]');
  3400. if($e.length) {
  3401. var image = $e.data('image'),
  3402. caption = $e.data('caption');
  3403. modal.addClass('modal-loading')
  3404. .data('group-index', id)
  3405. .toggleClass('lightbox-with-caption', typeof caption == 'string')
  3406. .removeClass('lightbox-full');
  3407. modal.find('.lightbox-img').attr('src', image);
  3408. modal.find('.caption > .content').text(caption);
  3409. winWidth = $(window).width();
  3410. $.zui.imgReady(image, function() {
  3411. dialog.css({
  3412. width: Math.min(winWidth, this.width)
  3413. });
  3414. if(winWidth < (this.width + 30)) modal.addClass('lightbox-full');
  3415. e.ready();
  3416. });
  3417. }
  3418. modal.find('.prev').toggleClass('show', groups.filter('[data-group-index="' + (id - 1) + '"]').length > 0);
  3419. modal.find('.next').toggleClass('show', groups.filter('[data-group-index="' + (id + 1) + '"]').length > 0);
  3420. return false;
  3421. });
  3422. }
  3423. });
  3424. };
  3425. $.fn.lightbox = function(option) {
  3426. var defaultGroup = 'group' + (new Date()).getTime();
  3427. return this.each(function() {
  3428. var $this = $(this);
  3429. var options = typeof option == 'object' && option;
  3430. if(typeof options == 'object' && options.group) {
  3431. $this.attr('data-lightbox-group', options.group);
  3432. } else if($this.data('group')) {
  3433. $this.attr('data-lightbox-group', $this.data('group'));
  3434. } else {
  3435. $this.attr('data-lightbox-group', defaultGroup);
  3436. }
  3437. $this.data('group', $this.data('lightbox-group'));
  3438. var data = $this.data('zui.lightbox');
  3439. if(!data) $this.data('zui.lightbox', (data = new Lightbox(this, options)));
  3440. if(typeof option == 'string') data[option]();
  3441. });
  3442. };
  3443. $.fn.lightbox.Constructor = Lightbox;
  3444. $(function() {
  3445. $('[data-toggle="lightbox"]').lightbox();
  3446. });
  3447. }(jQuery, window, Math));
  3448. /* ========================================================================
  3449. * ZUI: messager.js
  3450. * http://zui.sexy
  3451. * ========================================================================
  3452. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  3453. * ======================================================================== */
  3454. (function($, window) {
  3455. 'use strict';
  3456. var id = 0;
  3457. var template = '<div class="messager messager-{type} {placement}" id="messager{id}" style="display:none"><div class="messager-content"></div><div class="messager-actions"><button type="button" class="close action">&times;</button></div></div>';
  3458. var defaultOptions = {
  3459. type: 'default',
  3460. placement: 'top',
  3461. time: 4000,
  3462. parent: 'body',
  3463. // clear: false,
  3464. icon: null,
  3465. close: true,
  3466. fade: true,
  3467. scale: true
  3468. };
  3469. var lastMessager;
  3470. var Messager = function(message, options) {
  3471. var that = this;
  3472. that.id = id++;
  3473. options = that.options = $.extend({}, defaultOptions, options);
  3474. that.message = (options.icon ? '<i class="icon-' + options.icon + ' icon"></i> ' : '') + message;
  3475. that.$ = $(template.format(options)).toggleClass('fade', options.fade).toggleClass('scale', options.scale).attr('id', 'messager-' + that.id);
  3476. if(!options.close) {
  3477. that.$.find('.close').remove();
  3478. } else {
  3479. that.$.on('click', '.close', function() {
  3480. that.hide();
  3481. });
  3482. }
  3483. that.$.find('.messager-content').html(that.message);
  3484. that.$.data('zui.messager', that);
  3485. };
  3486. Messager.prototype.show = function(message) {
  3487. var that = this,
  3488. options = this.options;
  3489. if(lastMessager) {
  3490. if(lastMessager.id == that.id) {
  3491. that.$.removeClass('in');
  3492. } else if(lastMessager.isShow) {
  3493. lastMessager.hide();
  3494. }
  3495. }
  3496. if(that.hiding) {
  3497. clearTimeout(that.hiding);
  3498. that.hiding = null;
  3499. }
  3500. if(message) {
  3501. that.message = (options.icon ? '<i class="icon-' + options.icon + ' icon"></i> ' : '') + message;
  3502. that.$.find('.messager-content').html(that.message);
  3503. }
  3504. that.$.appendTo(options.parent).show();
  3505. if(options.placement === 'top' || options.placement === 'bottom' || options.placement === 'center') {
  3506. that.$.css('left', ($(window).width() - that.$.width() - 50) / 2);
  3507. }
  3508. if(options.placement === 'left' || options.placement === 'right' || options.placement === 'center') {
  3509. that.$.css('top', ($(window).height() - that.$.height() - 50) / 2);
  3510. }
  3511. that.$.addClass('in');
  3512. if(options.time) {
  3513. that.hiding = setTimeout(function() {
  3514. that.hide();
  3515. }, options.time);
  3516. }
  3517. that.isShow = true;
  3518. lastMessager = that;
  3519. };
  3520. Messager.prototype.hide = function() {
  3521. var that = this;
  3522. if(that.$.hasClass('in')) {
  3523. that.$.removeClass('in');
  3524. setTimeout(function() {
  3525. that.$.remove();
  3526. }, 200);
  3527. }
  3528. that.isShow = false;
  3529. };
  3530. var showMessage = function(message, options) {
  3531. if(typeof options === 'string') {
  3532. options = {
  3533. type: options
  3534. };
  3535. }
  3536. var msg = new Messager(message, options);
  3537. msg.show();
  3538. return msg;
  3539. };
  3540. var hideMessage = function() {
  3541. $('.messager').each(function() {
  3542. var msg = $(this).data('zui.messager');
  3543. if(msg && msg.hide) msg.hide();
  3544. });
  3545. };
  3546. var getOptions = function(options) {
  3547. return(typeof options === 'string') ? {
  3548. placement: options
  3549. } : options;
  3550. };
  3551. $.zui({
  3552. Messager: Messager,
  3553. showMessager: showMessage,
  3554. messager: {
  3555. show: showMessage,
  3556. hide: hideMessage,
  3557. primary: function(message, options) {
  3558. return showMessage(message, $.extend({
  3559. type: 'primary'
  3560. }, getOptions(options)));
  3561. },
  3562. success: function(message, options) {
  3563. return showMessage(message, $.extend({
  3564. type: 'success',
  3565. icon: 'ok-sign'
  3566. }, getOptions(options)));
  3567. },
  3568. info: function(message, options) {
  3569. return showMessage(message, $.extend({
  3570. type: 'info',
  3571. icon: 'info-sign'
  3572. }, getOptions(options)));
  3573. },
  3574. warning: function(message, options) {
  3575. return showMessage(message, $.extend({
  3576. type: 'warning',
  3577. icon: 'warning-sign'
  3578. }, getOptions(options)));
  3579. },
  3580. danger: function(message, options) {
  3581. return showMessage(message, $.extend({
  3582. type: 'danger',
  3583. icon: 'exclamation-sign'
  3584. }, getOptions(options)));
  3585. },
  3586. important: function(message, options) {
  3587. return showMessage(message, $.extend({
  3588. type: 'important'
  3589. }, getOptions(options)));
  3590. },
  3591. special: function(message, options) {
  3592. return showMessage(message, $.extend({
  3593. type: 'special'
  3594. }, getOptions(options)));
  3595. }
  3596. }
  3597. });
  3598. }(jQuery, window));
  3599. /* ========================================================================
  3600. * ZUI: menu.js
  3601. * http://zui.sexy
  3602. * ========================================================================
  3603. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  3604. * ======================================================================== */
  3605. (function($) {
  3606. 'use strict';
  3607. var Menu = function(element, options) {
  3608. this.$ = $(element);
  3609. this.options = this.getOptions(options);
  3610. this.init();
  3611. };
  3612. Menu.DEFAULTS = {
  3613. auto: false,
  3614. foldicon: 'icon-chevron-right'
  3615. };
  3616. Menu.prototype.getOptions = function(options) {
  3617. options = $.extend({}, Menu.DEFAULTS, this.$.data(), options);
  3618. return options;
  3619. };
  3620. Menu.prototype.init = function() {
  3621. var children = this.$.children('.nav');
  3622. children.find('.nav').closest('li').addClass('nav-parent');
  3623. children.find('.nav > li.active').closest('li').addClass('active');
  3624. children.find('.nav-parent > a').append('<i class="' + this.options.foldicon + ' nav-parent-fold-icon"></i>');
  3625. this.handleFold();
  3626. };
  3627. Menu.prototype.handleFold = function() {
  3628. var auto = this.options.auto;
  3629. var $menu = this.$;
  3630. this.$.on('click', '.nav-parent > a', function(event) {
  3631. if(auto) {
  3632. $menu.find('.nav-parent.show').find('.nav').slideUp(function() {
  3633. $(this).closest('.nav-parent').removeClass('show');
  3634. });
  3635. $menu.find('.icon-rotate-90').removeClass('icon-rotate-90');
  3636. }
  3637. var li = $(this).closest('.nav-parent');
  3638. if(li.hasClass('show')) {
  3639. li.find('.icon-rotate-90').removeClass('icon-rotate-90');
  3640. li.find('.nav').slideUp(function() {
  3641. $(this).closest('.nav-parent').removeClass('show');
  3642. });
  3643. } else {
  3644. li.find('.nav-parent-fold-icon').addClass('icon-rotate-90');
  3645. li.find('.nav').slideDown(function() {
  3646. $(this).closest('.nav-parent').addClass('show');
  3647. });
  3648. }
  3649. event.preventDefault();
  3650. return false;
  3651. });
  3652. };
  3653. $.fn.menu = function(option) {
  3654. return this.each(function() {
  3655. var $this = $(this);
  3656. var data = $this.data('zui.menu');
  3657. var options = typeof option == 'object' && option;
  3658. if(!data) $this.data('zui.menu', (data = new Menu(this, options)));
  3659. if(typeof option == 'string') data[option]();
  3660. });
  3661. };
  3662. $.fn.menu.Constructor = Menu;
  3663. $(function() {
  3664. $('[data-toggle="menu"]').menu();
  3665. });
  3666. }(jQuery));
  3667. /**
  3668. * bootbox.js [v4.4.0]
  3669. *
  3670. * http://bootboxjs.com/license.txt
  3671. * ========================================================================
  3672. * Improvement in ZUI:
  3673. * 1. Determine client language and apply setting automatically.
  3674. * 2. Changed button position.
  3675. * ======================================================================== */
  3676. // @see https://github.com/makeusabrew/bootbox/issues/180
  3677. // @see https://github.com/makeusabrew/bootbox/issues/186
  3678. (function(root, factory) {
  3679. 'use strict';
  3680. if(typeof define === "function" && define.amd) {
  3681. // AMD. Register as an anonymous module.
  3682. define(["jquery"], factory);
  3683. } else if(typeof exports === "object") {
  3684. // Node. Does not work with strict CommonJS, but
  3685. // only CommonJS-like environments that support module.exports,
  3686. // like Node.
  3687. module.exports = factory(require("jquery"));
  3688. } else {
  3689. // Browser globals (root is window)
  3690. root.bootbox = factory(root.jQuery);
  3691. }
  3692. }(this, function init($, undefined) {
  3693. 'use strict';
  3694. // the base DOM structure needed to create a modal
  3695. var templates = {
  3696. dialog: "<div class='bootbox modal' tabindex='-1' role='dialog'>" +
  3697. "<div class='modal-dialog'>" +
  3698. "<div class='modal-content'>" +
  3699. "<div class='modal-body'><div class='bootbox-body'></div></div>" +
  3700. "</div>" +
  3701. "</div>" +
  3702. "</div>",
  3703. header: "<div class='modal-header'>" +
  3704. "<h4 class='modal-title'></h4>" +
  3705. "</div>",
  3706. footer: "<div class='modal-footer'></div>",
  3707. closeButton: "<button type='button' class='bootbox-close-button close' data-dismiss='modal' aria-hidden='true'>&times;</button>",
  3708. form: "<form class='bootbox-form'></form>",
  3709. inputs: {
  3710. text: "<input class='bootbox-input bootbox-input-text form-control' autocomplete=off type=text />",
  3711. textarea: "<textarea class='bootbox-input bootbox-input-textarea form-control'></textarea>",
  3712. email: "<input class='bootbox-input bootbox-input-email form-control' autocomplete='off' type='email' />",
  3713. select: "<select class='bootbox-input bootbox-input-select form-control'></select>",
  3714. checkbox: "<div class='checkbox'><label><input class='bootbox-input bootbox-input-checkbox' type='checkbox' /></label></div>",
  3715. date: "<input class='bootbox-input bootbox-input-date form-control' autocomplete=off type='date' />",
  3716. time: "<input class='bootbox-input bootbox-input-time form-control' autocomplete=off type='time' />",
  3717. number: "<input class='bootbox-input bootbox-input-number form-control' autocomplete=off type='number' />",
  3718. password: "<input class='bootbox-input bootbox-input-password form-control' autocomplete='off' type='password' />"
  3719. }
  3720. };
  3721. var defaults = {
  3722. // default language
  3723. locale: $.zui && $.zui.clientLang ? $.zui.clientLang() : 'zh_cn',
  3724. // show backdrop or not. Default to static so user has to interact with dialog
  3725. backdrop: "static",
  3726. // animate the modal in/out
  3727. animate: true,
  3728. // additional class string applied to the top level dialog
  3729. className: null,
  3730. // whether or not to include a close button
  3731. closeButton: true,
  3732. // show the dialog immediately by default
  3733. show: true,
  3734. // dialog container
  3735. container: "body"
  3736. };
  3737. // our public object; augmented after our private API
  3738. var exports = {};
  3739. function judgeClientLang() {
  3740. var lang;
  3741. if(typeof(config) != 'undefined' && config.clientLang) {
  3742. lang = config.clientLang;
  3743. } else {
  3744. var hl = $('html').attr('lang');
  3745. lang = hl ? hl : 'en';
  3746. }
  3747. return lang.replace('-', '_').toLowerCase();
  3748. }
  3749. /**
  3750. * @private
  3751. */
  3752. function _t(key) {
  3753. var locale = locales[defaults.locale];
  3754. return locale ? locale[key] : locales.en[key];
  3755. }
  3756. function processCallback(e, dialog, callback) {
  3757. e.stopPropagation();
  3758. e.preventDefault();
  3759. // by default we assume a callback will get rid of the dialog,
  3760. // although it is given the opportunity to override this
  3761. // so, if the callback can be invoked and it *explicitly returns false*
  3762. // then we'll set a flag to keep the dialog active...
  3763. var preserveDialog = $.isFunction(callback) && callback.call(dialog, e) === false;
  3764. // ... otherwise we'll bin it
  3765. if(!preserveDialog) {
  3766. dialog.modal("hide");
  3767. }
  3768. }
  3769. function getKeyLength(obj) {
  3770. // @TODO defer to Object.keys(x).length if available?
  3771. var k, t = 0;
  3772. for(k in obj) {
  3773. t++;
  3774. }
  3775. return t;
  3776. }
  3777. function each(collection, iterator) {
  3778. var index = 0;
  3779. $.each(collection, function(key, value) {
  3780. iterator(key, value, index++);
  3781. });
  3782. }
  3783. function sanitize(options) {
  3784. var buttons;
  3785. var total;
  3786. if(typeof options !== "object") {
  3787. throw new Error("Please supply an object of options");
  3788. }
  3789. if(!options.message) {
  3790. throw new Error("Please specify a message");
  3791. }
  3792. // make sure any supplied options take precedence over defaults
  3793. options = $.extend({}, defaults, options);
  3794. if(!options.buttons) {
  3795. options.buttons = {};
  3796. }
  3797. buttons = options.buttons;
  3798. total = getKeyLength(buttons);
  3799. each(buttons, function(key, button, index) {
  3800. if($.isFunction(button)) {
  3801. // short form, assume value is our callback. Since button
  3802. // isn't an object it isn't a reference either so re-assign it
  3803. button = buttons[key] = {
  3804. callback: button
  3805. };
  3806. }
  3807. // before any further checks make sure by now button is the correct type
  3808. if($.type(button) !== "object") {
  3809. throw new Error("button with key " + key + " must be an object");
  3810. }
  3811. if(!button.label) {
  3812. // the lack of an explicit label means we'll assume the key is good enough
  3813. button.label = key;
  3814. }
  3815. if(!button.className) {
  3816. if(total <= 2 && index === total - 1) {
  3817. // always add a primary to the main option in a two-button dialog
  3818. button.className = "btn-primary";
  3819. } else {
  3820. button.className = "btn-default";
  3821. }
  3822. }
  3823. });
  3824. return options;
  3825. }
  3826. /**
  3827. * map a flexible set of arguments into a single returned object
  3828. * if args.length is already one just return it, otherwise
  3829. * use the properties argument to map the unnamed args to
  3830. * object properties
  3831. * so in the latter case:
  3832. * mapArguments(["foo", $.noop], ["message", "callback"])
  3833. * -> { message: "foo", callback: $.noop }
  3834. */
  3835. function mapArguments(args, properties) {
  3836. var argn = args.length;
  3837. var options = {};
  3838. if(argn < 1 || argn > 2) {
  3839. throw new Error("Invalid argument length");
  3840. }
  3841. if(argn === 2 || typeof args[0] === "string") {
  3842. options[properties[0]] = args[0];
  3843. options[properties[1]] = args[1];
  3844. } else {
  3845. options = args[0];
  3846. }
  3847. return options;
  3848. }
  3849. /**
  3850. * merge a set of default dialog options with user supplied arguments
  3851. */
  3852. function mergeArguments(defaults, args, properties) {
  3853. return $.extend(
  3854. // deep merge
  3855. true,
  3856. // ensure the target is an empty, unreferenced object
  3857. {},
  3858. // the base options object for this type of dialog (often just buttons)
  3859. defaults,
  3860. // args could be an object or array; if it's an array properties will
  3861. // map it to a proper options object
  3862. mapArguments(
  3863. args,
  3864. properties
  3865. )
  3866. );
  3867. }
  3868. /**
  3869. * this entry-level method makes heavy use of composition to take a simple
  3870. * range of inputs and return valid options suitable for passing to bootbox.dialog
  3871. */
  3872. function mergeDialogOptions(className, labels, properties, args) {
  3873. // build up a base set of dialog properties
  3874. var baseOptions = {
  3875. className: "bootbox-" + className,
  3876. buttons: createLabels.apply(null, labels)
  3877. };
  3878. // ensure the buttons properties generated, *after* merging
  3879. // with user args are still valid against the supplied labels
  3880. return validateButtons(
  3881. // merge the generated base properties with user supplied arguments
  3882. mergeArguments(
  3883. baseOptions,
  3884. args,
  3885. // if args.length > 1, properties specify how each arg maps to an object key
  3886. properties
  3887. ),
  3888. labels
  3889. );
  3890. }
  3891. /**
  3892. * from a given list of arguments return a suitable object of button labels
  3893. * all this does is normalise the given labels and translate them where possible
  3894. * e.g. "ok", "confirm" -> { ok: "OK, cancel: "Annuleren" }
  3895. */
  3896. function createLabels() {
  3897. var buttons = {};
  3898. for(var i = 0, j = arguments.length; i < j; i++) {
  3899. var argument = arguments[i];
  3900. var key = argument.toLowerCase();
  3901. var value = argument.toUpperCase();
  3902. buttons[key] = {
  3903. label: _t(value)
  3904. };
  3905. }
  3906. return buttons;
  3907. }
  3908. function validateButtons(options, buttons) {
  3909. var allowedButtons = {};
  3910. each(buttons, function(key, value) {
  3911. allowedButtons[value] = true;
  3912. });
  3913. each(options.buttons, function(key) {
  3914. if(allowedButtons[key] === undefined) {
  3915. throw new Error("button key " + key + " is not allowed (options are " + buttons.join("\n") + ")");
  3916. }
  3917. });
  3918. return options;
  3919. }
  3920. exports.alert = function() {
  3921. var options;
  3922. options = mergeDialogOptions("alert", ["ok"], ["message", "callback"], arguments);
  3923. if(options.callback && !$.isFunction(options.callback)) {
  3924. throw new Error("alert requires callback property to be a function when provided");
  3925. }
  3926. /**
  3927. * overrides
  3928. */
  3929. options.buttons.ok.callback = options.onEscape = function() {
  3930. if($.isFunction(options.callback)) {
  3931. return options.callback.call(this);
  3932. }
  3933. return true;
  3934. };
  3935. return exports.dialog(options);
  3936. };
  3937. exports.confirm = function() {
  3938. var options;
  3939. options = mergeDialogOptions("confirm", ["cancel", "confirm"], ["message", "callback"], arguments);
  3940. /**
  3941. * overrides; undo anything the user tried to set they shouldn't have
  3942. */
  3943. options.buttons.cancel.callback = options.onEscape = function() {
  3944. return options.callback.call(this, false);
  3945. };
  3946. options.buttons.confirm.callback = function() {
  3947. return options.callback.call(this, true);
  3948. };
  3949. // confirm specific validation
  3950. if(!$.isFunction(options.callback)) {
  3951. throw new Error("confirm requires a callback");
  3952. }
  3953. return exports.dialog(options);
  3954. };
  3955. exports.prompt = function() {
  3956. var options;
  3957. var defaults;
  3958. var dialog;
  3959. var form;
  3960. var input;
  3961. var shouldShow;
  3962. var inputOptions;
  3963. // we have to create our form first otherwise
  3964. // its value is undefined when gearing up our options
  3965. // @TODO this could be solved by allowing message to
  3966. // be a function instead...
  3967. form = $(templates.form);
  3968. // prompt defaults are more complex than others in that
  3969. // users can override more defaults
  3970. // @TODO I don't like that prompt has to do a lot of heavy
  3971. // lifting which mergeDialogOptions can *almost* support already
  3972. // just because of 'value' and 'inputType' - can we refactor?
  3973. defaults = {
  3974. className: "bootbox-prompt",
  3975. buttons: createLabels("cancel", "confirm"),
  3976. value: "",
  3977. inputType: "text"
  3978. };
  3979. options = validateButtons(
  3980. mergeArguments(defaults, arguments, ["title", "callback"]), ["cancel", "confirm"]
  3981. );
  3982. // capture the user's show value; we always set this to false before
  3983. // spawning the dialog to give us a chance to attach some handlers to
  3984. // it, but we need to make sure we respect a preference not to show it
  3985. shouldShow = (options.show === undefined) ? true : options.show;
  3986. /**
  3987. * overrides; undo anything the user tried to set they shouldn't have
  3988. */
  3989. options.message = form;
  3990. options.buttons.cancel.callback = options.onEscape = function() {
  3991. return options.callback.call(this, null);
  3992. };
  3993. options.buttons.confirm.callback = function() {
  3994. var value;
  3995. switch(options.inputType) {
  3996. case "text":
  3997. case "textarea":
  3998. case "email":
  3999. case "select":
  4000. case "date":
  4001. case "time":
  4002. case "number":
  4003. case "password":
  4004. value = input.val();
  4005. break;
  4006. case "checkbox":
  4007. var checkedItems = input.find("input:checked");
  4008. // we assume that checkboxes are always multiple,
  4009. // hence we default to an empty array
  4010. value = [];
  4011. each(checkedItems, function(_, item) {
  4012. value.push($(item).val());
  4013. });
  4014. break;
  4015. }
  4016. return options.callback.call(this, value);
  4017. };
  4018. options.show = false;
  4019. // prompt specific validation
  4020. if(!options.title) {
  4021. throw new Error("prompt requires a title");
  4022. }
  4023. if(!$.isFunction(options.callback)) {
  4024. throw new Error("prompt requires a callback");
  4025. }
  4026. if(!templates.inputs[options.inputType]) {
  4027. throw new Error("invalid prompt type");
  4028. }
  4029. // create the input based on the supplied type
  4030. input = $(templates.inputs[options.inputType]);
  4031. switch(options.inputType) {
  4032. case "text":
  4033. case "textarea":
  4034. case "email":
  4035. case "date":
  4036. case "time":
  4037. case "number":
  4038. case "password":
  4039. input.val(options.value);
  4040. break;
  4041. case "select":
  4042. var groups = {};
  4043. inputOptions = options.inputOptions || [];
  4044. if(!$.isArray(inputOptions)) {
  4045. throw new Error("Please pass an array of input options");
  4046. }
  4047. if(!inputOptions.length) {
  4048. throw new Error("prompt with select requires options");
  4049. }
  4050. each(inputOptions, function(_, option) {
  4051. // assume the element to attach to is the input...
  4052. var elem = input;
  4053. if(option.value === undefined || option.text === undefined) {
  4054. throw new Error("given options in wrong format");
  4055. }
  4056. // ... but override that element if this option sits in a group
  4057. if(option.group) {
  4058. // initialise group if necessary
  4059. if(!groups[option.group]) {
  4060. groups[option.group] = $("<optgroup/>").attr("label", option.group);
  4061. }
  4062. elem = groups[option.group];
  4063. }
  4064. elem.append("<option value='" + option.value + "'>" + option.text + "</option>");
  4065. });
  4066. each(groups, function(_, group) {
  4067. input.append(group);
  4068. });
  4069. // safe to set a select's value as per a normal input
  4070. input.val(options.value);
  4071. break;
  4072. case "checkbox":
  4073. var values = $.isArray(options.value) ? options.value : [options.value];
  4074. inputOptions = options.inputOptions || [];
  4075. if(!inputOptions.length) {
  4076. throw new Error("prompt with checkbox requires options");
  4077. }
  4078. if(!inputOptions[0].value || !inputOptions[0].text) {
  4079. throw new Error("given options in wrong format");
  4080. }
  4081. // checkboxes have to nest within a containing element, so
  4082. // they break the rules a bit and we end up re-assigning
  4083. // our 'input' element to this container instead
  4084. input = $("<div/>");
  4085. each(inputOptions, function(_, option) {
  4086. var checkbox = $(templates.inputs[options.inputType]);
  4087. checkbox.find("input").attr("value", option.value);
  4088. checkbox.find("label").append(option.text);
  4089. // we've ensured values is an array so we can always iterate over it
  4090. each(values, function(_, value) {
  4091. if(value === option.value) {
  4092. checkbox.find("input").prop("checked", true);
  4093. }
  4094. });
  4095. input.append(checkbox);
  4096. });
  4097. break;
  4098. }
  4099. // @TODO provide an attributes option instead
  4100. // and simply map that as keys: vals
  4101. if(options.placeholder) {
  4102. input.attr("placeholder", options.placeholder);
  4103. }
  4104. if(options.pattern) {
  4105. input.attr("pattern", options.pattern);
  4106. }
  4107. if(options.maxlength) {
  4108. input.attr("maxlength", options.maxlength);
  4109. }
  4110. // now place it in our form
  4111. form.append(input);
  4112. form.on("submit", function(e) {
  4113. e.preventDefault();
  4114. // Fix for SammyJS (or similar JS routing library) hijacking the form post.
  4115. e.stopPropagation();
  4116. // @TODO can we actually click *the* button object instead?
  4117. // e.g. buttons.confirm.click() or similar
  4118. dialog.find(".btn-primary").click();
  4119. });
  4120. dialog = exports.dialog(options);
  4121. // clear the existing handler focusing the submit button...
  4122. dialog.off("shown.zui.modal");
  4123. // ...and replace it with one focusing our input, if possible
  4124. dialog.on("shown.zui.modal", function() {
  4125. // need the closure here since input isn't
  4126. // an object otherwise
  4127. input.focus();
  4128. });
  4129. if(shouldShow === true) {
  4130. dialog.modal("show");
  4131. }
  4132. return dialog;
  4133. };
  4134. exports.dialog = function(options) {
  4135. options = sanitize(options);
  4136. var dialog = $(templates.dialog);
  4137. var innerDialog = dialog.find(".modal-dialog");
  4138. var body = dialog.find(".modal-body");
  4139. var buttons = options.buttons;
  4140. var buttonStr = "";
  4141. var callbacks = {
  4142. onEscape: options.onEscape
  4143. };
  4144. if($.fn.modal === undefined) {
  4145. throw new Error(
  4146. "$.fn.modal is not defined; please double check you have included " +
  4147. "the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ " +
  4148. "for more details."
  4149. );
  4150. }
  4151. each(buttons, function(key, button) {
  4152. // @TODO I don't like this string appending to itself; bit dirty. Needs reworking
  4153. // can we just build up button elements instead? slower but neater. Then button
  4154. // can just become a template too
  4155. buttonStr += "<button data-bb-handler='" + key + "' type='button' class='btn " + button.className + "'>" + button.label + "</button>";
  4156. callbacks[key] = button.callback;
  4157. });
  4158. body.find(".bootbox-body").html(options.message);
  4159. if(options.animate === true) {
  4160. dialog.addClass("fade");
  4161. }
  4162. if(options.className) {
  4163. dialog.addClass(options.className);
  4164. }
  4165. if(options.size === "large") {
  4166. innerDialog.addClass("modal-lg");
  4167. } else if(options.size === "small") {
  4168. innerDialog.addClass("modal-sm");
  4169. }
  4170. if(options.title) {
  4171. body.before(templates.header);
  4172. }
  4173. if(options.closeButton) {
  4174. var closeButton = $(templates.closeButton);
  4175. if(options.title) {
  4176. dialog.find(".modal-header").prepend(closeButton);
  4177. } else {
  4178. closeButton.css("margin-top", "-10px").prependTo(body);
  4179. }
  4180. }
  4181. if(options.title) {
  4182. dialog.find(".modal-title").html(options.title);
  4183. }
  4184. if(buttonStr.length) {
  4185. body.after(templates.footer);
  4186. dialog.find(".modal-footer").html(buttonStr);
  4187. }
  4188. /**
  4189. * Bootstrap event listeners; used handle extra
  4190. * setup & teardown required after the underlying
  4191. * modal has performed certain actions
  4192. */
  4193. dialog.on("hidden.zui.modal", function(e) {
  4194. // ensure we don't accidentally intercept hidden events triggered
  4195. // by children of the current dialog. We shouldn't anymore now BS
  4196. // namespaces its events; but still worth doing
  4197. if(e.target === this) {
  4198. dialog.remove();
  4199. }
  4200. });
  4201. /*
  4202. dialog.on("show.zui.modal", function() {
  4203. // sadly this doesn't work; show is called *just* before
  4204. // the backdrop is added so we'd need a setTimeout hack or
  4205. // otherwise... leaving in as would be nice
  4206. if (options.backdrop) {
  4207. dialog.next(".modal-backdrop").addClass("bootbox-backdrop");
  4208. }
  4209. });
  4210. */
  4211. dialog.on("shown.zui.modal", function() {
  4212. dialog.find(".btn-primary:first").focus();
  4213. });
  4214. /**
  4215. * Bootbox event listeners; experimental and may not last
  4216. * just an attempt to decouple some behaviours from their
  4217. * respective triggers
  4218. */
  4219. if(options.backdrop !== "static") {
  4220. // A boolean true/false according to the Bootstrap docs
  4221. // should show a dialog the user can dismiss by clicking on
  4222. // the background.
  4223. // We always only ever pass static/false to the actual
  4224. // $.modal function because with `true` we can't trap
  4225. // this event (the .modal-backdrop swallows it)
  4226. // However, we still want to sort of respect true
  4227. // and invoke the escape mechanism instead
  4228. dialog.on("click.dismiss.zui.modal", function(e) {
  4229. // @NOTE: the target varies in >= 3.3.x releases since the modal backdrop
  4230. // moved *inside* the outer dialog rather than *alongside* it
  4231. if(dialog.children(".modal-backdrop").length) {
  4232. e.currentTarget = dialog.children(".modal-backdrop").get(0);
  4233. }
  4234. if(e.target !== e.currentTarget) {
  4235. return;
  4236. }
  4237. dialog.trigger("escape.close.bb");
  4238. });
  4239. }
  4240. dialog.on("escape.close.bb", function(e) {
  4241. if(callbacks.onEscape) {
  4242. processCallback(e, dialog, callbacks.onEscape);
  4243. }
  4244. });
  4245. /**
  4246. * Standard jQuery event listeners; used to handle user
  4247. * interaction with our dialog
  4248. */
  4249. dialog.on("click", ".modal-footer button", function(e) {
  4250. var callbackKey = $(this).data("bb-handler");
  4251. processCallback(e, dialog, callbacks[callbackKey]);
  4252. });
  4253. dialog.on("click", ".bootbox-close-button", function(e) {
  4254. // onEscape might be falsy but that's fine; the fact is
  4255. // if the user has managed to click the close button we
  4256. // have to close the dialog, callback or not
  4257. processCallback(e, dialog, callbacks.onEscape);
  4258. });
  4259. dialog.on("keyup", function(e) {
  4260. if(e.which === 27) {
  4261. dialog.trigger("escape.close.bb");
  4262. }
  4263. });
  4264. // the remainder of this method simply deals with adding our
  4265. // dialogent to the DOM, augmenting it with Bootstrap's modal
  4266. // functionality and then giving the resulting object back
  4267. // to our caller
  4268. $(options.container).append(dialog);
  4269. dialog.modal({
  4270. backdrop: options.backdrop ? "static" : false,
  4271. keyboard: false,
  4272. show: false
  4273. });
  4274. if(options.show) {
  4275. dialog.modal("show");
  4276. }
  4277. // @TODO should we return the raw element here or should
  4278. // we wrap it in an object on which we can expose some neater
  4279. // methods, e.g. var d = bootbox.alert(); d.hide(); instead
  4280. // of d.modal("hide");
  4281. /*
  4282. function BBDialog(elem) {
  4283. this.elem = elem;
  4284. }
  4285. BBDialog.prototype = {
  4286. hide: function() {
  4287. return this.elem.modal("hide");
  4288. },
  4289. show: function() {
  4290. return this.elem.modal("show");
  4291. }
  4292. };
  4293. */
  4294. return dialog;
  4295. };
  4296. exports.setDefaults = function() {
  4297. var values = {};
  4298. if(arguments.length === 2) {
  4299. // allow passing of single key/value...
  4300. values[arguments[0]] = arguments[1];
  4301. } else {
  4302. // ... and as an object too
  4303. values = arguments[0];
  4304. }
  4305. $.extend(defaults, values);
  4306. };
  4307. exports.hideAll = function() {
  4308. $(".bootbox").modal("hide");
  4309. return exports;
  4310. };
  4311. /**
  4312. * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are
  4313. * unlikely to be required. If this gets too large it can be split out into separate JS files.
  4314. */
  4315. var locales = {
  4316. en: {
  4317. OK: "OK",
  4318. CANCEL: "Cancel",
  4319. CONFIRM: "OK"
  4320. },
  4321. zh_cn: {
  4322. OK: "确认",
  4323. CANCEL: "取消",
  4324. CONFIRM: "确认"
  4325. },
  4326. zh_tw: {
  4327. OK: "確認",
  4328. CANCEL: "取消",
  4329. CONFIRM: "確認"
  4330. }
  4331. };
  4332. exports.addLocale = function(name, values) {
  4333. $.each(["OK", "CANCEL", "CONFIRM"], function(_, v) {
  4334. if(!values[v]) {
  4335. throw new Error("Please supply a translation for '" + v + "'");
  4336. }
  4337. });
  4338. locales[name] = {
  4339. OK: values.OK,
  4340. CANCEL: values.CANCEL,
  4341. CONFIRM: values.CONFIRM
  4342. };
  4343. return exports;
  4344. };
  4345. exports.removeLocale = function(name) {
  4346. delete locales[name];
  4347. return exports;
  4348. };
  4349. exports.setLocale = function(name) {
  4350. return exports.setDefaults("locale", name);
  4351. };
  4352. exports.init = function(_$) {
  4353. return init(_$ || $);
  4354. };
  4355. return exports;
  4356. }));
  4357. /* ========================================================================
  4358. * ZUI: dashboard.js
  4359. * http://zui.sexy
  4360. * ========================================================================
  4361. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  4362. * ======================================================================== */
  4363. (function($, Math) {
  4364. 'use strict';
  4365. var Dashboard = function(element, options) {
  4366. this.$ = $(element);
  4367. this.options = this.getOptions(options);
  4368. this.draggable = this.$.hasClass('dashboard-draggable') || this.options.draggable;
  4369. this.init();
  4370. };
  4371. Dashboard.DEFAULTS = {
  4372. height: 360,
  4373. shadowType: 'normal',
  4374. sensitive: false,
  4375. circleShadowSize: 100
  4376. };
  4377. Dashboard.prototype.getOptions = function(options) {
  4378. options = $.extend({}, Dashboard.DEFAULTS, this.$.data(), options);
  4379. return options;
  4380. };
  4381. Dashboard.prototype.handleRemoveEvent = function() {
  4382. var afterPanelRemoved = this.options.afterPanelRemoved;
  4383. var tip = this.options.panelRemovingTip;
  4384. this.$.on('click', '.remove-panel', function() {
  4385. var panel = $(this).closest('.panel');
  4386. var name = panel.data('name') || panel.find('.panel-heading').text().replace('\n', '').replace(/(^\s*)|(\s*$)/g, '');
  4387. var index = panel.attr('data-id');
  4388. if(tip === undefined || confirm(tip.format(name))) {
  4389. panel.parent().remove();
  4390. if(afterPanelRemoved && $.isFunction(afterPanelRemoved)) {
  4391. afterPanelRemoved(index);
  4392. }
  4393. }
  4394. });
  4395. };
  4396. Dashboard.prototype.handleRefreshEvent = function() {
  4397. this.$.on('click', '.refresh-panel', function() {
  4398. var panel = $(this).closest('.panel');
  4399. refreshPanel(panel);
  4400. });
  4401. };
  4402. Dashboard.prototype.handleDraggable = function() {
  4403. var dashboard = this.$;
  4404. var options = this.options;
  4405. var circleShadow = options.shadowType === 'circle';
  4406. var circleSize = options.circleShadowSize;
  4407. var halfCircleSize = circleSize / 2;
  4408. var afterOrdered = options.afterOrdered;
  4409. this.$.addClass('dashboard-draggable');
  4410. this.$.find('.panel-actions').mousedown(function(event) {
  4411. event.preventDefault();
  4412. event.stopPropagation();
  4413. });
  4414. var pColClass;
  4415. this.$.find('.panel-heading').mousedown(function(event) {
  4416. // console.log('--------------------------------');
  4417. var panel = $(this).closest('.panel');
  4418. var pCol = panel.parent();
  4419. var row = panel.closest('.row');
  4420. var dPanel = panel.clone().addClass('panel-dragging-shadow');
  4421. var pos = panel.offset();
  4422. var dPos = dashboard.offset();
  4423. var dColShadow = row.find('.dragging-col-holder');
  4424. var sWidth = panel.width(),
  4425. sHeight = panel.height(),
  4426. sX1, sY1, sX2, sY2, moveFn, dropCol, dropBefore, nextDropCol;
  4427. if(!dColShadow.length) {
  4428. dColShadow = $('<div class="dragging-col-holder"><div class="panel"></div></div>').removeClass('dragging-col').appendTo(row);
  4429. }
  4430. if(pColClass) dColShadow.removeClass(pColClass);
  4431. dColShadow.addClass(pColClass = pCol.attr('class'));
  4432. dColShadow.insertBefore(pCol).find('.panel').replaceWith(panel.clone().addClass('panel-dragging panel-dragging-holder'));
  4433. dashboard.addClass('dashboard-dragging');
  4434. panel.addClass('panel-dragging').parent().addClass('dragging-col');
  4435. dPanel.css({
  4436. left: pos.left - dPos.left,
  4437. top: pos.top - dPos.top,
  4438. width: sWidth,
  4439. height: sHeight
  4440. }).appendTo(dashboard).data('mouseOffset', {
  4441. x: event.pageX - pos.left + dPos.left,
  4442. y: event.pageY - pos.top + dPos.top
  4443. });
  4444. if(circleShadow) {
  4445. dPanel.addClass('circle');
  4446. setTimeout(function() {
  4447. dPanel.css({
  4448. left: event.pageX - dPos.left - halfCircleSize,
  4449. top: event.pageY - dPos.top - halfCircleSize,
  4450. width: circleSize,
  4451. height: circleSize
  4452. }).data('mouseOffset', {
  4453. x: dPos.left + halfCircleSize,
  4454. y: dPos.top + halfCircleSize
  4455. });
  4456. }, 100);
  4457. }
  4458. $(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp);
  4459. event.preventDefault();
  4460. function mouseMove(event) {
  4461. // console.log('......................');
  4462. var offset = dPanel.data('mouseOffset');
  4463. sX1 = event.pageX - offset.x;
  4464. sY1 = event.pageY - offset.y;
  4465. sX2 = sX1 + sWidth;
  4466. sY2 = sY1 + sHeight;
  4467. dPanel.css({
  4468. left: sX1,
  4469. top: sY1
  4470. });
  4471. row.find('.dragging-in').removeClass('dragging-in');
  4472. dropBefore = false;
  4473. dropCol = null;
  4474. var area = 0,
  4475. thisArea;
  4476. row.children(':not(.dragging-col)').each(function() {
  4477. var col = $(this);
  4478. if(col.hasClass('dragging-col-holder')) {
  4479. dropBefore = (!options.sensitive) || (area < 100);
  4480. return true;
  4481. }
  4482. var p = col.children('.panel');
  4483. var pP = p.offset(),
  4484. pW = p.width(),
  4485. pH = p.height();
  4486. var pX = pP.left,
  4487. pY = pP.top;
  4488. if(options.sensitive) {
  4489. pX -= dPos.left;
  4490. pY -= dPos.top;
  4491. thisArea = getIntersectArea(sX1, sY1, sX2, sY2, pX, pY, pX + pW, pY + pH);
  4492. if(thisArea > 100 && thisArea > area && thisArea > Math.min(getRectArea(sX1, sY1, sX2, sY2), getRectArea(pX, pY, pX + pW, pY + pH)) / 3) {
  4493. area = thisArea;
  4494. dropCol = col;
  4495. }
  4496. // if(thisArea)
  4497. // {
  4498. // console.log('panel ' + col.data('id'), '({0}, {1}, {2}, {3}), ({4}, {5}, {6}, {7})'.format(sX1, sY1, sX2, sY2, pX, pY, pX + pW, pY + pH));
  4499. // }
  4500. } else {
  4501. var mX = event.pageX,
  4502. mY = event.pageY;
  4503. if(mX > pX && mY > pY && mX < (pX + pW) && mY < (pY + pH)) {
  4504. // var dCol = row.find('.dragging-col');
  4505. dropCol = col;
  4506. return false;
  4507. }
  4508. }
  4509. });
  4510. if(dropCol) {
  4511. if(moveFn) clearTimeout(moveFn);
  4512. nextDropCol = dropCol;
  4513. moveFn = setTimeout(movePanel, 50);
  4514. }
  4515. event.preventDefault();
  4516. }
  4517. function movePanel() {
  4518. if(nextDropCol) {
  4519. nextDropCol.addClass('dragging-in');
  4520. if(dropBefore) dColShadow.insertAfter(nextDropCol);
  4521. else dColShadow.insertBefore(nextDropCol);
  4522. dashboard.addClass('dashboard-holding');
  4523. moveFn = null;
  4524. nextDropCol = null;
  4525. }
  4526. }
  4527. function mouseUp(event) {
  4528. if(moveFn) clearTimeout(moveFn);
  4529. var oldOrder = panel.data('order');
  4530. panel.parent().insertAfter(dColShadow);
  4531. var newOrder = 0;
  4532. var newOrders = {};
  4533. row.children(':not(.dragging-col-holder)').each(function() {
  4534. var p = $(this).children('.panel');
  4535. p.data('order', ++newOrder);
  4536. newOrders[p.attr('id')] = newOrder;
  4537. p.parent().attr('data-order', newOrder);
  4538. });
  4539. if(oldOrder != newOrders[panel.attr('id')]) {
  4540. row.data('orders', newOrders);
  4541. if(afterOrdered && $.isFunction(afterOrdered)) {
  4542. afterOrdered(newOrders);
  4543. }
  4544. }
  4545. dPanel.remove();
  4546. dashboard.removeClass('dashboard-holding');
  4547. dashboard.find('.dragging-col').removeClass('dragging-col');
  4548. dashboard.find('.panel-dragging').removeClass('panel-dragging');
  4549. row.find('.dragging-in').removeClass('dragging-in');
  4550. dashboard.removeClass('dashboard-dragging');
  4551. $(document).unbind('mousemove', mouseMove).unbind('mouseup', mouseUp);
  4552. event.preventDefault();
  4553. }
  4554. });
  4555. };
  4556. Dashboard.prototype.handlePanelPadding = function() {
  4557. this.$.find('.panel-body > table, .panel-body > .list-group').closest('.panel-body').addClass('no-padding');
  4558. };
  4559. Dashboard.prototype.handlePanelHeight = function() {
  4560. var dHeight = this.options.height;
  4561. this.$.find('.row').each(function() {
  4562. var row = $(this);
  4563. var panels = row.find('.panel');
  4564. var height = row.data('height') || dHeight;
  4565. if(typeof height != 'number') {
  4566. height = 0;
  4567. panels.each(function() {
  4568. height = Math.max(height, $(this).innerHeight());
  4569. });
  4570. }
  4571. panels.each(function() {
  4572. var $this = $(this);
  4573. $this.find('.panel-body').css('height', height - $this.find('.panel-heading').outerHeight() - 2);
  4574. });
  4575. });
  4576. };
  4577. function refreshPanel(panel) {
  4578. var url = panel.data('url');
  4579. if(!url) return;
  4580. panel.addClass('panel-loading').find('.panel-heading .icon-refresh,.panel-heading .icon-repeat').addClass('icon-spin');
  4581. $.ajax({
  4582. url: url,
  4583. dataType: 'html'
  4584. }).done(function(data) {
  4585. panel.find('.panel-body').html(data);
  4586. }).fail(function() {
  4587. panel.addClass('panel-error');
  4588. }).always(function() {
  4589. panel.removeClass('panel-loading');
  4590. panel.find('.panel-heading .icon-refresh,.panel-heading .icon-repeat').removeClass('icon-spin');
  4591. });
  4592. }
  4593. function getRectArea(x1, y1, x2, y2) {
  4594. return Math.abs((x2 - x1) * (y2 - y1));
  4595. }
  4596. function isPointInner(x, y, x1, y1, x2, y2) {
  4597. return x >= x1 && x <= x2 && y >= y1 && y <= y2;
  4598. }
  4599. function getIntersectArea(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) {
  4600. var x1 = Math.max(ax1, bx1),
  4601. y1 = Math.max(ay1, by1),
  4602. x2 = Math.min(ax2, bx2),
  4603. y2 = Math.min(ay2, by2);
  4604. if(isPointInner(x1, y1, ax1, ay1, ax2, ay2) && isPointInner(x2, y2, ax1, ay1, ax2, ay2) && isPointInner(x1, y1, bx1, by1, bx2, by2) && isPointInner(x2, y2, bx1, by1, bx2, by2)) {
  4605. return getRectArea(x1, y1, x2, y2);
  4606. }
  4607. return 0;
  4608. }
  4609. Dashboard.prototype.init = function() {
  4610. this.handlePanelHeight();
  4611. this.handlePanelPadding();
  4612. this.handleRemoveEvent();
  4613. this.handleRefreshEvent();
  4614. if(this.draggable) this.handleDraggable();
  4615. var orderSeed = 0;
  4616. this.$.find('.panel').each(function() {
  4617. var $this = $(this);
  4618. $this.data('order', ++orderSeed);
  4619. if(!$this.attr('id')) {
  4620. $this.attr('id', 'panel' + orderSeed);
  4621. }
  4622. if(!$this.attr('data-id')) {
  4623. $this.attr('data-id', orderSeed);
  4624. }
  4625. refreshPanel($this);
  4626. });
  4627. };
  4628. $.fn.dashboard = function(option) {
  4629. return this.each(function() {
  4630. var $this = $(this);
  4631. var data = $this.data('zui.dashboard');
  4632. var options = typeof option == 'object' && option;
  4633. if(!data) $this.data('zui.dashboard', (data = new Dashboard(this, options)));
  4634. if(typeof option == 'string') data[option]();
  4635. });
  4636. };
  4637. $.fn.dashboard.Constructor = Dashboard;
  4638. }(jQuery, Math));
  4639. /* ========================================================================
  4640. * ZUI: boards.js
  4641. * http://zui.sexy
  4642. * ========================================================================
  4643. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  4644. * ======================================================================== */
  4645. (function($) {
  4646. 'use strict';
  4647. if(!$.fn.droppable) throw new Error('Droppable requires for boards');
  4648. var Boards = function(element, options) {
  4649. this.$ = $(element);
  4650. this.options = this.getOptions(options);
  4651. this.getLang();
  4652. this.init();
  4653. };
  4654. Boards.DEFAULTS = {
  4655. lang: 'zh-cn',
  4656. langs: {
  4657. 'zh-cn': {
  4658. append2end: '移动到末尾'
  4659. },
  4660. 'zh-tw': {
  4661. append2end: '移动到末尾'
  4662. },
  4663. 'en': {
  4664. append2end: 'Move to the end.'
  4665. }
  4666. }
  4667. }; // default options
  4668. Boards.prototype.getOptions = function(options) {
  4669. options = $.extend({}, Boards.DEFAULTS, this.$.data(), options);
  4670. return options;
  4671. };
  4672. Boards.prototype.getLang = function() {
  4673. var config = window.config;
  4674. if(!this.options.lang) {
  4675. if(typeof(config) != 'undefined' && config.clientLang) {
  4676. this.options.lang = config.clientLang;
  4677. } else {
  4678. var hl = $('html').attr('lang');
  4679. this.options.lang = hl ? hl : 'en';
  4680. }
  4681. this.options.lang = this.options.lang.replace(/-/, '_').toLowerCase();
  4682. }
  4683. this.lang = this.options.langs[this.options.lang] || this.options.langs[Boards.DEFAULTS.lang];
  4684. };
  4685. Boards.prototype.init = function() {
  4686. var idSeed = 1;
  4687. var lang = this.lang;
  4688. this.$.find('.board-item:not(".disable-drop"), .board:not(".disable-drop")').each(function() {
  4689. var $this = $(this);
  4690. if($this.attr('id')) {
  4691. $this.attr('data-id', $this.attr('id'));
  4692. } else if(!$this.attr('data-id')) {
  4693. $this.attr('data-id', 'board' + (idSeed++));
  4694. }
  4695. if($this.hasClass('board')) {
  4696. $this.find('.board-list').append('<div class="board-item board-item-empty"><i class="icon-plus"></i> {append2end}</div>'.format(lang))
  4697. .append('<div class="board-item board-item-shadow"></div>'.format(lang));
  4698. }
  4699. });
  4700. this.bind();
  4701. };
  4702. Boards.prototype.bind = function(items) {
  4703. var $boards = this.$,
  4704. setting = this.options;
  4705. if(typeof(items) == 'undefined') {
  4706. items = $boards.find('.board-item:not(".disable-drop, .board-item-shadow")');
  4707. }
  4708. items.droppable({
  4709. before: setting.before,
  4710. target: '.board-item:not(".disable-drop, .board-item-shadow")',
  4711. flex: true,
  4712. start: function(e) {
  4713. $boards.addClass('dragging').find('.board-item-shadow').height(e.element.outerHeight());
  4714. },
  4715. drag: function(e) {
  4716. $boards.find('.board.drop-in-empty').removeClass('drop-in-empty');
  4717. if(e.isIn) {
  4718. var board = e.target.closest('.board').addClass('drop-in');
  4719. var shadow = board.find('.board-item-shadow');
  4720. var target = e.target;
  4721. $boards.addClass('drop-in').find('.board.drop-in').not(board).removeClass('drop-in');
  4722. shadow.insertBefore(target);
  4723. board.toggleClass('drop-in-empty', target.hasClass('board-item-empty'));
  4724. }
  4725. },
  4726. drop: function(e) {
  4727. if(e.isNew) {
  4728. var DROP = 'drop';
  4729. var result;
  4730. if(setting.hasOwnProperty(DROP) && $.isFunction(setting[DROP])) {
  4731. result = setting[DROP](e);
  4732. }
  4733. if(result !== false) e.element.insertBefore(e.target);
  4734. }
  4735. },
  4736. finish: function() {
  4737. $boards.removeClass('dragging').removeClass('drop-in').find('.board.drop-in').removeClass('drop-in');
  4738. }
  4739. });
  4740. };
  4741. $.fn.boards = function(option) {
  4742. return this.each(function() {
  4743. var $this = $(this);
  4744. var data = $this.data('zui.boards');
  4745. var options = typeof option == 'object' && option;
  4746. if(!data) $this.data('zui.boards', (data = new Boards(this, options)));
  4747. if(typeof option == 'string') data[option]();
  4748. });
  4749. };
  4750. $.fn.boards.Constructor = Boards;
  4751. $(function() {
  4752. $('[data-toggle="boards"]').boards();
  4753. });
  4754. }(jQuery));
  4755. /* ========================================================================
  4756. * ZUI: color.js
  4757. * http://zui.sexy
  4758. * ========================================================================
  4759. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  4760. * ======================================================================== */
  4761. (function($, Math, window) {
  4762. 'use strict';
  4763. var hexReg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
  4764. var namedColors = {
  4765. aliceblue: '#f0f8ff',
  4766. antiquewhite: '#faebd7',
  4767. aqua: '#00ffff',
  4768. aquamarine: '#7fffd4',
  4769. azure: '#f0ffff',
  4770. beige: '#f5f5dc',
  4771. bisque: '#ffe4c4',
  4772. black: '#000000',
  4773. blanchedalmond: '#ffebcd',
  4774. blue: '#0000ff',
  4775. blueviolet: '#8a2be2',
  4776. brown: '#a52a2a',
  4777. burlywood: '#deb887',
  4778. cadetblue: '#5f9ea0',
  4779. chartreuse: '#7fff00',
  4780. chocolate: '#d2691e',
  4781. coral: '#ff7f50',
  4782. cornflowerblue: '#6495ed',
  4783. cornsilk: '#fff8dc',
  4784. crimson: '#dc143c',
  4785. cyan: '#00ffff',
  4786. darkblue: '#00008b',
  4787. darkcyan: '#008b8b',
  4788. darkgoldenrod: '#b8860b',
  4789. darkgray: '#a9a9a9',
  4790. darkgreen: '#006400',
  4791. darkkhaki: '#bdb76b',
  4792. darkmagenta: '#8b008b',
  4793. darkolivegreen: '#556b2f',
  4794. darkorange: '#ff8c00',
  4795. darkorchid: '#9932cc',
  4796. darkred: '#8b0000',
  4797. darksalmon: '#e9967a',
  4798. darkseagreen: '#8fbc8f',
  4799. darkslateblue: '#483d8b',
  4800. darkslategray: '#2f4f4f',
  4801. darkturquoise: '#00ced1',
  4802. darkviolet: '#9400d3',
  4803. deeppink: '#ff1493',
  4804. deepskyblue: '#00bfff',
  4805. dimgray: '#696969',
  4806. dodgerblue: '#1e90ff',
  4807. firebrick: '#b22222',
  4808. floralwhite: '#fffaf0',
  4809. forestgreen: '#228b22',
  4810. fuchsia: '#ff00ff',
  4811. gainsboro: '#dcdcdc',
  4812. ghostwhite: '#f8f8ff',
  4813. gold: '#ffd700',
  4814. goldenrod: '#daa520',
  4815. gray: '#808080',
  4816. green: '#008000',
  4817. greenyellow: '#adff2f',
  4818. honeydew: '#f0fff0',
  4819. hotpink: '#ff69b4',
  4820. indianred: '#cd5c5c',
  4821. indigo: '#4b0082',
  4822. ivory: '#fffff0',
  4823. khaki: '#f0e68c',
  4824. lavender: '#e6e6fa',
  4825. lavenderblush: '#fff0f5',
  4826. lawngreen: '#7cfc00',
  4827. lemonchiffon: '#fffacd',
  4828. lightblue: '#add8e6',
  4829. lightcoral: '#f08080',
  4830. lightcyan: '#e0ffff',
  4831. lightgoldenrodyellow: '#fafad2',
  4832. lightgray: '#d3d3d3',
  4833. lightgreen: '#90ee90',
  4834. lightpink: '#ffb6c1',
  4835. lightsalmon: '#ffa07a',
  4836. lightseagreen: '#20b2aa',
  4837. lightskyblue: '#87cefa',
  4838. lightslategray: '#778899',
  4839. lightsteelblue: '#b0c4de',
  4840. lightyellow: '#ffffe0',
  4841. lime: '#00ff00',
  4842. limegreen: '#32cd32',
  4843. linen: '#faf0e6',
  4844. magenta: '#ff00ff',
  4845. maroon: '#800000',
  4846. mediumaquamarine: '#66cdaa',
  4847. mediumblue: '#0000cd',
  4848. mediumorchid: '#ba55d3',
  4849. mediumpurple: '#9370db',
  4850. mediumseagreen: '#3cb371',
  4851. mediumslateblue: '#7b68ee',
  4852. mediumspringgreen: '#00fa9a',
  4853. mediumturquoise: '#48d1cc',
  4854. mediumvioletred: '#c71585',
  4855. midnightblue: '#191970',
  4856. mintcream: '#f5fffa',
  4857. mistyrose: '#ffe4e1',
  4858. moccasin: '#ffe4b5',
  4859. navajowhite: '#ffdead',
  4860. navy: '#000080',
  4861. oldlace: '#fdf5e6',
  4862. olive: '#808000',
  4863. olivedrab: '#6b8e23',
  4864. orange: '#ffa500',
  4865. orangered: '#ff4500',
  4866. orchid: '#da70d6',
  4867. palegoldenrod: '#eee8aa',
  4868. palegreen: '#98fb98',
  4869. paleturquoise: '#afeeee',
  4870. palevioletred: '#db7093',
  4871. papayawhip: '#ffefd5',
  4872. peachpuff: '#ffdab9',
  4873. peru: '#cd853f',
  4874. pink: '#ffc0cb',
  4875. plum: '#dda0dd',
  4876. powderblue: '#b0e0e6',
  4877. purple: '#800080',
  4878. red: '#ff0000',
  4879. rosybrown: '#bc8f8f',
  4880. royalblue: '#4169e1',
  4881. saddlebrown: '#8b4513',
  4882. salmon: '#fa8072',
  4883. sandybrown: '#f4a460',
  4884. seagreen: '#2e8b57',
  4885. seashell: '#fff5ee',
  4886. sienna: '#a0522d',
  4887. silver: '#c0c0c0',
  4888. skyblue: '#87ceeb',
  4889. slateblue: '#6a5acd',
  4890. slategray: '#708090',
  4891. snow: '#fffafa',
  4892. springgreen: '#00ff7f',
  4893. steelblue: '#4682b4',
  4894. tan: '#d2b48c',
  4895. teal: '#008080',
  4896. thistle: '#d8bfd8',
  4897. tomato: '#ff6347',
  4898. turquoise: '#40e0d0',
  4899. violet: '#ee82ee',
  4900. wheat: '#f5deb3',
  4901. white: '#ffffff',
  4902. whitesmoke: '#f5f5f5',
  4903. yellow: '#ffff00',
  4904. yellowgreen: '#9acd32'
  4905. };
  4906. /* color */
  4907. var Color = function(r, g, b, a) {
  4908. this.r = 0;
  4909. this.g = 0;
  4910. this.b = 0;
  4911. this.a = 1;
  4912. if(a !== undefined) this.a = clamp(number(a), 1);
  4913. if(r !== undefined && g !== undefined && b !== undefined) {
  4914. this.r = parseInt(clamp(number(r), 255));
  4915. this.g = parseInt(clamp(number(g), 255));
  4916. this.b = parseInt(clamp(number(b), 255));
  4917. } else if(r !== undefined) {
  4918. var type = typeof(r);
  4919. if(type == 'string') {
  4920. r = r.toLowerCase();
  4921. if(r === 'transparent') {
  4922. this.a = 0;
  4923. } else if(namedColors[r]) {
  4924. this.rgb(hexToRgb(namedColors[r]));
  4925. } else {
  4926. this.rgb(hexToRgb(r));
  4927. }
  4928. } else if(type == 'number' && g === undefined) {
  4929. this.r = parseInt(clamp(r, 255));
  4930. this.g = this.r;
  4931. this.b = this.r;
  4932. } else if(type == 'object' && r.hasOwnProperty('r')) {
  4933. this.r = parseInt(clamp(number(r.r), 255));
  4934. if(r.hasOwnProperty('g')) this.g = parseInt(clamp(number(r.g), 255));
  4935. if(r.hasOwnProperty('b')) this.b = parseInt(clamp(number(r.b), 255));
  4936. if(r.hasOwnProperty('a')) this.a = clamp(number(r.a), 1);
  4937. } else if(type == 'object' && r.hasOwnProperty('h')) {
  4938. var hsl = {
  4939. h: clamp(number(r.h), 360),
  4940. s: 1,
  4941. l: 1,
  4942. a: 1
  4943. };
  4944. if(r.hasOwnProperty('s')) hsl.s = clamp(number(r.s), 1);
  4945. if(r.hasOwnProperty('l')) hsl.l = clamp(number(r.l), 1);
  4946. if(r.hasOwnProperty('a')) hsl.a = clamp(number(r.a), 1);
  4947. this.rgb(hslToRgb(hsl));
  4948. }
  4949. }
  4950. };
  4951. Color.prototype.rgb = function(rgb) {
  4952. if(rgb !== undefined) {
  4953. if(typeof(rgb) == 'object') {
  4954. if(rgb.hasOwnProperty('r')) this.r = parseInt(clamp(number(rgb.r), 255));
  4955. if(rgb.hasOwnProperty('g')) this.g = parseInt(clamp(number(rgb.g), 255));
  4956. if(rgb.hasOwnProperty('b')) this.b = parseInt(clamp(number(rgb.b), 255));
  4957. if(rgb.hasOwnProperty('a')) this.a = clamp(number(rgb.a), 1);
  4958. } else {
  4959. var v = parseInt(number(rgb));
  4960. this.r = v;
  4961. this.g = v;
  4962. this.b = v;
  4963. }
  4964. return this;
  4965. } else return {
  4966. r: this.r,
  4967. g: this.g,
  4968. b: this.b,
  4969. a: this.a
  4970. };
  4971. };
  4972. Color.prototype.hue = function(hue) {
  4973. var hsl = this.toHsl();
  4974. if(hue === undefined) return hsl.h;
  4975. else {
  4976. hsl.h = clamp(number(hue), 360);
  4977. this.rgb(hslToRgb(hsl));
  4978. return this;
  4979. }
  4980. };
  4981. Color.prototype.darken = function(amount) {
  4982. var hsl = this.toHsl();
  4983. hsl.l -= amount / 100;
  4984. hsl.l = clamp(hsl.l, 1);
  4985. this.rgb(hslToRgb(hsl));
  4986. return this;
  4987. };
  4988. Color.prototype.clone = function() {
  4989. return new Color(this.r, this.g, this.b, this.a);
  4990. };
  4991. Color.prototype.lighten = function(amount) {
  4992. return this.darken(-amount);
  4993. };
  4994. Color.prototype.fade = function(amount) {
  4995. this.a = clamp(amount / 100, 1);
  4996. return this;
  4997. };
  4998. Color.prototype.spin = function(amount) {
  4999. var hsl = this.toHsl();
  5000. var hue = (hsl.h + amount) % 360;
  5001. hsl.h = hue < 0 ? 360 + hue : hue;
  5002. this.rgb(hslToRgb(hsl));
  5003. return this;
  5004. };
  5005. Color.prototype.toHsl = function() {
  5006. var r = this.r / 255,
  5007. g = this.g / 255,
  5008. b = this.b / 255,
  5009. a = this.a;
  5010. var max = Math.max(r, g, b),
  5011. min = Math.min(r, g, b);
  5012. var h, s, l = (max + min) / 2,
  5013. d = max - min;
  5014. if(max === min) {
  5015. h = s = 0;
  5016. } else {
  5017. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  5018. switch(max) {
  5019. case r:
  5020. h = (g - b) / d + (g < b ? 6 : 0);
  5021. break;
  5022. case g:
  5023. h = (b - r) / d + 2;
  5024. break;
  5025. case b:
  5026. h = (r - g) / d + 4;
  5027. break;
  5028. }
  5029. h /= 6;
  5030. }
  5031. return {
  5032. h: h * 360,
  5033. s: s,
  5034. l: l,
  5035. a: a
  5036. };
  5037. };
  5038. Color.prototype.luma = function() {
  5039. var r = this.r / 255,
  5040. g = this.g / 255,
  5041. b = this.b / 255;
  5042. r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
  5043. g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
  5044. b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
  5045. return 0.2126 * r + 0.7152 * g + 0.0722 * b;
  5046. };
  5047. Color.prototype.saturate = function(amount) {
  5048. var hsl = this.toHsl();
  5049. hsl.s += amount / 100;
  5050. hsl.s = clamp(hsl.s);
  5051. this.rgb(hslToRgb(hsl));
  5052. return this;
  5053. };
  5054. Color.prototype.desaturate = function(amount) {
  5055. return this.saturate(-amount);
  5056. };
  5057. Color.prototype.contrast = function(dark, light, threshold) {
  5058. if(typeof light === 'undefined') light = new Color(255, 255, 255, 1);
  5059. else light = new Color(light);
  5060. if(typeof dark === 'undefined') dark = new Color(0, 0, 0, 1);
  5061. else dark = new Color(dark);
  5062. if(this.a < 0.5) return dark;
  5063. if(threshold === undefined) threshold = 0.43;
  5064. else threshold = number(threshold);
  5065. if(dark.luma() > light.luma()) {
  5066. var t = light;
  5067. light = dark;
  5068. dark = t;
  5069. }
  5070. if(this.luma() < threshold) {
  5071. return light;
  5072. } else {
  5073. return dark;
  5074. }
  5075. };
  5076. Color.prototype.hexStr = function() {
  5077. var r = this.r.toString(16),
  5078. g = this.g.toString(16),
  5079. b = this.b.toString(16);
  5080. if(r.length == 1) r = '0' + r;
  5081. if(g.length == 1) g = '0' + g;
  5082. if(b.length == 1) b = '0' + b;
  5083. return '#' + r + g + b;
  5084. };
  5085. Color.prototype.toCssStr = function() {
  5086. if(this.a > 0) {
  5087. if(this.a < 1) {
  5088. return 'rgba(' + this.r + ',' + this.g + ',' + this.b + ',' + this.a + ')';
  5089. } else {
  5090. return this.hexStr();
  5091. }
  5092. } else {
  5093. return 'transparent';
  5094. }
  5095. };
  5096. Color.prototype.isColor = isColor;
  5097. /* helpers */
  5098. function hexToRgb(hex) {
  5099. hex = hex.toLowerCase();
  5100. if(hex && hexReg.test(hex)) {
  5101. var i;
  5102. if(hex.length === 4) {
  5103. var hexNew = '#';
  5104. for(i = 1; i < 4; i += 1) {
  5105. hexNew += hex.slice(i, i + 1).concat(hex.slice(i, i + 1));
  5106. }
  5107. hex = hexNew;
  5108. }
  5109. var hexChange = [];
  5110. for(i = 1; i < 7; i += 2) {
  5111. hexChange.push(parseInt('0x' + hex.slice(i, i + 2)));
  5112. }
  5113. return {
  5114. r: hexChange[0],
  5115. g: hexChange[1],
  5116. b: hexChange[2],
  5117. a: 1
  5118. };
  5119. } else {
  5120. throw new Error('function hexToRgb: Wrong hex string! (hex: ' + hex + ')');
  5121. }
  5122. }
  5123. function isColor(hex) {
  5124. return typeof(hex) === 'string' && (hex.toLowerCase() === 'transparent' || namedColors[hex.toLowerCase()] || hexReg.test($.trim(hex.toLowerCase())));
  5125. }
  5126. function hslToRgb(hsl) {
  5127. var h = hsl.h,
  5128. s = hsl.s,
  5129. l = hsl.l,
  5130. a = hsl.a;
  5131. h = (number(h) % 360) / 360;
  5132. s = clamp(number(s));
  5133. l = clamp(number(l));
  5134. a = clamp(number(a));
  5135. var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
  5136. var m1 = l * 2 - m2;
  5137. var r = {
  5138. r: hue(h + 1 / 3) * 255,
  5139. g: hue(h) * 255,
  5140. b: hue(h - 1 / 3) * 255,
  5141. a: a
  5142. };
  5143. return r;
  5144. function hue(h) {
  5145. h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
  5146. if(h * 6 < 1) {
  5147. return m1 + (m2 - m1) * h * 6;
  5148. } else if(h * 2 < 1) {
  5149. return m2;
  5150. } else if(h * 3 < 2) {
  5151. return m1 + (m2 - m1) * (2 / 3 - h) * 6;
  5152. } else {
  5153. return m1;
  5154. }
  5155. }
  5156. }
  5157. function fit(n, end, start) {
  5158. if(start === undefined) start = 0;
  5159. if(end === undefined) end = 255;
  5160. return Math.min(Math.max(n, start), end);
  5161. }
  5162. function clamp(v, max) {
  5163. return fit(v, max);
  5164. }
  5165. function number(n) {
  5166. if(typeof(n) == 'number') return n;
  5167. return parseFloat(n);
  5168. }
  5169. $.zui({
  5170. Color: Color
  5171. });
  5172. }(jQuery, Math, window));
  5173. /* ========================================================================
  5174. * ZUI: tree.js
  5175. * http://zui.sexy
  5176. * ========================================================================
  5177. * Copyright (c) 2014 cnezsoft.com; Licensed MIT
  5178. * ======================================================================== */
  5179. (function($) {
  5180. 'use strict';
  5181. var name = 'zui.tree'; // modal name
  5182. // The tree modal class
  5183. var Tree = function(element, options) {
  5184. this.name = name;
  5185. this.$ = $(element);
  5186. this.getOptions(options);
  5187. this.init();
  5188. };
  5189. // default options
  5190. Tree.DEFAULTS = {
  5191. animate: null,
  5192. initialState: 'normal'
  5193. };
  5194. Tree.prototype.init = function() {
  5195. if(this.options.animate) this.$.addClass('tree-animate');
  5196. this.$lists = this.$.find('ul');
  5197. this.$lists.parent('li').addClass('has-list').prepend('<i class="list-toggle icon"></i>');
  5198. var that = this;
  5199. this.$.on('click', '.list-toggle, a[href=#]', function(e) {
  5200. that.toggle($(this).parent('li'));
  5201. e.preventDefault();
  5202. });
  5203. if(this.options.initialState === 'expand') {
  5204. this.expand();
  5205. } else if(this.options.initialState === 'collapse') {
  5206. this.collapse();
  5207. } else if(this.options.animate) {
  5208. this.$.find('li.has-list.open').addClass('in');
  5209. }
  5210. };
  5211. Tree.prototype.expand = function($li, disabledAnimate) {
  5212. if($li) {
  5213. $li.addClass('open');
  5214. if(!disabledAnimate && this.options.animate) {
  5215. setTimeout(function() {
  5216. $li.addClass('in');
  5217. }, 10);
  5218. } else {
  5219. $li.addClass('in');
  5220. }
  5221. } else {
  5222. this.$.find('li.has-list').addClass('open in');
  5223. }
  5224. this.callEvent('expand', $li, this);
  5225. };
  5226. Tree.prototype.collapse = function($li, disabledAnimate) {
  5227. if($li) {
  5228. if(!disabledAnimate && this.options.animate) {
  5229. $li.removeClass('in');
  5230. setTimeout(function() {
  5231. $li.removeClass('open');
  5232. }, 300);
  5233. } else {
  5234. $li.removeClass('open in');
  5235. }
  5236. } else {
  5237. this.$.find('li.has-list').removeClass('open in');
  5238. }
  5239. this.callEvent('collapse', $li, this);
  5240. };
  5241. Tree.prototype.toggle = function($li) {
  5242. var collapse = ($li && $li.hasClass('open')) || $li === false || ($li === undefined && this.$.find('li.has-list.open').length);
  5243. this[collapse ? 'collapse' : 'expand']($li);
  5244. };
  5245. // Get and init options
  5246. Tree.prototype.getOptions = function(options) {
  5247. this.options = $.extend({}, Tree.DEFAULTS, this.$.data(), options);
  5248. if(this.options.animate === null && this.$.hasClass('tree-animate')) {
  5249. this.options.animate = true;
  5250. }
  5251. };
  5252. // Call event helper
  5253. Tree.prototype.callEvent = function(name, params) {
  5254. var result = this.$.callEvent(name + '.' + this.name, params, this);
  5255. return !(result.result !== undefined && (!result.result));
  5256. };
  5257. // Extense jquery element
  5258. $.fn.tree = function(option, params) {
  5259. return this.each(function() {
  5260. var $this = $(this);
  5261. var data = $this.data(name);
  5262. var options = typeof option == 'object' && option;
  5263. if(!data) $this.data(name, (data = new Tree(this, options)));
  5264. if(typeof option == 'string') data[option](params);
  5265. });
  5266. };
  5267. $.fn.tree.Constructor = Tree;
  5268. // Auto call tree after document load complete
  5269. $(function() {
  5270. $('[data-ride="tree"]').tree();
  5271. });
  5272. }(jQuery));