12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883 |
- (function(window, document, undefined) {'use strict';
- function minErr(module) {
- return function () {
- var code = arguments[0],
- prefix = '[' + (module ? module + ':' : '') + code + '] ',
- template = arguments[1],
- templateArgs = arguments,
- stringify = function (obj) {
- if (typeof obj === 'function') {
- return obj.toString().replace(/ \{[\s\S]*$/, '');
- } else if (typeof obj === 'undefined') {
- return 'undefined';
- } else if (typeof obj !== 'string') {
- return JSON.stringify(obj);
- }
- return obj;
- },
- message, i;
- message = prefix + template.replace(/\{\d+\}/g, function (match) {
- var index = +match.slice(1, -1), arg;
- if (index + 2 < templateArgs.length) {
- arg = templateArgs[index + 2];
- if (typeof arg === 'function') {
- return arg.toString().replace(/ ?\{[\s\S]*$/, '');
- } else if (typeof arg === 'undefined') {
- return 'undefined';
- } else if (typeof arg !== 'string') {
- return toJson(arg);
- }
- return arg;
- }
- return match;
- });
- message = message + '\nhttp://errors.angularjs.org/1.2.21/' +
- (module ? module + '/' : '') + code;
- for (i = 2; i < arguments.length; i++) {
- message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
- encodeURIComponent(stringify(arguments[i]));
- }
- return new Error(message);
- };
- }
- var VALIDITY_STATE_PROPERTY = 'validity';
- var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
- var hasOwnProperty = Object.prototype.hasOwnProperty;
- var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
- var manualLowercase = function(s) {
-
- return isString(s)
- ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
- : s;
- };
- var manualUppercase = function(s) {
-
- return isString(s)
- ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
- : s;
- };
- if ('i' !== 'I'.toLowerCase()) {
- lowercase = manualLowercase;
- uppercase = manualUppercase;
- }
- var
- msie,
- jqLite,
- jQuery,
- slice = [].slice,
- push = [].push,
- toString = Object.prototype.toString,
- ngMinErr = minErr('ng'),
-
- angular = window.angular || (window.angular = {}),
- angularModule,
- nodeName_,
- uid = ['0', '0', '0'];
- msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
- if (isNaN(msie)) {
- msie = int((/trident\/.*; rv:(\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
- }
- function isArrayLike(obj) {
- if (obj == null || isWindow(obj)) {
- return false;
- }
- var length = obj.length;
- if (obj.nodeType === 1 && length) {
- return true;
- }
- return isString(obj) || isArray(obj) || length === 0 ||
- typeof length === 'number' && length > 0 && (length - 1) in obj;
- }
- function forEach(obj, iterator, context) {
- var key;
- if (obj) {
- if (isFunction(obj)) {
- for (key in obj) {
-
-
- if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
- iterator.call(context, obj[key], key);
- }
- }
- } else if (isArray(obj) || isArrayLike(obj)) {
- for (key = 0; key < obj.length; key++) {
- iterator.call(context, obj[key], key);
- }
- } else if (obj.forEach && obj.forEach !== forEach) {
- obj.forEach(iterator, context);
- } else {
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- iterator.call(context, obj[key], key);
- }
- }
- }
- }
- return obj;
- }
- function sortedKeys(obj) {
- var keys = [];
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- keys.push(key);
- }
- }
- return keys.sort();
- }
- function forEachSorted(obj, iterator, context) {
- var keys = sortedKeys(obj);
- for ( var i = 0; i < keys.length; i++) {
- iterator.call(context, obj[keys[i]], keys[i]);
- }
- return keys;
- }
- function reverseParams(iteratorFn) {
- return function(value, key) { iteratorFn(key, value); };
- }
- function nextUid() {
- var index = uid.length;
- var digit;
- while(index) {
- index--;
- digit = uid[index].charCodeAt(0);
- if (digit == 57 ) {
- uid[index] = 'A';
- return uid.join('');
- }
- if (digit == 90 ) {
- uid[index] = '0';
- } else {
- uid[index] = String.fromCharCode(digit + 1);
- return uid.join('');
- }
- }
- uid.unshift('0');
- return uid.join('');
- }
- function setHashKey(obj, h) {
- if (h) {
- obj.$$hashKey = h;
- }
- else {
- delete obj.$$hashKey;
- }
- }
- function extend(dst) {
- var h = dst.$$hashKey;
- forEach(arguments, function(obj) {
- if (obj !== dst) {
- forEach(obj, function(value, key) {
- dst[key] = value;
- });
- }
- });
- setHashKey(dst,h);
- return dst;
- }
- function int(str) {
- return parseInt(str, 10);
- }
- function inherit(parent, extra) {
- return extend(new (extend(function() {}, {prototype:parent}))(), extra);
- }
- function noop() {}
- noop.$inject = [];
- function identity($) {return $;}
- identity.$inject = [];
- function valueFn(value) {return function() {return value;};}
- function isUndefined(value){return typeof value === 'undefined';}
- function isDefined(value){return typeof value !== 'undefined';}
- function isObject(value){return value != null && typeof value === 'object';}
- function isString(value){return typeof value === 'string';}
- function isNumber(value){return typeof value === 'number';}
- function isDate(value) {
- return toString.call(value) === '[object Date]';
- }
- var isArray = (function() {
- if (!isFunction(Array.isArray)) {
- return function(value) {
- return toString.call(value) === '[object Array]';
- };
- }
- return Array.isArray;
- })();
- function isFunction(value){return typeof value === 'function';}
- function isRegExp(value) {
- return toString.call(value) === '[object RegExp]';
- }
- function isWindow(obj) {
- return obj && obj.document && obj.location && obj.alert && obj.setInterval;
- }
- function isScope(obj) {
- return obj && obj.$evalAsync && obj.$watch;
- }
- function isFile(obj) {
- return toString.call(obj) === '[object File]';
- }
- function isBlob(obj) {
- return toString.call(obj) === '[object Blob]';
- }
- function isBoolean(value) {
- return typeof value === 'boolean';
- }
- function isPromiseLike(obj) {
- return obj && isFunction(obj.then);
- }
- var trim = (function() {
-
-
-
- if (!String.prototype.trim) {
- return function(value) {
- return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
- };
- }
- return function(value) {
- return isString(value) ? value.trim() : value;
- };
- })();
- function isElement(node) {
- return !!(node &&
- (node.nodeName
- || (node.prop && node.attr && node.find)));
- }
- function makeMap(str) {
- var obj = {}, items = str.split(","), i;
- for ( i = 0; i < items.length; i++ )
- obj[ items[i] ] = true;
- return obj;
- }
- if (msie < 9) {
- nodeName_ = function(element) {
- element = element.nodeName ? element : element[0];
- return (element.scopeName && element.scopeName != 'HTML')
- ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
- };
- } else {
- nodeName_ = function(element) {
- return element.nodeName ? element.nodeName : element[0].nodeName;
- };
- }
- function map(obj, iterator, context) {
- var results = [];
- forEach(obj, function(value, index, list) {
- results.push(iterator.call(context, value, index, list));
- });
- return results;
- }
- function size(obj, ownPropsOnly) {
- var count = 0, key;
- if (isArray(obj) || isString(obj)) {
- return obj.length;
- } else if (isObject(obj)) {
- for (key in obj)
- if (!ownPropsOnly || obj.hasOwnProperty(key))
- count++;
- }
- return count;
- }
- function includes(array, obj) {
- return indexOf(array, obj) != -1;
- }
- function indexOf(array, obj) {
- if (array.indexOf) return array.indexOf(obj);
- for (var i = 0; i < array.length; i++) {
- if (obj === array[i]) return i;
- }
- return -1;
- }
- function arrayRemove(array, value) {
- var index = indexOf(array, value);
- if (index >=0)
- array.splice(index, 1);
- return value;
- }
- function isLeafNode (node) {
- if (node) {
- switch (node.nodeName) {
- case "OPTION":
- case "PRE":
- case "TITLE":
- return true;
- }
- }
- return false;
- }
- function copy(source, destination, stackSource, stackDest) {
- if (isWindow(source) || isScope(source)) {
- throw ngMinErr('cpws',
- "Can't copy! Making copies of Window or Scope instances is not supported.");
- }
- if (!destination) {
- destination = source;
- if (source) {
- if (isArray(source)) {
- destination = copy(source, [], stackSource, stackDest);
- } else if (isDate(source)) {
- destination = new Date(source.getTime());
- } else if (isRegExp(source)) {
- destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
- destination.lastIndex = source.lastIndex;
- } else if (isObject(source)) {
- destination = copy(source, {}, stackSource, stackDest);
- }
- }
- } else {
- if (source === destination) throw ngMinErr('cpi',
- "Can't copy! Source and destination are identical.");
- stackSource = stackSource || [];
- stackDest = stackDest || [];
- if (isObject(source)) {
- var index = indexOf(stackSource, source);
- if (index !== -1) return stackDest[index];
- stackSource.push(source);
- stackDest.push(destination);
- }
- var result;
- if (isArray(source)) {
- destination.length = 0;
- for ( var i = 0; i < source.length; i++) {
- result = copy(source[i], null, stackSource, stackDest);
- if (isObject(source[i])) {
- stackSource.push(source[i]);
- stackDest.push(result);
- }
- destination.push(result);
- }
- } else {
- var h = destination.$$hashKey;
- forEach(destination, function(value, key) {
- delete destination[key];
- });
- for ( var key in source) {
- result = copy(source[key], null, stackSource, stackDest);
- if (isObject(source[key])) {
- stackSource.push(source[key]);
- stackDest.push(result);
- }
- destination[key] = result;
- }
- setHashKey(destination,h);
- }
- }
- return destination;
- }
- function shallowCopy(src, dst) {
- if (isArray(src)) {
- dst = dst || [];
- for ( var i = 0; i < src.length; i++) {
- dst[i] = src[i];
- }
- } else if (isObject(src)) {
- dst = dst || {};
- for (var key in src) {
- if (hasOwnProperty.call(src, key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
- dst[key] = src[key];
- }
- }
- }
- return dst || src;
- }
- function equals(o1, o2) {
- if (o1 === o2) return true;
- if (o1 === null || o2 === null) return false;
- if (o1 !== o1 && o2 !== o2) return true;
- var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
- if (t1 == t2) {
- if (t1 == 'object') {
- if (isArray(o1)) {
- if (!isArray(o2)) return false;
- if ((length = o1.length) == o2.length) {
- for(key=0; key<length; key++) {
- if (!equals(o1[key], o2[key])) return false;
- }
- return true;
- }
- } else if (isDate(o1)) {
- return isDate(o2) && o1.getTime() == o2.getTime();
- } else if (isRegExp(o1) && isRegExp(o2)) {
- return o1.toString() == o2.toString();
- } else {
- if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
- keySet = {};
- for(key in o1) {
- if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
- if (!equals(o1[key], o2[key])) return false;
- keySet[key] = true;
- }
- for(key in o2) {
- if (!keySet.hasOwnProperty(key) &&
- key.charAt(0) !== '$' &&
- o2[key] !== undefined &&
- !isFunction(o2[key])) return false;
- }
- return true;
- }
- }
- }
- return false;
- }
- var csp = function() {
- if (isDefined(csp.isActive_)) return csp.isActive_;
- var active = !!(document.querySelector('[ng-csp]') ||
- document.querySelector('[data-ng-csp]'));
- if (!active) {
- try {
-
- new Function('');
-
- } catch (e) {
- active = true;
- }
- }
- return (csp.isActive_ = active);
- };
- function concat(array1, array2, index) {
- return array1.concat(slice.call(array2, index));
- }
- function sliceArgs(args, startIndex) {
- return slice.call(args, startIndex || 0);
- }
- function bind(self, fn) {
- var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
- if (isFunction(fn) && !(fn instanceof RegExp)) {
- return curryArgs.length
- ? function() {
- return arguments.length
- ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
- : fn.apply(self, curryArgs);
- }
- : function() {
- return arguments.length
- ? fn.apply(self, arguments)
- : fn.call(self);
- };
- } else {
-
- return fn;
- }
- }
- function toJsonReplacer(key, value) {
- var val = value;
- if (typeof key === 'string' && key.charAt(0) === '$') {
- val = undefined;
- } else if (isWindow(value)) {
- val = '$WINDOW';
- } else if (value && document === value) {
- val = '$DOCUMENT';
- } else if (isScope(value)) {
- val = '$SCOPE';
- }
- return val;
- }
- function toJson(obj, pretty) {
- if (typeof obj === 'undefined') return undefined;
- return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null);
- }
- function fromJson(json) {
- return isString(json)
- ? JSON.parse(json)
- : json;
- }
- function toBoolean(value) {
- if (typeof value === 'function') {
- value = true;
- } else if (value && value.length !== 0) {
- var v = lowercase("" + value);
- value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
- } else {
- value = false;
- }
- return value;
- }
- function startingTag(element) {
- element = jqLite(element).clone();
- try {
-
-
- element.empty();
- } catch(e) {}
-
- var TEXT_NODE = 3;
- var elemHtml = jqLite('<div>').append(element).html();
- try {
- return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
- elemHtml.
- match(/^(<[^>]+>)/)[1].
- replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
- } catch(e) {
- return lowercase(elemHtml);
- }
- }
- function tryDecodeURIComponent(value) {
- try {
- return decodeURIComponent(value);
- } catch(e) {
-
- }
- }
- function parseKeyValue(/**string*/keyValue) {
- var obj = {}, key_value, key;
- forEach((keyValue || "").split('&'), function(keyValue) {
- if ( keyValue ) {
- key_value = keyValue.replace(/\+/g,'%20').split('=');
- key = tryDecodeURIComponent(key_value[0]);
- if ( isDefined(key) ) {
- var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
- if (!hasOwnProperty.call(obj, key)) {
- obj[key] = val;
- } else if(isArray(obj[key])) {
- obj[key].push(val);
- } else {
- obj[key] = [obj[key],val];
- }
- }
- }
- });
- return obj;
- }
- function toKeyValue(obj) {
- var parts = [];
- forEach(obj, function(value, key) {
- if (isArray(value)) {
- forEach(value, function(arrayValue) {
- parts.push(encodeUriQuery(key, true) +
- (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
- });
- } else {
- parts.push(encodeUriQuery(key, true) +
- (value === true ? '' : '=' + encodeUriQuery(value, true)));
- }
- });
- return parts.length ? parts.join('&') : '';
- }
- function encodeUriSegment(val) {
- return encodeUriQuery(val, true).
- replace(/%26/gi, '&').
- replace(/%3D/gi, '=').
- replace(/%2B/gi, '+');
- }
- function encodeUriQuery(val, pctEncodeSpaces) {
- return encodeURIComponent(val).
- replace(/%40/gi, '@').
- replace(/%3A/gi, ':').
- replace(/%24/g, '$').
- replace(/%2C/gi, ',').
- replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
- }
- function angularInit(element, bootstrap) {
- var elements = [element],
- appElement,
- module,
- names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
- NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
- function append(element) {
- element && elements.push(element);
- }
- forEach(names, function(name) {
- names[name] = true;
- append(document.getElementById(name));
- name = name.replace(':', '\\:');
- if (element.querySelectorAll) {
- forEach(element.querySelectorAll('.' + name), append);
- forEach(element.querySelectorAll('.' + name + '\\:'), append);
- forEach(element.querySelectorAll('[' + name + ']'), append);
- }
- });
- forEach(elements, function(element) {
- if (!appElement) {
- var className = ' ' + element.className + ' ';
- var match = NG_APP_CLASS_REGEXP.exec(className);
- if (match) {
- appElement = element;
- module = (match[2] || '').replace(/\s+/g, ',');
- } else {
- forEach(element.attributes, function(attr) {
- if (!appElement && names[attr.name]) {
- appElement = element;
- module = attr.value;
- }
- });
- }
- }
- });
- if (appElement) {
- bootstrap(appElement, module ? [module] : []);
- }
- }
- function bootstrap(element, modules) {
- var doBootstrap = function() {
- element = jqLite(element);
- if (element.injector()) {
- var tag = (element[0] === document) ? 'document' : startingTag(element);
- throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
- }
- modules = modules || [];
- modules.unshift(['$provide', function($provide) {
- $provide.value('$rootElement', element);
- }]);
- modules.unshift('ng');
- var injector = createInjector(modules);
- injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
- function(scope, element, compile, injector, animate) {
- scope.$apply(function() {
- element.data('$injector', injector);
- compile(element)(scope);
- });
- }]
- );
- return injector;
- };
- var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
- if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
- return doBootstrap();
- }
- window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
- angular.resumeBootstrap = function(extraModules) {
- forEach(extraModules, function(module) {
- modules.push(module);
- });
- doBootstrap();
- };
- }
- var SNAKE_CASE_REGEXP = /[A-Z]/g;
- function snake_case(name, separator) {
- separator = separator || '_';
- return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
- return (pos ? separator : '') + letter.toLowerCase();
- });
- }
- function bindJQuery() {
-
- jQuery = window.jQuery;
-
-
- if (jQuery && jQuery.fn.on) {
- jqLite = jQuery;
- extend(jQuery.fn, {
- scope: JQLitePrototype.scope,
- isolateScope: JQLitePrototype.isolateScope,
- controller: JQLitePrototype.controller,
- injector: JQLitePrototype.injector,
- inheritedData: JQLitePrototype.inheritedData
- });
-
-
- jqLitePatchJQueryRemove('remove', true, true, false);
- jqLitePatchJQueryRemove('empty', false, false, false);
- jqLitePatchJQueryRemove('html', false, false, true);
- } else {
- jqLite = JQLite;
- }
- angular.element = jqLite;
- }
- function assertArg(arg, name, reason) {
- if (!arg) {
- throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
- }
- return arg;
- }
- function assertArgFn(arg, name, acceptArrayAnnotation) {
- if (acceptArrayAnnotation && isArray(arg)) {
- arg = arg[arg.length - 1];
- }
- assertArg(isFunction(arg), name, 'not a function, got ' +
- (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
- return arg;
- }
- function assertNotHasOwnProperty(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
- }
- }
- function getter(obj, path, bindFnToScope) {
- if (!path) return obj;
- var keys = path.split('.');
- var key;
- var lastInstance = obj;
- var len = keys.length;
- for (var i = 0; i < len; i++) {
- key = keys[i];
- if (obj) {
- obj = (lastInstance = obj)[key];
- }
- }
- if (!bindFnToScope && isFunction(obj)) {
- return bind(lastInstance, obj);
- }
- return obj;
- }
- function getBlockElements(nodes) {
- var startNode = nodes[0],
- endNode = nodes[nodes.length - 1];
- if (startNode === endNode) {
- return jqLite(startNode);
- }
- var element = startNode;
- var elements = [element];
- do {
- element = element.nextSibling;
- if (!element) break;
- elements.push(element);
- } while (element !== endNode);
- return jqLite(elements);
- }
- function setupModuleLoader(window) {
- var $injectorMinErr = minErr('$injector');
- var ngMinErr = minErr('ng');
- function ensure(obj, name, factory) {
- return obj[name] || (obj[name] = factory());
- }
- var angular = ensure(window, 'angular', Object);
-
- angular.$$minErr = angular.$$minErr || minErr;
- return ensure(angular, 'module', function() {
-
- var modules = {};
-
- return function module(name, requires, configFn) {
- var assertNotHasOwnProperty = function(name, context) {
- if (name === 'hasOwnProperty') {
- throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
- }
- };
- assertNotHasOwnProperty(name, 'module');
- if (requires && modules.hasOwnProperty(name)) {
- modules[name] = null;
- }
- return ensure(modules, name, function() {
- if (!requires) {
- throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
- "the module name or forgot to load it. If registering a module ensure that you " +
- "specify the dependencies as the second argument.", name);
- }
-
- var invokeQueue = [];
-
- var runBlocks = [];
- var config = invokeLater('$injector', 'invoke');
-
- var moduleInstance = {
-
- _invokeQueue: invokeQueue,
- _runBlocks: runBlocks,
-
- requires: requires,
-
- name: name,
-
- provider: invokeLater('$provide', 'provider'),
-
- factory: invokeLater('$provide', 'factory'),
-
- service: invokeLater('$provide', 'service'),
-
- value: invokeLater('$provide', 'value'),
-
- constant: invokeLater('$provide', 'constant', 'unshift'),
-
- animation: invokeLater('$animateProvider', 'register'),
-
- filter: invokeLater('$filterProvider', 'register'),
-
- controller: invokeLater('$controllerProvider', 'register'),
-
- directive: invokeLater('$compileProvider', 'directive'),
-
- config: config,
-
- run: function(block) {
- runBlocks.push(block);
- return this;
- }
- };
- if (configFn) {
- config(configFn);
- }
- return moduleInstance;
-
- function invokeLater(provider, method, insertMethod) {
- return function() {
- invokeQueue[insertMethod || 'push']([provider, method, arguments]);
- return moduleInstance;
- };
- }
- });
- };
- });
- }
- var version = {
- full: '1.2.21',
- major: 1,
- minor: 2,
- dot: 21,
- codeName: 'wizard-props'
- };
- function publishExternalAPI(angular){
- extend(angular, {
- 'bootstrap': bootstrap,
- 'copy': copy,
- 'extend': extend,
- 'equals': equals,
- 'element': jqLite,
- 'forEach': forEach,
- 'injector': createInjector,
- 'noop':noop,
- 'bind':bind,
- 'toJson': toJson,
- 'fromJson': fromJson,
- 'identity':identity,
- 'isUndefined': isUndefined,
- 'isDefined': isDefined,
- 'isString': isString,
- 'isFunction': isFunction,
- 'isObject': isObject,
- 'isNumber': isNumber,
- 'isElement': isElement,
- 'isArray': isArray,
- 'version': version,
- 'isDate': isDate,
- 'lowercase': lowercase,
- 'uppercase': uppercase,
- 'callbacks': {counter: 0},
- '$$minErr': minErr,
- '$$csp': csp
- });
- angularModule = setupModuleLoader(window);
- try {
- angularModule('ngLocale');
- } catch (e) {
- angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
- }
- angularModule('ng', ['ngLocale'], ['$provide',
- function ngModule($provide) {
-
- $provide.provider({
- $$sanitizeUri: $$SanitizeUriProvider
- });
- $provide.provider('$compile', $CompileProvider).
- directive({
- a: htmlAnchorDirective,
- input: inputDirective,
- textarea: inputDirective,
- form: formDirective,
- script: scriptDirective,
- select: selectDirective,
- style: styleDirective,
- option: optionDirective,
- ngBind: ngBindDirective,
- ngBindHtml: ngBindHtmlDirective,
- ngBindTemplate: ngBindTemplateDirective,
- ngClass: ngClassDirective,
- ngClassEven: ngClassEvenDirective,
- ngClassOdd: ngClassOddDirective,
- ngCloak: ngCloakDirective,
- ngController: ngControllerDirective,
- ngForm: ngFormDirective,
- ngHide: ngHideDirective,
- ngIf: ngIfDirective,
- ngInclude: ngIncludeDirective,
- ngInit: ngInitDirective,
- ngNonBindable: ngNonBindableDirective,
- ngPluralize: ngPluralizeDirective,
- ngRepeat: ngRepeatDirective,
- ngShow: ngShowDirective,
- ngStyle: ngStyleDirective,
- ngSwitch: ngSwitchDirective,
- ngSwitchWhen: ngSwitchWhenDirective,
- ngSwitchDefault: ngSwitchDefaultDirective,
- ngOptions: ngOptionsDirective,
- ngTransclude: ngTranscludeDirective,
- ngModel: ngModelDirective,
- ngList: ngListDirective,
- ngChange: ngChangeDirective,
- required: requiredDirective,
- ngRequired: requiredDirective,
- ngValue: ngValueDirective
- }).
- directive({
- ngInclude: ngIncludeFillContentDirective
- }).
- directive(ngAttributeAliasDirectives).
- directive(ngEventDirectives);
- $provide.provider({
- $anchorScroll: $AnchorScrollProvider,
- $animate: $AnimateProvider,
- $browser: $BrowserProvider,
- $cacheFactory: $CacheFactoryProvider,
- $controller: $ControllerProvider,
- $document: $DocumentProvider,
- $exceptionHandler: $ExceptionHandlerProvider,
- $filter: $FilterProvider,
- $interpolate: $InterpolateProvider,
- $interval: $IntervalProvider,
- $http: $HttpProvider,
- $httpBackend: $HttpBackendProvider,
- $location: $LocationProvider,
- $log: $LogProvider,
- $parse: $ParseProvider,
- $rootScope: $RootScopeProvider,
- $q: $QProvider,
- $sce: $SceProvider,
- $sceDelegate: $SceDelegateProvider,
- $sniffer: $SnifferProvider,
- $templateCache: $TemplateCacheProvider,
- $timeout: $TimeoutProvider,
- $window: $WindowProvider,
- $$rAF: $$RAFProvider,
- $$asyncCallback : $$AsyncCallbackProvider
- });
- }
- ]);
- }
- JQLite.expando = 'ng339';
- var jqCache = JQLite.cache = {},
- jqId = 1,
- addEventListenerFn = (window.document.addEventListener
- ? function(element, type, fn) {element.addEventListener(type, fn, false);}
- : function(element, type, fn) {element.attachEvent('on' + type, fn);}),
- removeEventListenerFn = (window.document.removeEventListener
- ? function(element, type, fn) {element.removeEventListener(type, fn, false); }
- : function(element, type, fn) {element.detachEvent('on' + type, fn); });
- var jqData = JQLite._data = function(node) {
-
- return this.cache[node[this.expando]] || {};
- };
- function jqNextId() { return ++jqId; }
- var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
- var MOZ_HACK_REGEXP = /^moz([A-Z])/;
- var jqLiteMinErr = minErr('jqLite');
- function camelCase(name) {
- return name.
- replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
- return offset ? letter.toUpperCase() : letter;
- }).
- replace(MOZ_HACK_REGEXP, 'Moz$1');
- }
- function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) {
- var originalJqFn = jQuery.fn[name];
- originalJqFn = originalJqFn.$original || originalJqFn;
- removePatch.$original = originalJqFn;
- jQuery.fn[name] = removePatch;
- function removePatch(param) {
-
- var list = filterElems && param ? [this.filter(param)] : [this],
- fireEvent = dispatchThis,
- set, setIndex, setLength,
- element, childIndex, childLength, children;
- if (!getterIfNoArguments || param != null) {
- while(list.length) {
- set = list.shift();
- for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
- element = jqLite(set[setIndex]);
- if (fireEvent) {
- element.triggerHandler('$destroy');
- } else {
- fireEvent = !fireEvent;
- }
- for(childIndex = 0, childLength = (children = element.children()).length;
- childIndex < childLength;
- childIndex++) {
- list.push(jQuery(children[childIndex]));
- }
- }
- }
- }
- return originalJqFn.apply(this, arguments);
- }
- }
- var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
- var HTML_REGEXP = /<|&#?\w+;/;
- var TAG_NAME_REGEXP = /<([\w:]+)/;
- var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
- var wrapMap = {
- 'option': [1, '<select multiple="multiple">', '</select>'],
- 'thead': [1, '<table>', '</table>'],
- 'col': [2, '<table><colgroup>', '</colgroup></table>'],
- 'tr': [2, '<table><tbody>', '</tbody></table>'],
- 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
- '_default': [0, "", ""]
- };
- wrapMap.optgroup = wrapMap.option;
- wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
- wrapMap.th = wrapMap.td;
- function jqLiteIsTextNode(html) {
- return !HTML_REGEXP.test(html);
- }
- function jqLiteBuildFragment(html, context) {
- var elem, tmp, tag, wrap,
- fragment = context.createDocumentFragment(),
- nodes = [], i, j, jj;
- if (jqLiteIsTextNode(html)) {
-
- nodes.push(context.createTextNode(html));
- } else {
- tmp = fragment.appendChild(context.createElement('div'));
-
- tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
- wrap = wrapMap[tag] || wrapMap._default;
- tmp.innerHTML = '<div> </div>' +
- wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
- tmp.removeChild(tmp.firstChild);
-
- i = wrap[0];
- while (i--) {
- tmp = tmp.lastChild;
- }
- for (j=0, jj=tmp.childNodes.length; j<jj; ++j) nodes.push(tmp.childNodes[j]);
- tmp = fragment.firstChild;
- tmp.textContent = "";
- }
-
- fragment.textContent = "";
- fragment.innerHTML = "";
- return nodes;
- }
- function jqLiteParseHTML(html, context) {
- context = context || document;
- var parsed;
- if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
- return [context.createElement(parsed[1])];
- }
- return jqLiteBuildFragment(html, context);
- }
- function JQLite(element) {
- if (element instanceof JQLite) {
- return element;
- }
- if (isString(element)) {
- element = trim(element);
- }
- if (!(this instanceof JQLite)) {
- if (isString(element) && element.charAt(0) != '<') {
- throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
- }
- return new JQLite(element);
- }
- if (isString(element)) {
- jqLiteAddNodes(this, jqLiteParseHTML(element));
- var fragment = jqLite(document.createDocumentFragment());
- fragment.append(this);
- } else {
- jqLiteAddNodes(this, element);
- }
- }
- function jqLiteClone(element) {
- return element.cloneNode(true);
- }
- function jqLiteDealoc(element){
- jqLiteRemoveData(element);
- for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
- jqLiteDealoc(children[i]);
- }
- }
- function jqLiteOff(element, type, fn, unsupported) {
- if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
- var events = jqLiteExpandoStore(element, 'events'),
- handle = jqLiteExpandoStore(element, 'handle');
- if (!handle) return;
- if (isUndefined(type)) {
- forEach(events, function(eventHandler, type) {
- removeEventListenerFn(element, type, eventHandler);
- delete events[type];
- });
- } else {
- forEach(type.split(' '), function(type) {
- if (isUndefined(fn)) {
- removeEventListenerFn(element, type, events[type]);
- delete events[type];
- } else {
- arrayRemove(events[type] || [], fn);
- }
- });
- }
- }
- function jqLiteRemoveData(element, name) {
- var expandoId = element.ng339,
- expandoStore = jqCache[expandoId];
- if (expandoStore) {
- if (name) {
- delete jqCache[expandoId].data[name];
- return;
- }
- if (expandoStore.handle) {
- expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
- jqLiteOff(element);
- }
- delete jqCache[expandoId];
- element.ng339 = undefined;
- }
- }
- function jqLiteExpandoStore(element, key, value) {
- var expandoId = element.ng339,
- expandoStore = jqCache[expandoId || -1];
- if (isDefined(value)) {
- if (!expandoStore) {
- element.ng339 = expandoId = jqNextId();
- expandoStore = jqCache[expandoId] = {};
- }
- expandoStore[key] = value;
- } else {
- return expandoStore && expandoStore[key];
- }
- }
- function jqLiteData(element, key, value) {
- var data = jqLiteExpandoStore(element, 'data'),
- isSetter = isDefined(value),
- keyDefined = !isSetter && isDefined(key),
- isSimpleGetter = keyDefined && !isObject(key);
- if (!data && !isSimpleGetter) {
- jqLiteExpandoStore(element, 'data', data = {});
- }
- if (isSetter) {
- data[key] = value;
- } else {
- if (keyDefined) {
- if (isSimpleGetter) {
-
- return data && data[key];
- } else {
- extend(data, key);
- }
- } else {
- return data;
- }
- }
- }
- function jqLiteHasClass(element, selector) {
- if (!element.getAttribute) return false;
- return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
- indexOf( " " + selector + " " ) > -1);
- }
- function jqLiteRemoveClass(element, cssClasses) {
- if (cssClasses && element.setAttribute) {
- forEach(cssClasses.split(' '), function(cssClass) {
- element.setAttribute('class', trim(
- (" " + (element.getAttribute('class') || '') + " ")
- .replace(/[\n\t]/g, " ")
- .replace(" " + trim(cssClass) + " ", " "))
- );
- });
- }
- }
- function jqLiteAddClass(element, cssClasses) {
- if (cssClasses && element.setAttribute) {
- var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
- .replace(/[\n\t]/g, " ");
- forEach(cssClasses.split(' '), function(cssClass) {
- cssClass = trim(cssClass);
- if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
- existingClasses += cssClass + ' ';
- }
- });
- element.setAttribute('class', trim(existingClasses));
- }
- }
- function jqLiteAddNodes(root, elements) {
- if (elements) {
- elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
- ? elements
- : [ elements ];
- for(var i=0; i < elements.length; i++) {
- root.push(elements[i]);
- }
- }
- }
- function jqLiteController(element, name) {
- return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
- }
- function jqLiteInheritedData(element, name, value) {
-
-
- if(element.nodeType == 9) {
- element = element.documentElement;
- }
- var names = isArray(name) ? name : [name];
- while (element) {
- for (var i = 0, ii = names.length; i < ii; i++) {
- if ((value = jqLite.data(element, names[i])) !== undefined) return value;
- }
-
-
-
- element = element.parentNode || (element.nodeType === 11 && element.host);
- }
- }
- function jqLiteEmpty(element) {
- for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
- jqLiteDealoc(childNodes[i]);
- }
- while (element.firstChild) {
- element.removeChild(element.firstChild);
- }
- }
- var JQLitePrototype = JQLite.prototype = {
- ready: function(fn) {
- var fired = false;
- function trigger() {
- if (fired) return;
- fired = true;
- fn();
- }
-
- if (document.readyState === 'complete'){
- setTimeout(trigger);
- } else {
- this.on('DOMContentLoaded', trigger);
-
-
- JQLite(window).on('load', trigger);
-
- }
- },
- toString: function() {
- var value = [];
- forEach(this, function(e){ value.push('' + e);});
- return '[' + value.join(', ') + ']';
- },
- eq: function(index) {
- return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
- },
- length: 0,
- push: push,
- sort: [].sort,
- splice: [].splice
- };
- var BOOLEAN_ATTR = {};
- forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
- BOOLEAN_ATTR[lowercase(value)] = value;
- });
- var BOOLEAN_ELEMENTS = {};
- forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
- BOOLEAN_ELEMENTS[uppercase(value)] = true;
- });
- function getBooleanAttrName(element, name) {
-
- var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
-
- return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
- }
- forEach({
- data: jqLiteData,
- removeData: jqLiteRemoveData
- }, function(fn, name) {
- JQLite[name] = fn;
- });
- forEach({
- data: jqLiteData,
- inheritedData: jqLiteInheritedData,
- scope: function(element) {
-
- return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
- },
- isolateScope: function(element) {
-
- return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
- },
- controller: jqLiteController,
- injector: function(element) {
- return jqLiteInheritedData(element, '$injector');
- },
- removeAttr: function(element,name) {
- element.removeAttribute(name);
- },
- hasClass: jqLiteHasClass,
- css: function(element, name, value) {
- name = camelCase(name);
- if (isDefined(value)) {
- element.style[name] = value;
- } else {
- var val;
- if (msie <= 8) {
-
- val = element.currentStyle && element.currentStyle[name];
- if (val === '') val = 'auto';
- }
- val = val || element.style[name];
- if (msie <= 8) {
-
- val = (val === '') ? undefined : val;
- }
- return val;
- }
- },
- attr: function(element, name, value){
- var lowercasedName = lowercase(name);
- if (BOOLEAN_ATTR[lowercasedName]) {
- if (isDefined(value)) {
- if (!!value) {
- element[name] = true;
- element.setAttribute(name, lowercasedName);
- } else {
- element[name] = false;
- element.removeAttribute(lowercasedName);
- }
- } else {
- return (element[name] ||
- (element.attributes.getNamedItem(name)|| noop).specified)
- ? lowercasedName
- : undefined;
- }
- } else if (isDefined(value)) {
- element.setAttribute(name, value);
- } else if (element.getAttribute) {
-
-
- var ret = element.getAttribute(name, 2);
-
- return ret === null ? undefined : ret;
- }
- },
- prop: function(element, name, value) {
- if (isDefined(value)) {
- element[name] = value;
- } else {
- return element[name];
- }
- },
- text: (function() {
- var NODE_TYPE_TEXT_PROPERTY = [];
- if (msie < 9) {
- NODE_TYPE_TEXT_PROPERTY[1] = 'innerText';
- NODE_TYPE_TEXT_PROPERTY[3] = 'nodeValue';
- } else {
- NODE_TYPE_TEXT_PROPERTY[1] =
- NODE_TYPE_TEXT_PROPERTY[3] = 'textContent';
- }
- getText.$dv = '';
- return getText;
- function getText(element, value) {
- var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType];
- if (isUndefined(value)) {
- return textProp ? element[textProp] : '';
- }
- element[textProp] = value;
- }
- })(),
- val: function(element, value) {
- if (isUndefined(value)) {
- if (nodeName_(element) === 'SELECT' && element.multiple) {
- var result = [];
- forEach(element.options, function (option) {
- if (option.selected) {
- result.push(option.value || option.text);
- }
- });
- return result.length === 0 ? null : result;
- }
- return element.value;
- }
- element.value = value;
- },
- html: function(element, value) {
- if (isUndefined(value)) {
- return element.innerHTML;
- }
- for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
- jqLiteDealoc(childNodes[i]);
- }
- element.innerHTML = value;
- },
- empty: jqLiteEmpty
- }, function(fn, name){
-
- JQLite.prototype[name] = function(arg1, arg2) {
- var i, key;
- var nodeCount = this.length;
-
-
-
- if (fn !== jqLiteEmpty &&
- (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
- if (isObject(arg1)) {
-
- for (i = 0; i < nodeCount; i++) {
- if (fn === jqLiteData) {
-
- fn(this[i], arg1);
- } else {
- for (key in arg1) {
- fn(this[i], key, arg1[key]);
- }
- }
- }
-
- return this;
- } else {
-
-
- var value = fn.$dv;
-
- var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
- for (var j = 0; j < jj; j++) {
- var nodeValue = fn(this[j], arg1, arg2);
- value = value ? value + nodeValue : nodeValue;
- }
- return value;
- }
- } else {
-
- for (i = 0; i < nodeCount; i++) {
- fn(this[i], arg1, arg2);
- }
-
- return this;
- }
- };
- });
- function createEventHandler(element, events) {
- var eventHandler = function (event, type) {
- if (!event.preventDefault) {
- event.preventDefault = function() {
- event.returnValue = false;
- };
- }
- if (!event.stopPropagation) {
- event.stopPropagation = function() {
- event.cancelBubble = true;
- };
- }
- if (!event.target) {
- event.target = event.srcElement || document;
- }
- if (isUndefined(event.defaultPrevented)) {
- var prevent = event.preventDefault;
- event.preventDefault = function() {
- event.defaultPrevented = true;
- prevent.call(event);
- };
- event.defaultPrevented = false;
- }
- event.isDefaultPrevented = function() {
- return event.defaultPrevented || event.returnValue === false;
- };
-
- var eventHandlersCopy = shallowCopy(events[type || event.type] || []);
- forEach(eventHandlersCopy, function(fn) {
- fn.call(element, event);
- });
-
-
- if (msie <= 8) {
-
- event.preventDefault = null;
- event.stopPropagation = null;
- event.isDefaultPrevented = null;
- } else {
-
- delete event.preventDefault;
- delete event.stopPropagation;
- delete event.isDefaultPrevented;
- }
- };
- eventHandler.elem = element;
- return eventHandler;
- }
- forEach({
- removeData: jqLiteRemoveData,
- dealoc: jqLiteDealoc,
- on: function onFn(element, type, fn, unsupported){
- if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
- var events = jqLiteExpandoStore(element, 'events'),
- handle = jqLiteExpandoStore(element, 'handle');
- if (!events) jqLiteExpandoStore(element, 'events', events = {});
- if (!handle) jqLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
- forEach(type.split(' '), function(type){
- var eventFns = events[type];
- if (!eventFns) {
- if (type == 'mouseenter' || type == 'mouseleave') {
- var contains = document.body.contains || document.body.compareDocumentPosition ?
- function( a, b ) {
-
- var adown = a.nodeType === 9 ? a.documentElement : a,
- bup = b && b.parentNode;
- return a === bup || !!( bup && bup.nodeType === 1 && (
- adown.contains ?
- adown.contains( bup ) :
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
- ));
- } :
- function( a, b ) {
- if ( b ) {
- while ( (b = b.parentNode) ) {
- if ( b === a ) {
- return true;
- }
- }
- }
- return false;
- };
- events[type] = [];
-
-
-
- var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"};
- onFn(element, eventmap[type], function(event) {
- var target = this, related = event.relatedTarget;
-
-
- if ( !related || (related !== target && !contains(target, related)) ){
- handle(event, type);
- }
- });
- } else {
- addEventListenerFn(element, type, handle);
- events[type] = [];
- }
- eventFns = events[type];
- }
- eventFns.push(fn);
- });
- },
- off: jqLiteOff,
- one: function(element, type, fn) {
- element = jqLite(element);
-
-
-
- element.on(type, function onFn() {
- element.off(type, fn);
- element.off(type, onFn);
- });
- element.on(type, fn);
- },
- replaceWith: function(element, replaceNode) {
- var index, parent = element.parentNode;
- jqLiteDealoc(element);
- forEach(new JQLite(replaceNode), function(node){
- if (index) {
- parent.insertBefore(node, index.nextSibling);
- } else {
- parent.replaceChild(node, element);
- }
- index = node;
- });
- },
- children: function(element) {
- var children = [];
- forEach(element.childNodes, function(element){
- if (element.nodeType === 1)
- children.push(element);
- });
- return children;
- },
- contents: function(element) {
- return element.contentDocument || element.childNodes || [];
- },
- append: function(element, node) {
- forEach(new JQLite(node), function(child){
- if (element.nodeType === 1 || element.nodeType === 11) {
- element.appendChild(child);
- }
- });
- },
- prepend: function(element, node) {
- if (element.nodeType === 1) {
- var index = element.firstChild;
- forEach(new JQLite(node), function(child){
- element.insertBefore(child, index);
- });
- }
- },
- wrap: function(element, wrapNode) {
- wrapNode = jqLite(wrapNode)[0];
- var parent = element.parentNode;
- if (parent) {
- parent.replaceChild(wrapNode, element);
- }
- wrapNode.appendChild(element);
- },
- remove: function(element) {
- jqLiteDealoc(element);
- var parent = element.parentNode;
- if (parent) parent.removeChild(element);
- },
- after: function(element, newElement) {
- var index = element, parent = element.parentNode;
- forEach(new JQLite(newElement), function(node){
- parent.insertBefore(node, index.nextSibling);
- index = node;
- });
- },
- addClass: jqLiteAddClass,
- removeClass: jqLiteRemoveClass,
- toggleClass: function(element, selector, condition) {
- if (selector) {
- forEach(selector.split(' '), function(className){
- var classCondition = condition;
- if (isUndefined(classCondition)) {
- classCondition = !jqLiteHasClass(element, className);
- }
- (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
- });
- }
- },
- parent: function(element) {
- var parent = element.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- next: function(element) {
- if (element.nextElementSibling) {
- return element.nextElementSibling;
- }
-
- var elm = element.nextSibling;
- while (elm != null && elm.nodeType !== 1) {
- elm = elm.nextSibling;
- }
- return elm;
- },
- find: function(element, selector) {
- if (element.getElementsByTagName) {
- return element.getElementsByTagName(selector);
- } else {
- return [];
- }
- },
- clone: jqLiteClone,
- triggerHandler: function(element, eventName, eventData) {
-
- var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName],
- eventFnsCopy = shallowCopy(eventFns || []);
- eventData = eventData || [];
- var event = [{
- preventDefault: noop,
- stopPropagation: noop
- }];
- forEach(eventFnsCopy, function(fn) {
- fn.apply(element, event.concat(eventData));
- });
- }
- }, function(fn, name){
-
- JQLite.prototype[name] = function(arg1, arg2, arg3) {
- var value;
- for(var i=0; i < this.length; i++) {
- if (isUndefined(value)) {
- value = fn(this[i], arg1, arg2, arg3);
- if (isDefined(value)) {
-
- value = jqLite(value);
- }
- } else {
- jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
- }
- }
- return isDefined(value) ? value : this;
- };
-
- JQLite.prototype.bind = JQLite.prototype.on;
- JQLite.prototype.unbind = JQLite.prototype.off;
- });
- function hashKey(obj, nextUidFn) {
- var objType = typeof obj,
- key;
- if (objType == 'function' || (objType == 'object' && obj !== null)) {
- if (typeof (key = obj.$$hashKey) == 'function') {
-
- key = obj.$$hashKey();
- } else if (key === undefined) {
- key = obj.$$hashKey = (nextUidFn || nextUid)();
- }
- } else {
- key = obj;
- }
- return objType + ':' + key;
- }
- function HashMap(array, isolatedUid) {
- if (isolatedUid) {
- var uid = 0;
- this.nextUid = function() {
- return ++uid;
- };
- }
- forEach(array, this.put, this);
- }
- HashMap.prototype = {
-
- put: function(key, value) {
- this[hashKey(key, this.nextUid)] = value;
- },
-
- get: function(key) {
- return this[hashKey(key, this.nextUid)];
- },
-
- remove: function(key) {
- var value = this[key = hashKey(key, this.nextUid)];
- delete this[key];
- return value;
- }
- };
- var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
- var FN_ARG_SPLIT = /,/;
- var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
- var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
- var $injectorMinErr = minErr('$injector');
- function annotate(fn) {
- var $inject,
- fnText,
- argDecl,
- last;
- if (typeof fn === 'function') {
- if (!($inject = fn.$inject)) {
- $inject = [];
- if (fn.length) {
- fnText = fn.toString().replace(STRIP_COMMENTS, '');
- argDecl = fnText.match(FN_ARGS);
- forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
- arg.replace(FN_ARG, function(all, underscore, name){
- $inject.push(name);
- });
- });
- }
- fn.$inject = $inject;
- }
- } else if (isArray(fn)) {
- last = fn.length - 1;
- assertArgFn(fn[last], 'fn');
- $inject = fn.slice(0, last);
- } else {
- assertArgFn(fn, 'fn', true);
- }
- return $inject;
- }
- function createInjector(modulesToLoad) {
- var INSTANTIATING = {},
- providerSuffix = 'Provider',
- path = [],
- loadedModules = new HashMap([], true),
- providerCache = {
- $provide: {
- provider: supportObject(provider),
- factory: supportObject(factory),
- service: supportObject(service),
- value: supportObject(value),
- constant: supportObject(constant),
- decorator: decorator
- }
- },
- providerInjector = (providerCache.$injector =
- createInternalInjector(providerCache, function() {
- throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
- })),
- instanceCache = {},
- instanceInjector = (instanceCache.$injector =
- createInternalInjector(instanceCache, function(servicename) {
- var provider = providerInjector.get(servicename + providerSuffix);
- return instanceInjector.invoke(provider.$get, provider);
- }));
- forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
- return instanceInjector;
-
-
-
- function supportObject(delegate) {
- return function(key, value) {
- if (isObject(key)) {
- forEach(key, reverseParams(delegate));
- } else {
- return delegate(key, value);
- }
- };
- }
- function provider(name, provider_) {
- assertNotHasOwnProperty(name, 'service');
- if (isFunction(provider_) || isArray(provider_)) {
- provider_ = providerInjector.instantiate(provider_);
- }
- if (!provider_.$get) {
- throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
- }
- return providerCache[name + providerSuffix] = provider_;
- }
- function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
- function service(name, constructor) {
- return factory(name, ['$injector', function($injector) {
- return $injector.instantiate(constructor);
- }]);
- }
- function value(name, val) { return factory(name, valueFn(val)); }
- function constant(name, value) {
- assertNotHasOwnProperty(name, 'constant');
- providerCache[name] = value;
- instanceCache[name] = value;
- }
- function decorator(serviceName, decorFn) {
- var origProvider = providerInjector.get(serviceName + providerSuffix),
- orig$get = origProvider.$get;
- origProvider.$get = function() {
- var origInstance = instanceInjector.invoke(orig$get, origProvider);
- return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
- };
- }
-
-
-
- function loadModules(modulesToLoad){
- var runBlocks = [], moduleFn, invokeQueue, i, ii;
- forEach(modulesToLoad, function(module) {
- if (loadedModules.get(module)) return;
- loadedModules.put(module, true);
- try {
- if (isString(module)) {
- moduleFn = angularModule(module);
- runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
- for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
- var invokeArgs = invokeQueue[i],
- provider = providerInjector.get(invokeArgs[0]);
- provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
- }
- } else if (isFunction(module)) {
- runBlocks.push(providerInjector.invoke(module));
- } else if (isArray(module)) {
- runBlocks.push(providerInjector.invoke(module));
- } else {
- assertArgFn(module, 'module');
- }
- } catch (e) {
- if (isArray(module)) {
- module = module[module.length - 1];
- }
- if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
-
-
-
-
-
- e = e.message + '\n' + e.stack;
- }
- throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
- module, e.stack || e.message || e);
- }
- });
- return runBlocks;
- }
-
-
-
- function createInternalInjector(cache, factory) {
- function getService(serviceName) {
- if (cache.hasOwnProperty(serviceName)) {
- if (cache[serviceName] === INSTANTIATING) {
- throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
- serviceName + ' <- ' + path.join(' <- '));
- }
- return cache[serviceName];
- } else {
- try {
- path.unshift(serviceName);
- cache[serviceName] = INSTANTIATING;
- return cache[serviceName] = factory(serviceName);
- } catch (err) {
- if (cache[serviceName] === INSTANTIATING) {
- delete cache[serviceName];
- }
- throw err;
- } finally {
- path.shift();
- }
- }
- }
- function invoke(fn, self, locals){
- var args = [],
- $inject = annotate(fn),
- length, i,
- key;
- for(i = 0, length = $inject.length; i < length; i++) {
- key = $inject[i];
- if (typeof key !== 'string') {
- throw $injectorMinErr('itkn',
- 'Incorrect injection token! Expected service name as string, got {0}', key);
- }
- args.push(
- locals && locals.hasOwnProperty(key)
- ? locals[key]
- : getService(key)
- );
- }
- if (isArray(fn)) {
- fn = fn[length];
- }
-
-
- return fn.apply(self, args);
- }
- function instantiate(Type, locals) {
- var Constructor = function() {},
- instance, returnedValue;
-
-
- Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
- instance = new Constructor();
- returnedValue = invoke(Type, instance, locals);
- return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
- }
- return {
- invoke: invoke,
- instantiate: instantiate,
- get: getService,
- annotate: annotate,
- has: function(name) {
- return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
- }
- };
- }
- }
- function $AnchorScrollProvider() {
- var autoScrollingEnabled = true;
- this.disableAutoScrolling = function() {
- autoScrollingEnabled = false;
- };
- this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
- var document = $window.document;
-
-
-
-
- function getFirstAnchor(list) {
- var result = null;
- forEach(list, function(element) {
- if (!result && lowercase(element.nodeName) === 'a') result = element;
- });
- return result;
- }
- function scroll() {
- var hash = $location.hash(), elm;
-
- if (!hash) $window.scrollTo(0, 0);
-
- else if ((elm = document.getElementById(hash))) elm.scrollIntoView();
-
- else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();
-
- else if (hash === 'top') $window.scrollTo(0, 0);
- }
-
-
- if (autoScrollingEnabled) {
- $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
- function autoScrollWatchAction() {
- $rootScope.$evalAsync(scroll);
- });
- }
- return scroll;
- }];
- }
- var $animateMinErr = minErr('$animate');
- var $AnimateProvider = ['$provide', function($provide) {
- this.$$selectors = {};
-
- this.register = function(name, factory) {
- var key = name + '-animation';
- if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
- "Expecting class selector starting with '.' got '{0}'.", name);
- this.$$selectors[name.substr(1)] = key;
- $provide.factory(key, factory);
- };
-
- this.classNameFilter = function(expression) {
- if(arguments.length === 1) {
- this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
- }
- return this.$$classNameFilter;
- };
- this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) {
- function async(fn) {
- fn && $$asyncCallback(fn);
- }
-
- return {
-
- enter : function(element, parent, after, done) {
- if (after) {
- after.after(element);
- } else {
- if (!parent || !parent[0]) {
- parent = after.parent();
- }
- parent.append(element);
- }
- async(done);
- },
-
- leave : function(element, done) {
- element.remove();
- async(done);
- },
-
- move : function(element, parent, after, done) {
-
-
- this.enter(element, parent, after, done);
- },
-
- addClass : function(element, className, done) {
- className = isString(className) ?
- className :
- isArray(className) ? className.join(' ') : '';
- forEach(element, function (element) {
- jqLiteAddClass(element, className);
- });
- async(done);
- },
-
- removeClass : function(element, className, done) {
- className = isString(className) ?
- className :
- isArray(className) ? className.join(' ') : '';
- forEach(element, function (element) {
- jqLiteRemoveClass(element, className);
- });
- async(done);
- },
-
- setClass : function(element, add, remove, done) {
- forEach(element, function (element) {
- jqLiteAddClass(element, add);
- jqLiteRemoveClass(element, remove);
- });
- async(done);
- },
- enabled : noop
- };
- }];
- }];
- function $$AsyncCallbackProvider(){
- this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
- return $$rAF.supported
- ? function(fn) { return $$rAF(fn); }
- : function(fn) {
- return $timeout(fn, 0, false);
- };
- }];
- }
- function Browser(window, document, $log, $sniffer) {
- var self = this,
- rawDocument = document[0],
- location = window.location,
- history = window.history,
- setTimeout = window.setTimeout,
- clearTimeout = window.clearTimeout,
- pendingDeferIds = {};
- self.isMock = false;
- var outstandingRequestCount = 0;
- var outstandingRequestCallbacks = [];
-
- self.$$completeOutstandingRequest = completeOutstandingRequest;
- self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
-
- function completeOutstandingRequest(fn) {
- try {
- fn.apply(null, sliceArgs(arguments, 1));
- } finally {
- outstandingRequestCount--;
- if (outstandingRequestCount === 0) {
- while(outstandingRequestCallbacks.length) {
- try {
- outstandingRequestCallbacks.pop()();
- } catch (e) {
- $log.error(e);
- }
- }
- }
- }
- }
-
- self.notifyWhenNoOutstandingRequests = function(callback) {
-
-
-
- forEach(pollFns, function(pollFn){ pollFn(); });
- if (outstandingRequestCount === 0) {
- callback();
- } else {
- outstandingRequestCallbacks.push(callback);
- }
- };
-
-
-
- var pollFns = [],
- pollTimeout;
-
- self.addPollFn = function(fn) {
- if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
- pollFns.push(fn);
- return fn;
- };
-
- function startPoller(interval, setTimeout) {
- (function check() {
- forEach(pollFns, function(pollFn){ pollFn(); });
- pollTimeout = setTimeout(check, interval);
- })();
- }
-
-
-
- var lastBrowserUrl = location.href,
- baseElement = document.find('base'),
- newLocation = null;
-
- self.url = function(url, replace) {
-
- if (location !== window.location) location = window.location;
- if (history !== window.history) history = window.history;
-
- if (url) {
- if (lastBrowserUrl == url) return;
- lastBrowserUrl = url;
- if ($sniffer.history) {
- if (replace) history.replaceState(null, '', url);
- else {
- history.pushState(null, '', url);
-
- baseElement.attr('href', baseElement.attr('href'));
- }
- } else {
- newLocation = url;
- if (replace) {
- location.replace(url);
- } else {
- location.href = url;
- }
- }
- return self;
-
- } else {
-
-
-
- return newLocation || location.href.replace(/%27/g,"'");
- }
- };
- var urlChangeListeners = [],
- urlChangeInit = false;
- function fireUrlChange() {
- newLocation = null;
- if (lastBrowserUrl == self.url()) return;
- lastBrowserUrl = self.url();
- forEach(urlChangeListeners, function(listener) {
- listener(self.url());
- });
- }
-
- self.onUrlChange = function(callback) {
-
- if (!urlChangeInit) {
-
-
-
-
- if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);
-
- if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);
-
- else self.addPollFn(fireUrlChange);
- urlChangeInit = true;
- }
- urlChangeListeners.push(callback);
- return callback;
- };
-
-
-
-
- self.baseHref = function() {
- var href = baseElement.attr('href');
- return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
- };
-
-
-
- var lastCookies = {};
- var lastCookieString = '';
- var cookiePath = self.baseHref();
-
- self.cookies = function(name, value) {
-
- var cookieLength, cookieArray, cookie, i, index;
- if (name) {
- if (value === undefined) {
- rawDocument.cookie = escape(name) + "=;path=" + cookiePath +
- ";expires=Thu, 01 Jan 1970 00:00:00 GMT";
- } else {
- if (isString(value)) {
- cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) +
- ';path=' + cookiePath).length + 1;
-
-
-
-
- if (cookieLength > 4096) {
- $log.warn("Cookie '"+ name +
- "' possibly not set or overflowed because it was too large ("+
- cookieLength + " > 4096 bytes)!");
- }
- }
- }
- } else {
- if (rawDocument.cookie !== lastCookieString) {
- lastCookieString = rawDocument.cookie;
- cookieArray = lastCookieString.split("; ");
- lastCookies = {};
- for (i = 0; i < cookieArray.length; i++) {
- cookie = cookieArray[i];
- index = cookie.indexOf('=');
- if (index > 0) {
- name = unescape(cookie.substring(0, index));
-
-
-
- if (lastCookies[name] === undefined) {
- lastCookies[name] = unescape(cookie.substring(index + 1));
- }
- }
- }
- }
- return lastCookies;
- }
- };
-
- self.defer = function(fn, delay) {
- var timeoutId;
- outstandingRequestCount++;
- timeoutId = setTimeout(function() {
- delete pendingDeferIds[timeoutId];
- completeOutstandingRequest(fn);
- }, delay || 0);
- pendingDeferIds[timeoutId] = true;
- return timeoutId;
- };
-
- self.defer.cancel = function(deferId) {
- if (pendingDeferIds[deferId]) {
- delete pendingDeferIds[deferId];
- clearTimeout(deferId);
- completeOutstandingRequest(noop);
- return true;
- }
- return false;
- };
- }
- function $BrowserProvider(){
- this.$get = ['$window', '$log', '$sniffer', '$document',
- function( $window, $log, $sniffer, $document){
- return new Browser($window, $document, $log, $sniffer);
- }];
- }
- function $CacheFactoryProvider() {
- this.$get = function() {
- var caches = {};
- function cacheFactory(cacheId, options) {
- if (cacheId in caches) {
- throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
- }
- var size = 0,
- stats = extend({}, options, {id: cacheId}),
- data = {},
- capacity = (options && options.capacity) || Number.MAX_VALUE,
- lruHash = {},
- freshEnd = null,
- staleEnd = null;
-
- return caches[cacheId] = {
-
- put: function(key, value) {
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
- refresh(lruEntry);
- }
- if (isUndefined(value)) return;
- if (!(key in data)) size++;
- data[key] = value;
- if (size > capacity) {
- this.remove(staleEnd.key);
- }
- return value;
- },
-
- get: function(key) {
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key];
- if (!lruEntry) return;
- refresh(lruEntry);
- }
- return data[key];
- },
-
- remove: function(key) {
- if (capacity < Number.MAX_VALUE) {
- var lruEntry = lruHash[key];
- if (!lruEntry) return;
- if (lruEntry == freshEnd) freshEnd = lruEntry.p;
- if (lruEntry == staleEnd) staleEnd = lruEntry.n;
- link(lruEntry.n,lruEntry.p);
- delete lruHash[key];
- }
- delete data[key];
- size--;
- },
-
- removeAll: function() {
- data = {};
- size = 0;
- lruHash = {};
- freshEnd = staleEnd = null;
- },
-
- destroy: function() {
- data = null;
- stats = null;
- lruHash = null;
- delete caches[cacheId];
- },
-
- info: function() {
- return extend({}, stats, {size: size});
- }
- };
-
- function refresh(entry) {
- if (entry != freshEnd) {
- if (!staleEnd) {
- staleEnd = entry;
- } else if (staleEnd == entry) {
- staleEnd = entry.n;
- }
- link(entry.n, entry.p);
- link(entry, freshEnd);
- freshEnd = entry;
- freshEnd.n = null;
- }
- }
-
- function link(nextEntry, prevEntry) {
- if (nextEntry != prevEntry) {
- if (nextEntry) nextEntry.p = prevEntry;
- if (prevEntry) prevEntry.n = nextEntry;
- }
- }
- }
-
- cacheFactory.info = function() {
- var info = {};
- forEach(caches, function(cache, cacheId) {
- info[cacheId] = cache.info();
- });
- return info;
- };
-
- cacheFactory.get = function(cacheId) {
- return caches[cacheId];
- };
- return cacheFactory;
- };
- }
- function $TemplateCacheProvider() {
- this.$get = ['$cacheFactory', function($cacheFactory) {
- return $cacheFactory('templates');
- }];
- }
- var $compileMinErr = minErr('$compile');
- $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
- function $CompileProvider($provide, $$sanitizeUriProvider) {
- var hasDirectives = {},
- Suffix = 'Directive',
- COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,
- CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/;
-
-
-
- var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
-
- this.directive = function registerDirective(name, directiveFactory) {
- assertNotHasOwnProperty(name, 'directive');
- if (isString(name)) {
- assertArg(directiveFactory, 'directiveFactory');
- if (!hasDirectives.hasOwnProperty(name)) {
- hasDirectives[name] = [];
- $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
- function($injector, $exceptionHandler) {
- var directives = [];
- forEach(hasDirectives[name], function(directiveFactory, index) {
- try {
- var directive = $injector.invoke(directiveFactory);
- if (isFunction(directive)) {
- directive = { compile: valueFn(directive) };
- } else if (!directive.compile && directive.link) {
- directive.compile = valueFn(directive.link);
- }
- directive.priority = directive.priority || 0;
- directive.index = index;
- directive.name = directive.name || name;
- directive.require = directive.require || (directive.controller && directive.name);
- directive.restrict = directive.restrict || 'A';
- directives.push(directive);
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- return directives;
- }]);
- }
- hasDirectives[name].push(directiveFactory);
- } else {
- forEach(name, reverseParams(registerDirective));
- }
- return this;
- };
-
- this.aHrefSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
- return this;
- } else {
- return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
- }
- };
-
- this.imgSrcSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
- return this;
- } else {
- return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
- }
- };
- this.$get = [
- '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
- '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
- function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
- $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
- var Attributes = function(element, attr) {
- this.$$element = element;
- this.$attr = attr || {};
- };
- Attributes.prototype = {
- $normalize: directiveNormalize,
-
- $addClass : function(classVal) {
- if(classVal && classVal.length > 0) {
- $animate.addClass(this.$$element, classVal);
- }
- },
-
- $removeClass : function(classVal) {
- if(classVal && classVal.length > 0) {
- $animate.removeClass(this.$$element, classVal);
- }
- },
-
- $updateClass : function(newClasses, oldClasses) {
- var toAdd = tokenDifference(newClasses, oldClasses);
- var toRemove = tokenDifference(oldClasses, newClasses);
- if(toAdd.length === 0) {
- $animate.removeClass(this.$$element, toRemove);
- } else if(toRemove.length === 0) {
- $animate.addClass(this.$$element, toAdd);
- } else {
- $animate.setClass(this.$$element, toAdd, toRemove);
- }
- },
-
- $set: function(key, value, writeAttr, attrName) {
-
-
-
- var booleanKey = getBooleanAttrName(this.$$element[0], key),
- normalizedVal,
- nodeName;
- if (booleanKey) {
- this.$$element.prop(key, value);
- attrName = booleanKey;
- }
- this[key] = value;
-
- if (attrName) {
- this.$attr[key] = attrName;
- } else {
- attrName = this.$attr[key];
- if (!attrName) {
- this.$attr[key] = attrName = snake_case(key, '-');
- }
- }
- nodeName = nodeName_(this.$$element);
-
- if ((nodeName === 'A' && key === 'href') ||
- (nodeName === 'IMG' && key === 'src')) {
- this[key] = value = $$sanitizeUri(value, key === 'src');
- }
- if (writeAttr !== false) {
- if (value === null || value === undefined) {
- this.$$element.removeAttr(attrName);
- } else {
- this.$$element.attr(attrName, value);
- }
- }
-
- var $$observers = this.$$observers;
- $$observers && forEach($$observers[key], function(fn) {
- try {
- fn(value);
- } catch (e) {
- $exceptionHandler(e);
- }
- });
- },
-
- $observe: function(key, fn) {
- var attrs = this,
- $$observers = (attrs.$$observers || (attrs.$$observers = {})),
- listeners = ($$observers[key] || ($$observers[key] = []));
- listeners.push(fn);
- $rootScope.$evalAsync(function() {
- if (!listeners.$$inter) {
-
- fn(attrs[key]);
- }
- });
- return fn;
- }
- };
- var startSymbol = $interpolate.startSymbol(),
- endSymbol = $interpolate.endSymbol(),
- denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
- ? identity
- : function denormalizeTemplate(template) {
- return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
- },
- NG_ATTR_BINDING = /^ngAttr[A-Z]/;
- return compile;
-
- function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
- previousCompileContext) {
- if (!($compileNodes instanceof jqLite)) {
-
-
- $compileNodes = jqLite($compileNodes);
- }
-
-
- forEach($compileNodes, function(node, index){
- if (node.nodeType == 3 && node.nodeValue.match(/\S+/) ) {
- $compileNodes[index] = node = jqLite(node).wrap('<span></span>').parent()[0];
- }
- });
- var compositeLinkFn =
- compileNodes($compileNodes, transcludeFn, $compileNodes,
- maxPriority, ignoreDirective, previousCompileContext);
- safeAddClass($compileNodes, 'ng-scope');
- return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn){
- assertArg(scope, 'scope');
-
-
- var $linkNode = cloneConnectFn
- ? JQLitePrototype.clone.call($compileNodes)
- : $compileNodes;
- forEach(transcludeControllers, function(instance, name) {
- $linkNode.data('$' + name + 'Controller', instance);
- });
-
- for(var i = 0, ii = $linkNode.length; i<ii; i++) {
- var node = $linkNode[i],
- nodeType = node.nodeType;
- if (nodeType === 1 || nodeType === 9 ) {
- $linkNode.eq(i).data('$scope', scope);
- }
- }
- if (cloneConnectFn) cloneConnectFn($linkNode, scope);
- if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
- return $linkNode;
- };
- }
- function safeAddClass($element, className) {
- try {
- $element.addClass(className);
- } catch(e) {
-
-
- }
- }
-
- function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
- previousCompileContext) {
- var linkFns = [],
- attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound;
- for (var i = 0; i < nodeList.length; i++) {
- attrs = new Attributes();
-
- directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
- ignoreDirective);
- nodeLinkFn = (directives.length)
- ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
- null, [], [], previousCompileContext)
- : null;
- if (nodeLinkFn && nodeLinkFn.scope) {
- safeAddClass(attrs.$$element, 'ng-scope');
- }
- childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
- !(childNodes = nodeList[i].childNodes) ||
- !childNodes.length)
- ? null
- : compileNodes(childNodes,
- nodeLinkFn ? (
- (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
- && nodeLinkFn.transclude) : transcludeFn);
- linkFns.push(nodeLinkFn, childLinkFn);
- linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
-
- previousCompileContext = null;
- }
-
- return linkFnFound ? compositeLinkFn : null;
- function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
- var nodeLinkFn, childLinkFn, node, childScope, i, ii, n, childBoundTranscludeFn;
-
- var nodeListLength = nodeList.length,
- stableNodeList = new Array(nodeListLength);
- for (i = 0; i < nodeListLength; i++) {
- stableNodeList[i] = nodeList[i];
- }
- for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
- node = stableNodeList[n];
- nodeLinkFn = linkFns[i++];
- childLinkFn = linkFns[i++];
- if (nodeLinkFn) {
- if (nodeLinkFn.scope) {
- childScope = scope.$new();
- jqLite.data(node, '$scope', childScope);
- } else {
- childScope = scope;
- }
- if ( nodeLinkFn.transcludeOnThisElement ) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
- } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
- childBoundTranscludeFn = parentBoundTranscludeFn;
- } else if (!parentBoundTranscludeFn && transcludeFn) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
- } else {
- childBoundTranscludeFn = null;
- }
- nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);
- } else if (childLinkFn) {
- childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
- }
- }
- }
- }
- function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
- var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {
- var scopeCreated = false;
- if (!transcludedScope) {
- transcludedScope = scope.$new();
- transcludedScope.$$transcluded = true;
- scopeCreated = true;
- }
- var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn);
- if (scopeCreated) {
- clone.on('$destroy', function() { transcludedScope.$destroy(); });
- }
- return clone;
- };
- return boundTranscludeFn;
- }
-
- function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
- var nodeType = node.nodeType,
- attrsMap = attrs.$attr,
- match,
- className;
- switch(nodeType) {
- case 1:
-
- addDirective(directives,
- directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
-
- for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
- j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
- var attrStartName = false;
- var attrEndName = false;
- attr = nAttrs[j];
- if (!msie || msie >= 8 || attr.specified) {
- name = attr.name;
- value = trim(attr.value);
-
- ngAttrName = directiveNormalize(name);
- if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
- name = snake_case(ngAttrName.substr(6), '-');
- }
- var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
- if (ngAttrName === directiveNName + 'Start') {
- attrStartName = name;
- attrEndName = name.substr(0, name.length - 5) + 'end';
- name = name.substr(0, name.length - 6);
- }
- nName = directiveNormalize(name.toLowerCase());
- attrsMap[nName] = name;
- if (isNgAttr || !attrs.hasOwnProperty(nName)) {
- attrs[nName] = value;
- if (getBooleanAttrName(node, nName)) {
- attrs[nName] = true;
- }
- }
- addAttrInterpolateDirective(node, directives, value, nName);
- addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
- attrEndName);
- }
- }
-
- className = node.className;
- if (isString(className) && className !== '') {
- while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
- nName = directiveNormalize(match[2]);
- if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
- attrs[nName] = trim(match[3]);
- }
- className = className.substr(match.index + match[0].length);
- }
- }
- break;
- case 3:
- addTextInterpolateDirective(directives, node.nodeValue);
- break;
- case 8:
- try {
- match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
- if (match) {
- nName = directiveNormalize(match[1]);
- if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
- attrs[nName] = trim(match[2]);
- }
- }
- } catch (e) {
-
-
-
- }
- break;
- }
- directives.sort(byPriority);
- return directives;
- }
-
- function groupScan(node, attrStart, attrEnd) {
- var nodes = [];
- var depth = 0;
- if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
- var startNode = node;
- do {
- if (!node) {
- throw $compileMinErr('uterdir',
- "Unterminated attribute, found '{0}' but no matching '{1}' found.",
- attrStart, attrEnd);
- }
- if (node.nodeType == 1 ) {
- if (node.hasAttribute(attrStart)) depth++;
- if (node.hasAttribute(attrEnd)) depth--;
- }
- nodes.push(node);
- node = node.nextSibling;
- } while (depth > 0);
- } else {
- nodes.push(node);
- }
- return jqLite(nodes);
- }
-
- function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
- return function(scope, element, attrs, controllers, transcludeFn) {
- element = groupScan(element[0], attrStart, attrEnd);
- return linkFn(scope, element, attrs, controllers, transcludeFn);
- };
- }
-
- function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
- jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
- previousCompileContext) {
- previousCompileContext = previousCompileContext || {};
- var terminalPriority = -Number.MAX_VALUE,
- newScopeDirective,
- controllerDirectives = previousCompileContext.controllerDirectives,
- newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
- templateDirective = previousCompileContext.templateDirective,
- nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
- hasTranscludeDirective = false,
- hasTemplate = false,
- hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
- $compileNode = templateAttrs.$$element = jqLite(compileNode),
- directive,
- directiveName,
- $template,
- replaceDirective = originalReplaceDirective,
- childTranscludeFn = transcludeFn,
- linkFn,
- directiveValue;
-
- for(var i = 0, ii = directives.length; i < ii; i++) {
- directive = directives[i];
- var attrStart = directive.$$start;
- var attrEnd = directive.$$end;
-
- if (attrStart) {
- $compileNode = groupScan(compileNode, attrStart, attrEnd);
- }
- $template = undefined;
- if (terminalPriority > directive.priority) {
- break;
- }
- if (directiveValue = directive.scope) {
- newScopeDirective = newScopeDirective || directive;
-
-
- if (!directive.templateUrl) {
- assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
- $compileNode);
- if (isObject(directiveValue)) {
- newIsolateScopeDirective = directive;
- }
- }
- }
- directiveName = directive.name;
- if (!directive.templateUrl && directive.controller) {
- directiveValue = directive.controller;
- controllerDirectives = controllerDirectives || {};
- assertNoDuplicate("'" + directiveName + "' controller",
- controllerDirectives[directiveName], directive, $compileNode);
- controllerDirectives[directiveName] = directive;
- }
- if (directiveValue = directive.transclude) {
- hasTranscludeDirective = true;
-
-
-
- if (!directive.$$tlb) {
- assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
- nonTlbTranscludeDirective = directive;
- }
- if (directiveValue == 'element') {
- hasElementTranscludeDirective = true;
- terminalPriority = directive.priority;
- $template = $compileNode;
- $compileNode = templateAttrs.$$element =
- jqLite(document.createComment(' ' + directiveName + ': ' +
- templateAttrs[directiveName] + ' '));
- compileNode = $compileNode[0];
- replaceWith(jqCollection, sliceArgs($template), compileNode);
- childTranscludeFn = compile($template, transcludeFn, terminalPriority,
- replaceDirective && replaceDirective.name, {
-
-
-
-
-
-
-
- nonTlbTranscludeDirective: nonTlbTranscludeDirective
- });
- } else {
- $template = jqLite(jqLiteClone(compileNode)).contents();
- $compileNode.empty();
- childTranscludeFn = compile($template, transcludeFn);
- }
- }
- if (directive.template) {
- hasTemplate = true;
- assertNoDuplicate('template', templateDirective, directive, $compileNode);
- templateDirective = directive;
- directiveValue = (isFunction(directive.template))
- ? directive.template($compileNode, templateAttrs)
- : directive.template;
- directiveValue = denormalizeTemplate(directiveValue);
- if (directive.replace) {
- replaceDirective = directive;
- if (jqLiteIsTextNode(directiveValue)) {
- $template = [];
- } else {
- $template = jqLite(trim(directiveValue));
- }
- compileNode = $template[0];
- if ($template.length != 1 || compileNode.nodeType !== 1) {
- throw $compileMinErr('tplrt',
- "Template for directive '{0}' must have exactly one root element. {1}",
- directiveName, '');
- }
- replaceWith(jqCollection, $compileNode, compileNode);
- var newTemplateAttrs = {$attr: {}};
-
-
-
-
-
- var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
- var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
- if (newIsolateScopeDirective) {
- markDirectivesAsIsolate(templateDirectives);
- }
- directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
- mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
- ii = directives.length;
- } else {
- $compileNode.html(directiveValue);
- }
- }
- if (directive.templateUrl) {
- hasTemplate = true;
- assertNoDuplicate('template', templateDirective, directive, $compileNode);
- templateDirective = directive;
- if (directive.replace) {
- replaceDirective = directive;
- }
- nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
- templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
- controllerDirectives: controllerDirectives,
- newIsolateScopeDirective: newIsolateScopeDirective,
- templateDirective: templateDirective,
- nonTlbTranscludeDirective: nonTlbTranscludeDirective
- });
- ii = directives.length;
- } else if (directive.compile) {
- try {
- linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
- if (isFunction(linkFn)) {
- addLinkFns(null, linkFn, attrStart, attrEnd);
- } else if (linkFn) {
- addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
- }
- } catch (e) {
- $exceptionHandler(e, startingTag($compileNode));
- }
- }
- if (directive.terminal) {
- nodeLinkFn.terminal = true;
- terminalPriority = Math.max(terminalPriority, directive.priority);
- }
- }
- nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
- nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
- nodeLinkFn.templateOnThisElement = hasTemplate;
- nodeLinkFn.transclude = childTranscludeFn;
- previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
-
- return nodeLinkFn;
-
- function addLinkFns(pre, post, attrStart, attrEnd) {
- if (pre) {
- if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
- pre.require = directive.require;
- pre.directiveName = directiveName;
- if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
- pre = cloneAndAnnotateFn(pre, {isolateScope: true});
- }
- preLinkFns.push(pre);
- }
- if (post) {
- if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
- post.require = directive.require;
- post.directiveName = directiveName;
- if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
- post = cloneAndAnnotateFn(post, {isolateScope: true});
- }
- postLinkFns.push(post);
- }
- }
- function getControllers(directiveName, require, $element, elementControllers) {
- var value, retrievalMethod = 'data', optional = false;
- if (isString(require)) {
- while((value = require.charAt(0)) == '^' || value == '?') {
- require = require.substr(1);
- if (value == '^') {
- retrievalMethod = 'inheritedData';
- }
- optional = optional || value == '?';
- }
- value = null;
- if (elementControllers && retrievalMethod === 'data') {
- value = elementControllers[require];
- }
- value = value || $element[retrievalMethod]('$' + require + 'Controller');
- if (!value && !optional) {
- throw $compileMinErr('ctreq',
- "Controller '{0}', required by directive '{1}', can't be found!",
- require, directiveName);
- }
- return value;
- } else if (isArray(require)) {
- value = [];
- forEach(require, function(require) {
- value.push(getControllers(directiveName, require, $element, elementControllers));
- });
- }
- return value;
- }
- function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
- var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;
- attrs = (compileNode === linkNode)
- ? templateAttrs
- : shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
- $element = attrs.$$element;
- if (newIsolateScopeDirective) {
- var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
- isolateScope = scope.$new(true);
- if (templateDirective && (templateDirective === newIsolateScopeDirective ||
- templateDirective === newIsolateScopeDirective.$$originalDirective)) {
- $element.data('$isolateScope', isolateScope);
- } else {
- $element.data('$isolateScopeNoTemplate', isolateScope);
- }
- safeAddClass($element, 'ng-isolate-scope');
- forEach(newIsolateScopeDirective.scope, function(definition, scopeName) {
- var match = definition.match(LOCAL_REGEXP) || [],
- attrName = match[3] || scopeName,
- optional = (match[2] == '?'),
- mode = match[1],
- lastValue,
- parentGet, parentSet, compare;
- isolateScope.$$isolateBindings[scopeName] = mode + attrName;
- switch (mode) {
- case '@':
- attrs.$observe(attrName, function(value) {
- isolateScope[scopeName] = value;
- });
- attrs.$$observers[attrName].$$scope = scope;
- if( attrs[attrName] ) {
-
-
- isolateScope[scopeName] = $interpolate(attrs[attrName])(scope);
- }
- break;
- case '=':
- if (optional && !attrs[attrName]) {
- return;
- }
- parentGet = $parse(attrs[attrName]);
- if (parentGet.literal) {
- compare = equals;
- } else {
- compare = function(a,b) { return a === b; };
- }
- parentSet = parentGet.assign || function() {
-
- lastValue = isolateScope[scopeName] = parentGet(scope);
- throw $compileMinErr('nonassign',
- "Expression '{0}' used with directive '{1}' is non-assignable!",
- attrs[attrName], newIsolateScopeDirective.name);
- };
- lastValue = isolateScope[scopeName] = parentGet(scope);
- isolateScope.$watch(function parentValueWatch() {
- var parentValue = parentGet(scope);
- if (!compare(parentValue, isolateScope[scopeName])) {
-
- if (!compare(parentValue, lastValue)) {
-
- isolateScope[scopeName] = parentValue;
- } else {
-
- parentSet(scope, parentValue = isolateScope[scopeName]);
- }
- }
- return lastValue = parentValue;
- }, null, parentGet.literal);
- break;
- case '&':
- parentGet = $parse(attrs[attrName]);
- isolateScope[scopeName] = function(locals) {
- return parentGet(scope, locals);
- };
- break;
- default:
- throw $compileMinErr('iscp',
- "Invalid isolate scope definition for directive '{0}'." +
- " Definition: {... {1}: '{2}' ...}",
- newIsolateScopeDirective.name, scopeName, definition);
- }
- });
- }
- transcludeFn = boundTranscludeFn && controllersBoundTransclude;
- if (controllerDirectives) {
- forEach(controllerDirectives, function(directive) {
- var locals = {
- $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
- $element: $element,
- $attrs: attrs,
- $transclude: transcludeFn
- }, controllerInstance;
- controller = directive.controller;
- if (controller == '@') {
- controller = attrs[directive.name];
- }
- controllerInstance = $controller(controller, locals);
-
-
-
-
-
- elementControllers[directive.name] = controllerInstance;
- if (!hasElementTranscludeDirective) {
- $element.data('$' + directive.name + 'Controller', controllerInstance);
- }
- if (directive.controllerAs) {
- locals.$scope[directive.controllerAs] = controllerInstance;
- }
- });
- }
-
- for(i = 0, ii = preLinkFns.length; i < ii; i++) {
- try {
- linkFn = preLinkFns[i];
- linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
- linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
- } catch (e) {
- $exceptionHandler(e, startingTag($element));
- }
- }
-
-
-
- var scopeToChild = scope;
- if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
- scopeToChild = isolateScope;
- }
- childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
-
- for(i = postLinkFns.length - 1; i >= 0; i--) {
- try {
- linkFn = postLinkFns[i];
- linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
- linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
- } catch (e) {
- $exceptionHandler(e, startingTag($element));
- }
- }
-
- function controllersBoundTransclude(scope, cloneAttachFn) {
- var transcludeControllers;
-
- if (arguments.length < 2) {
- cloneAttachFn = scope;
- scope = undefined;
- }
- if (hasElementTranscludeDirective) {
- transcludeControllers = elementControllers;
- }
- return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers);
- }
- }
- }
- function markDirectivesAsIsolate(directives) {
-
- for (var j = 0, jj = directives.length; j < jj; j++) {
- directives[j] = inherit(directives[j], {$$isolateScope: true});
- }
- }
-
- function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
- endAttrName) {
- if (name === ignoreDirective) return null;
- var match = null;
- if (hasDirectives.hasOwnProperty(name)) {
- for(var directive, directives = $injector.get(name + Suffix),
- i = 0, ii = directives.length; i<ii; i++) {
- try {
- directive = directives[i];
- if ( (maxPriority === undefined || maxPriority > directive.priority) &&
- directive.restrict.indexOf(location) != -1) {
- if (startAttrName) {
- directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
- }
- tDirectives.push(directive);
- match = directive;
- }
- } catch(e) { $exceptionHandler(e); }
- }
- }
- return match;
- }
-
- function mergeTemplateAttributes(dst, src) {
- var srcAttr = src.$attr,
- dstAttr = dst.$attr,
- $element = dst.$$element;
-
- forEach(dst, function(value, key) {
- if (key.charAt(0) != '$') {
- if (src[key] && src[key] !== value) {
- value += (key === 'style' ? ';' : ' ') + src[key];
- }
- dst.$set(key, value, true, srcAttr[key]);
- }
- });
- // copy the new attributes on the old attrs object
- forEach(src, function(value, key) {
- if (key == 'class') {
- safeAddClass($element, value);
- dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
- } else if (key == 'style') {
- $element.attr('style', $element.attr('style') + ';' + value);
- dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
-
-
-
- } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
- dst[key] = value;
- dstAttr[key] = srcAttr[key];
- }
- });
- }
- function compileTemplateUrl(directives, $compileNode, tAttrs,
- $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
- var linkQueue = [],
- afterTemplateNodeLinkFn,
- afterTemplateChildLinkFn,
- beforeTemplateCompileNode = $compileNode[0],
- origAsyncDirective = directives.shift(),
-
- derivedSyncDirective = extend({}, origAsyncDirective, {
- templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
- }),
- templateUrl = (isFunction(origAsyncDirective.templateUrl))
- ? origAsyncDirective.templateUrl($compileNode, tAttrs)
- : origAsyncDirective.templateUrl;
- $compileNode.empty();
- $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
- success(function(content) {
- var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
- content = denormalizeTemplate(content);
- if (origAsyncDirective.replace) {
- if (jqLiteIsTextNode(content)) {
- $template = [];
- } else {
- $template = jqLite(trim(content));
- }
- compileNode = $template[0];
- if ($template.length != 1 || compileNode.nodeType !== 1) {
- throw $compileMinErr('tplrt',
- "Template for directive '{0}' must have exactly one root element. {1}",
- origAsyncDirective.name, templateUrl);
- }
- tempTemplateAttrs = {$attr: {}};
- replaceWith($rootElement, $compileNode, compileNode);
- var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
- if (isObject(origAsyncDirective.scope)) {
- markDirectivesAsIsolate(templateDirectives);
- }
- directives = templateDirectives.concat(directives);
- mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
- } else {
- compileNode = beforeTemplateCompileNode;
- $compileNode.html(content);
- }
- directives.unshift(derivedSyncDirective);
- afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
- childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
- previousCompileContext);
- forEach($rootElement, function(node, i) {
- if (node == compileNode) {
- $rootElement[i] = $compileNode[0];
- }
- });
- afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
- while(linkQueue.length) {
- var scope = linkQueue.shift(),
- beforeTemplateLinkNode = linkQueue.shift(),
- linkRootElement = linkQueue.shift(),
- boundTranscludeFn = linkQueue.shift(),
- linkNode = $compileNode[0];
- if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
- var oldClasses = beforeTemplateLinkNode.className;
- if (!(previousCompileContext.hasElementTranscludeDirective &&
- origAsyncDirective.replace)) {
-
- linkNode = jqLiteClone(compileNode);
- }
- replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
-
- safeAddClass(jqLite(linkNode), oldClasses);
- }
- if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
- } else {
- childBoundTranscludeFn = boundTranscludeFn;
- }
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
- childBoundTranscludeFn);
- }
- linkQueue = null;
- }).
- error(function(response, code, headers, config) {
- throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url);
- });
- return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
- var childBoundTranscludeFn = boundTranscludeFn;
- if (linkQueue) {
- linkQueue.push(scope);
- linkQueue.push(node);
- linkQueue.push(rootElement);
- linkQueue.push(childBoundTranscludeFn);
- } else {
- if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
- childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
- }
- afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
- }
- };
- }
-
- function byPriority(a, b) {
- var diff = b.priority - a.priority;
- if (diff !== 0) return diff;
- if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
- return a.index - b.index;
- }
- function assertNoDuplicate(what, previousDirective, directive, element) {
- if (previousDirective) {
- throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
- previousDirective.name, directive.name, what, startingTag(element));
- }
- }
- function addTextInterpolateDirective(directives, text) {
- var interpolateFn = $interpolate(text, true);
- if (interpolateFn) {
- directives.push({
- priority: 0,
- compile: function textInterpolateCompileFn(templateNode) {
-
-
- var parent = templateNode.parent(), hasCompileParent = parent.length;
- if (hasCompileParent) safeAddClass(templateNode.parent(), 'ng-binding');
- return function textInterpolateLinkFn(scope, node) {
- var parent = node.parent(),
- bindings = parent.data('$binding') || [];
- bindings.push(interpolateFn);
- parent.data('$binding', bindings);
- if (!hasCompileParent) safeAddClass(parent, 'ng-binding');
- scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
- node[0].nodeValue = value;
- });
- };
- }
- });
- }
- }
- function getTrustedContext(node, attrNormalizedName) {
- if (attrNormalizedName == "srcdoc") {
- return $sce.HTML;
- }
- var tag = nodeName_(node);
-
- if (attrNormalizedName == "xlinkHref" ||
- (tag == "FORM" && attrNormalizedName == "action") ||
- (tag != "IMG" && (attrNormalizedName == "src" ||
- attrNormalizedName == "ngSrc"))) {
- return $sce.RESOURCE_URL;
- }
- }
- function addAttrInterpolateDirective(node, directives, value, name) {
- var interpolateFn = $interpolate(value, true);
-
- if (!interpolateFn) return;
- if (name === "multiple" && nodeName_(node) === "SELECT") {
- throw $compileMinErr("selmulti",
- "Binding to the 'multiple' attribute is not supported. Element: {0}",
- startingTag(node));
- }
- directives.push({
- priority: 100,
- compile: function() {
- return {
- pre: function attrInterpolatePreLinkFn(scope, element, attr) {
- var $$observers = (attr.$$observers || (attr.$$observers = {}));
- if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
- throw $compileMinErr('nodomevents',
- "Interpolations for HTML DOM event attributes are disallowed. Please use the " +
- "ng- versions (such as ng-click instead of onclick) instead.");
- }
-
-
- interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name));
-
-
- if (!interpolateFn) return;
-
-
- attr[name] = interpolateFn(scope);
- ($$observers[name] || ($$observers[name] = [])).$$inter = true;
- (attr.$$observers && attr.$$observers[name].$$scope || scope).
- $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
-
-
-
-
-
-
- if(name === 'class' && newValue != oldValue) {
- attr.$updateClass(newValue, oldValue);
- } else {
- attr.$set(name, newValue);
- }
- });
- }
- };
- }
- });
- }
- /**
- * This is a special jqLite.replaceWith, which can replace items which
- * have no parents, provided that the containing jqLite collection is provided.
- *
- * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
- * in the root of the tree.
- * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
- * the shell, but replace its DOM node reference.
- * @param {Node} newNode The new DOM node.
- */
- function replaceWith($rootElement, elementsToRemove, newNode) {
- var firstElementToRemove = elementsToRemove[0],
- removeCount = elementsToRemove.length,
- parent = firstElementToRemove.parentNode,
- i, ii;
- if ($rootElement) {
- for(i = 0, ii = $rootElement.length; i < ii; i++) {
- if ($rootElement[i] == firstElementToRemove) {
- $rootElement[i++] = newNode;
- for (var j = i, j2 = j + removeCount - 1,
- jj = $rootElement.length;
- j < jj; j++, j2++) {
- if (j2 < jj) {
- $rootElement[j] = $rootElement[j2];
- } else {
- delete $rootElement[j];
- }
- }
- $rootElement.length -= removeCount - 1;
- break;
- }
- }
- }
- if (parent) {
- parent.replaceChild(newNode, firstElementToRemove);
- }
- var fragment = document.createDocumentFragment();
- fragment.appendChild(firstElementToRemove);
- newNode[jqLite.expando] = firstElementToRemove[jqLite.expando];
- for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
- var element = elementsToRemove[k];
- jqLite(element).remove(); // must do this way to clean up expando
- fragment.appendChild(element);
- delete elementsToRemove[k];
- }
- elementsToRemove[0] = newNode;
- elementsToRemove.length = 1;
- }
- function cloneAndAnnotateFn(fn, annotation) {
- return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
- }
- }];
- }
- var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
- function directiveNormalize(name) {
- return camelCase(name.replace(PREFIX_REGEXP, ''));
- }
- function nodesetLinkingFn(
- /* angular.Scope */ scope,
- /* NodeList */ nodeList,
- /* Element */ rootElement,
- /* function(Function) */ boundTranscludeFn
- ){}
- function directiveLinkingFn(
- /* nodesetLinkingFn */ nodesetLinkingFn,
- /* angular.Scope */ scope,
- /* Node */ node,
- /* Element */ rootElement,
- /* function(Function) */ boundTranscludeFn
- ){}
- function tokenDifference(str1, str2) {
- var values = '',
- tokens1 = str1.split(/\s+/),
- tokens2 = str2.split(/\s+/);
- outer:
- for(var i = 0; i < tokens1.length; i++) {
- var token = tokens1[i];
- for(var j = 0; j < tokens2.length; j++) {
- if(token == tokens2[j]) continue outer;
- }
- values += (values.length > 0 ? ' ' : '') + token;
- }
- return values;
- }
- function $ControllerProvider() {
- var controllers = {},
- CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
-
- this.register = function(name, constructor) {
- assertNotHasOwnProperty(name, 'controller');
- if (isObject(name)) {
- extend(controllers, name);
- } else {
- controllers[name] = constructor;
- }
- };
- this.$get = ['$injector', '$window', function($injector, $window) {
-
- return function(expression, locals) {
- var instance, match, constructor, identifier;
- if(isString(expression)) {
- match = expression.match(CNTRL_REG),
- constructor = match[1],
- identifier = match[3];
- expression = controllers.hasOwnProperty(constructor)
- ? controllers[constructor]
- : getter(locals.$scope, constructor, true) || getter($window, constructor, true);
- assertArgFn(expression, constructor, true);
- }
- instance = $injector.instantiate(expression, locals);
- if (identifier) {
- if (!(locals && typeof locals.$scope === 'object')) {
- throw minErr('$controller')('noscp',
- "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
- constructor || expression.name, identifier);
- }
- locals.$scope[identifier] = instance;
- }
- return instance;
- };
- }];
- }
- /**
- * @ngdoc service
- * @name $document
- * @requires $window
- *
- * @description
- * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
- *
- * @example
- <example module="documentExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <p>$document title: <b ng-bind="title"></b></p>
- <p>window.document title: <b ng-bind="windowTitle"></b></p>
- </div>
- </file>
- <file name="script.js">
- angular.module('documentExample', [])
- .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
- $scope.title = $document[0].title;
- $scope.windowTitle = angular.element(window.document)[0].title;
- }]);
- </file>
- </example>
- */
- function $DocumentProvider(){
- this.$get = ['$window', function(window){
- return jqLite(window.document);
- }];
- }
- /**
- * @ngdoc service
- * @name $exceptionHandler
- * @requires ng.$log
- *
- * @description
- * Any uncaught exception in angular expressions is delegated to this service.
- * The default implementation simply delegates to `$log.error` which logs it into
- * the browser console.
- *
- * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
- * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
- *
- * ## Example:
- *
- * ```js
- * angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {
- * return function (exception, cause) {
- * exception.message += ' (caused by "' + cause + '")';
- * throw exception;
- * };
- * });
- * ```
- *
- * This example will override the normal action of `$exceptionHandler`, to make angular
- * exceptions fail hard when they happen, instead of just logging to the console.
- *
- * @param {Error} exception Exception associated with the error.
- * @param {string=} cause optional information about the context in which
- * the error was thrown.
- *
- */
- function $ExceptionHandlerProvider() {
- this.$get = ['$log', function($log) {
- return function(exception, cause) {
- $log.error.apply($log, arguments);
- };
- }];
- }
- /**
- * Parse headers into key value object
- *
- * @param {string} headers Raw headers as a string
- * @returns {Object} Parsed headers as key value object
- */
- function parseHeaders(headers) {
- var parsed = {}, key, val, i;
- if (!headers) return parsed;
- forEach(headers.split('\n'), function(line) {
- i = line.indexOf(':');
- key = lowercase(trim(line.substr(0, i)));
- val = trim(line.substr(i + 1));
- if (key) {
- parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
- }
- });
- return parsed;
- }
- /**
- * Returns a function that provides access to parsed headers.
- *
- * Headers are lazy parsed when first requested.
- * @see parseHeaders
- *
- * @param {(string|Object)} headers Headers to provide access to.
- * @returns {function(string=)} Returns a getter function which if called with:
- *
- * - if called with single an argument returns a single header value or null
- * - if called with no arguments returns an object containing all headers.
- */
- function headersGetter(headers) {
- var headersObj = isObject(headers) ? headers : undefined;
- return function(name) {
- if (!headersObj) headersObj = parseHeaders(headers);
- if (name) {
- return headersObj[lowercase(name)] || null;
- }
- return headersObj;
- };
- }
- /**
- * Chain all given functions
- *
- * This function is used for both request and response transforming
- *
- * @param {*} data Data to transform.
- * @param {function(string=)} headers Http headers getter fn.
- * @param {(Function|Array.<Function>)} fns Function or an array of functions.
- * @returns {*} Transformed data.
- */
- function transformData(data, headers, fns) {
- if (isFunction(fns))
- return fns(data, headers);
- forEach(fns, function(fn) {
- data = fn(data, headers);
- });
- return data;
- }
- function isSuccess(status) {
- return 200 <= status && status < 300;
- }
- /**
- * @ngdoc provider
- * @name $httpProvider
- * @description
- * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
- * */
- function $HttpProvider() {
- var JSON_START = /^\s*(\[|\{[^\{])/,
- JSON_END = /[\}\]]\s*$/,
- PROTECTION_PREFIX = /^\)\]\}',?\n/,
- CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
-
- var defaults = this.defaults = {
-
- transformResponse: [function(data) {
- if (isString(data)) {
-
- data = data.replace(PROTECTION_PREFIX, '');
- if (JSON_START.test(data) && JSON_END.test(data))
- data = fromJson(data);
- }
- return data;
- }],
-
- transformRequest: [function(d) {
- return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;
- }],
-
- headers: {
- common: {
- 'Accept': 'application/json, text/plain, */*'
- },
- post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
- put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
- patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
- },
- xsrfCookieName: 'XSRF-TOKEN',
- xsrfHeaderName: 'X-XSRF-TOKEN'
- };
-
- var interceptorFactories = this.interceptors = [];
-
- var responseInterceptorFactories = this.responseInterceptors = [];
- this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
- function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
- var defaultCache = $cacheFactory('$http');
-
- var reversedInterceptors = [];
- forEach(interceptorFactories, function(interceptorFactory) {
- reversedInterceptors.unshift(isString(interceptorFactory)
- ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
- });
- forEach(responseInterceptorFactories, function(interceptorFactory, index) {
- var responseFn = isString(interceptorFactory)
- ? $injector.get(interceptorFactory)
- : $injector.invoke(interceptorFactory);
-
- reversedInterceptors.splice(index, 0, {
- response: function(response) {
- return responseFn($q.when(response));
- },
- responseError: function(response) {
- return responseFn($q.reject(response));
- }
- });
- });
-
- function $http(requestConfig) {
- var config = {
- method: 'get',
- transformRequest: defaults.transformRequest,
- transformResponse: defaults.transformResponse
- };
- var headers = mergeHeaders(requestConfig);
- extend(config, requestConfig);
- config.headers = headers;
- config.method = uppercase(config.method);
- var serverRequest = function(config) {
- headers = config.headers;
- var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
-
- if (isUndefined(reqData)) {
- forEach(headers, function(value, header) {
- if (lowercase(header) === 'content-type') {
- delete headers[header];
- }
- });
- }
- if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
- config.withCredentials = defaults.withCredentials;
- }
-
- return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
- };
- var chain = [serverRequest, undefined];
- var promise = $q.when(config);
-
- forEach(reversedInterceptors, function(interceptor) {
- if (interceptor.request || interceptor.requestError) {
- chain.unshift(interceptor.request, interceptor.requestError);
- }
- if (interceptor.response || interceptor.responseError) {
- chain.push(interceptor.response, interceptor.responseError);
- }
- });
- while(chain.length) {
- var thenFn = chain.shift();
- var rejectFn = chain.shift();
- promise = promise.then(thenFn, rejectFn);
- }
- promise.success = function(fn) {
- promise.then(function(response) {
- fn(response.data, response.status, response.headers, config);
- });
- return promise;
- };
- promise.error = function(fn) {
- promise.then(null, function(response) {
- fn(response.data, response.status, response.headers, config);
- });
- return promise;
- };
- return promise;
- function transformResponse(response) {
-
- var resp = extend({}, response, {
- data: transformData(response.data, response.headers, config.transformResponse)
- });
- return (isSuccess(response.status))
- ? resp
- : $q.reject(resp);
- }
- function mergeHeaders(config) {
- var defHeaders = defaults.headers,
- reqHeaders = extend({}, config.headers),
- defHeaderName, lowercaseDefHeaderName, reqHeaderName;
- defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
-
- defaultHeadersIteration:
- for (defHeaderName in defHeaders) {
- lowercaseDefHeaderName = lowercase(defHeaderName);
- for (reqHeaderName in reqHeaders) {
- if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
- continue defaultHeadersIteration;
- }
- }
- reqHeaders[defHeaderName] = defHeaders[defHeaderName];
- }
-
- execHeaders(reqHeaders);
- return reqHeaders;
- function execHeaders(headers) {
- var headerContent;
- forEach(headers, function(headerFn, header) {
- if (isFunction(headerFn)) {
- headerContent = headerFn();
- if (headerContent != null) {
- headers[header] = headerContent;
- } else {
- delete headers[header];
- }
- }
- });
- }
- }
- }
- $http.pendingRequests = [];
-
-
-
-
- createShortMethods('get', 'delete', 'head', 'jsonp');
-
-
- createShortMethodsWithData('post', 'put');
-
- $http.defaults = defaults;
- return $http;
- function createShortMethods(names) {
- forEach(arguments, function(name) {
- $http[name] = function(url, config) {
- return $http(extend(config || {}, {
- method: name,
- url: url
- }));
- };
- });
- }
- function createShortMethodsWithData(name) {
- forEach(arguments, function(name) {
- $http[name] = function(url, data, config) {
- return $http(extend(config || {}, {
- method: name,
- url: url,
- data: data
- }));
- };
- });
- }
-
- function sendReq(config, reqData, reqHeaders) {
- var deferred = $q.defer(),
- promise = deferred.promise,
- cache,
- cachedResp,
- url = buildUrl(config.url, config.params);
- $http.pendingRequests.push(config);
- promise.then(removePendingReq, removePendingReq);
- if ((config.cache || defaults.cache) && config.cache !== false && config.method == 'GET') {
- cache = isObject(config.cache) ? config.cache
- : isObject(defaults.cache) ? defaults.cache
- : defaultCache;
- }
- if (cache) {
- cachedResp = cache.get(url);
- if (isDefined(cachedResp)) {
- if (isPromiseLike(cachedResp)) {
-
- cachedResp.then(removePendingReq, removePendingReq);
- return cachedResp;
- } else {
-
- if (isArray(cachedResp)) {
- resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
- } else {
- resolvePromise(cachedResp, 200, {}, 'OK');
- }
- }
- } else {
-
- cache.put(url, promise);
- }
- }
-
-
- if (isUndefined(cachedResp)) {
- var xsrfValue = urlIsSameOrigin(config.url)
- ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
- : undefined;
- if (xsrfValue) {
- reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
- }
- $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
- config.withCredentials, config.responseType);
- }
- return promise;
-
- function done(status, response, headersString, statusText) {
- if (cache) {
- if (isSuccess(status)) {
- cache.put(url, [status, response, parseHeaders(headersString), statusText]);
- } else {
-
- cache.remove(url);
- }
- }
- resolvePromise(response, status, headersString, statusText);
- if (!$rootScope.$$phase) $rootScope.$apply();
- }
-
- function resolvePromise(response, status, headers, statusText) {
-
- status = Math.max(status, 0);
- (isSuccess(status) ? deferred.resolve : deferred.reject)({
- data: response,
- status: status,
- headers: headersGetter(headers),
- config: config,
- statusText : statusText
- });
- }
- function removePendingReq() {
- var idx = indexOf($http.pendingRequests, config);
- if (idx !== -1) $http.pendingRequests.splice(idx, 1);
- }
- }
- function buildUrl(url, params) {
- if (!params) return url;
- var parts = [];
- forEachSorted(params, function(value, key) {
- if (value === null || isUndefined(value)) return;
- if (!isArray(value)) value = [value];
- forEach(value, function(v) {
- if (isObject(v)) {
- if (isDate(v)){
- v = v.toISOString();
- } else if (isObject(v)) {
- v = toJson(v);
- }
- }
- parts.push(encodeUriQuery(key) + '=' +
- encodeUriQuery(v));
- });
- });
- if(parts.length > 0) {
- url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
- }
- return url;
- }
- }];
- }
- function createXhr(method) {
-
-
-
- if (msie <= 8 && (!method.match(/^(get|post|head|put|delete|options)$/i) ||
- !window.XMLHttpRequest)) {
- return new window.ActiveXObject("Microsoft.XMLHTTP");
- } else if (window.XMLHttpRequest) {
- return new window.XMLHttpRequest();
- }
- throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest.");
- }
- function $HttpBackendProvider() {
- this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
- return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);
- }];
- }
- function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
- var ABORTED = -1;
-
- return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
- var status;
- $browser.$$incOutstandingRequestCount();
- url = url || $browser.url();
- if (lowercase(method) == 'jsonp') {
- var callbackId = '_' + (callbacks.counter++).toString(36);
- callbacks[callbackId] = function(data) {
- callbacks[callbackId].data = data;
- callbacks[callbackId].called = true;
- };
- var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
- callbackId, function(status, text) {
- completeRequest(callback, status, callbacks[callbackId].data, "", text);
- callbacks[callbackId] = noop;
- });
- } else {
- var xhr = createXhr(method);
- xhr.open(method, url, true);
- forEach(headers, function(value, key) {
- if (isDefined(value)) {
- xhr.setRequestHeader(key, value);
- }
- });
-
-
-
- xhr.onreadystatechange = function() {
-
-
-
-
-
-
-
- if (xhr && xhr.readyState == 4) {
- var responseHeaders = null,
- response = null,
- statusText = '';
- if(status !== ABORTED) {
- responseHeaders = xhr.getAllResponseHeaders();
-
-
- response = ('response' in xhr) ? xhr.response : xhr.responseText;
- }
-
-
- if (!(status === ABORTED && msie < 10)) {
- statusText = xhr.statusText;
- }
- completeRequest(callback,
- status || xhr.status,
- response,
- responseHeaders,
- statusText);
- }
- };
- if (withCredentials) {
- xhr.withCredentials = true;
- }
- if (responseType) {
- try {
- xhr.responseType = responseType;
- } catch (e) {
-
-
-
-
-
-
-
- if (responseType !== 'json') {
- throw e;
- }
- }
- }
- xhr.send(post || null);
- }
- if (timeout > 0) {
- var timeoutId = $browserDefer(timeoutRequest, timeout);
- } else if (isPromiseLike(timeout)) {
- timeout.then(timeoutRequest);
- }
- function timeoutRequest() {
- status = ABORTED;
- jsonpDone && jsonpDone();
- xhr && xhr.abort();
- }
- function completeRequest(callback, status, response, headersString, statusText) {
-
- timeoutId && $browserDefer.cancel(timeoutId);
- jsonpDone = xhr = null;
-
-
-
- if (status === 0) {
- status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
- }
-
- status = status === 1223 ? 204 : status;
- statusText = statusText || '';
- callback(status, response, headersString, statusText);
- $browser.$$completeOutstandingRequest(noop);
- }
- };
- function jsonpReq(url, callbackId, done) {
-
-
-
- var script = rawDocument.createElement('script'), callback = null;
- script.type = "text/javascript";
- script.src = url;
- script.async = true;
- callback = function(event) {
- removeEventListenerFn(script, "load", callback);
- removeEventListenerFn(script, "error", callback);
- rawDocument.body.removeChild(script);
- script = null;
- var status = -1;
- var text = "unknown";
- if (event) {
- if (event.type === "load" && !callbacks[callbackId].called) {
- event = { type: "error" };
- }
- text = event.type;
- status = event.type === "error" ? 404 : 200;
- }
- if (done) {
- done(status, text);
- }
- };
- addEventListenerFn(script, "load", callback);
- addEventListenerFn(script, "error", callback);
- if (msie <= 8) {
- script.onreadystatechange = function() {
- if (isString(script.readyState) && /loaded|complete/.test(script.readyState)) {
- script.onreadystatechange = null;
- callback({
- type: 'load'
- });
- }
- };
- }
- rawDocument.body.appendChild(script);
- return callback;
- }
- }
- var $interpolateMinErr = minErr('$interpolate');
- function $InterpolateProvider() {
- var startSymbol = '{{';
- var endSymbol = '}}';
-
- this.startSymbol = function(value){
- if (value) {
- startSymbol = value;
- return this;
- } else {
- return startSymbol;
- }
- };
-
- this.endSymbol = function(value){
- if (value) {
- endSymbol = value;
- return this;
- } else {
- return endSymbol;
- }
- };
- this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
- var startSymbolLength = startSymbol.length,
- endSymbolLength = endSymbol.length;
-
- function $interpolate(text, mustHaveExpression, trustedContext) {
- var startIndex,
- endIndex,
- index = 0,
- parts = [],
- length = text.length,
- hasInterpolation = false,
- fn,
- exp,
- concat = [];
- while(index < length) {
- if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
- ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
- (index != startIndex) && parts.push(text.substring(index, startIndex));
- parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));
- fn.exp = exp;
- index = endIndex + endSymbolLength;
- hasInterpolation = true;
- } else {
-
- (index != length) && parts.push(text.substring(index));
- index = length;
- }
- }
- if (!(length = parts.length)) {
-
- parts.push('');
- length = 1;
- }
-
-
-
-
-
-
- if (trustedContext && parts.length > 1) {
- throw $interpolateMinErr('noconcat',
- "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
- "interpolations that concatenate multiple expressions when a trusted value is " +
- "required. See http://docs.angularjs.org/api/ng.$sce", text);
- }
- if (!mustHaveExpression || hasInterpolation) {
- concat.length = length;
- fn = function(context) {
- try {
- for(var i = 0, ii = length, part; i<ii; i++) {
- if (typeof (part = parts[i]) == 'function') {
- part = part(context);
- if (trustedContext) {
- part = $sce.getTrusted(trustedContext, part);
- } else {
- part = $sce.valueOf(part);
- }
- if (part == null) {
- part = '';
- } else {
- switch (typeof part) {
- case 'string':
- {
- break;
- }
- case 'number':
- {
- part = '' + part;
- break;
- }
- default:
- {
- part = toJson(part);
- }
- }
- }
- }
- concat[i] = part;
- }
- return concat.join('');
- }
- catch(err) {
- var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
- err.toString());
- $exceptionHandler(newErr);
- }
- };
- fn.exp = text;
- fn.parts = parts;
- return fn;
- }
- }
-
- $interpolate.startSymbol = function() {
- return startSymbol;
- };
-
- $interpolate.endSymbol = function() {
- return endSymbol;
- };
- return $interpolate;
- }];
- }
- function $IntervalProvider() {
- this.$get = ['$rootScope', '$window', '$q',
- function($rootScope, $window, $q) {
- var intervals = {};
-
- function interval(fn, delay, count, invokeApply) {
- var setInterval = $window.setInterval,
- clearInterval = $window.clearInterval,
- deferred = $q.defer(),
- promise = deferred.promise,
- iteration = 0,
- skipApply = (isDefined(invokeApply) && !invokeApply);
- count = isDefined(count) ? count : 0;
- promise.then(null, null, fn);
- promise.$$intervalId = setInterval(function tick() {
- deferred.notify(iteration++);
- if (count > 0 && iteration >= count) {
- deferred.resolve(iteration);
- clearInterval(promise.$$intervalId);
- delete intervals[promise.$$intervalId];
- }
- if (!skipApply) $rootScope.$apply();
- }, delay);
- intervals[promise.$$intervalId] = deferred;
- return promise;
- }
-
- interval.cancel = function(promise) {
- if (promise && promise.$$intervalId in intervals) {
- intervals[promise.$$intervalId].reject('canceled');
- $window.clearInterval(promise.$$intervalId);
- delete intervals[promise.$$intervalId];
- return true;
- }
- return false;
- };
- return interval;
- }];
- }
- function $LocaleProvider(){
- this.$get = function() {
- return {
- id: 'en-us',
- NUMBER_FORMATS: {
- DECIMAL_SEP: '.',
- GROUP_SEP: ',',
- PATTERNS: [
- {
- minInt: 1,
- minFrac: 0,
- maxFrac: 3,
- posPre: '',
- posSuf: '',
- negPre: '-',
- negSuf: '',
- gSize: 3,
- lgSize: 3
- },{
- minInt: 1,
- minFrac: 2,
- maxFrac: 2,
- posPre: '\u00A4',
- posSuf: '',
- negPre: '(\u00A4',
- negSuf: ')',
- gSize: 3,
- lgSize: 3
- }
- ],
- CURRENCY_SYM: '$'
- },
- DATETIME_FORMATS: {
- MONTH:
- 'January,February,March,April,May,June,July,August,September,October,November,December'
- .split(','),
- SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
- DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
- SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
- AMPMS: ['AM','PM'],
- medium: 'MMM d, y h:mm:ss a',
- short: 'M/d/yy h:mm a',
- fullDate: 'EEEE, MMMM d, y',
- longDate: 'MMMM d, y',
- mediumDate: 'MMM d, y',
- shortDate: 'M/d/yy',
- mediumTime: 'h:mm:ss a',
- shortTime: 'h:mm a'
- },
- pluralCat: function(num) {
- if (num === 1) {
- return 'one';
- }
- return 'other';
- }
- };
- };
- }
- var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
- DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
- var $locationMinErr = minErr('$location');
- function encodePath(path) {
- var segments = path.split('/'),
- i = segments.length;
- while (i--) {
- segments[i] = encodeUriSegment(segments[i]);
- }
- return segments.join('/');
- }
- function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
- var parsedUrl = urlResolve(absoluteUrl, appBase);
- locationObj.$$protocol = parsedUrl.protocol;
- locationObj.$$host = parsedUrl.hostname;
- locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
- }
- function parseAppUrl(relativeUrl, locationObj, appBase) {
- var prefixed = (relativeUrl.charAt(0) !== '/');
- if (prefixed) {
- relativeUrl = '/' + relativeUrl;
- }
- var match = urlResolve(relativeUrl, appBase);
- locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
- match.pathname.substring(1) : match.pathname);
- locationObj.$$search = parseKeyValue(match.search);
- locationObj.$$hash = decodeURIComponent(match.hash);
-
- if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
- locationObj.$$path = '/' + locationObj.$$path;
- }
- }
- function beginsWith(begin, whole) {
- if (whole.indexOf(begin) === 0) {
- return whole.substr(begin.length);
- }
- }
- function stripHash(url) {
- var index = url.indexOf('#');
- return index == -1 ? url : url.substr(0, index);
- }
- function stripFile(url) {
- return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
- }
- function serverBase(url) {
- return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
- }
- function LocationHtml5Url(appBase, basePrefix) {
- this.$$html5 = true;
- basePrefix = basePrefix || '';
- var appBaseNoFile = stripFile(appBase);
- parseAbsoluteUrl(appBase, this, appBase);
-
- this.$$parse = function(url) {
- var pathUrl = beginsWith(appBaseNoFile, url);
- if (!isString(pathUrl)) {
- throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
- appBaseNoFile);
- }
- parseAppUrl(pathUrl, this, appBase);
- if (!this.$$path) {
- this.$$path = '/';
- }
- this.$$compose();
- };
-
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- this.$$absUrl = appBaseNoFile + this.$$url.substr(1);
- };
- this.$$rewrite = function(url) {
- var appUrl, prevAppUrl;
- if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {
- prevAppUrl = appUrl;
- if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {
- return appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
- } else {
- return appBase + prevAppUrl;
- }
- } else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) {
- return appBaseNoFile + appUrl;
- } else if (appBaseNoFile == url + '/') {
- return appBaseNoFile;
- }
- };
- }
- function LocationHashbangUrl(appBase, hashPrefix) {
- var appBaseNoFile = stripFile(appBase);
- parseAbsoluteUrl(appBase, this, appBase);
-
- this.$$parse = function(url) {
- var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
- var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
- ? beginsWith(hashPrefix, withoutBaseUrl)
- : (this.$$html5)
- ? withoutBaseUrl
- : '';
- if (!isString(withoutHashUrl)) {
- throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
- hashPrefix);
- }
- parseAppUrl(withoutHashUrl, this, appBase);
- this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
- this.$$compose();
-
- function removeWindowsDriveName (path, url, base) {
-
- var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
- var firstPathSegmentMatch;
-
- if (url.indexOf(base) === 0) {
- url = url.replace(base, '');
- }
-
- if (windowsFilePathExp.exec(url)) {
- return path;
- }
- firstPathSegmentMatch = windowsFilePathExp.exec(path);
- return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
- }
- };
-
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
- this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
- };
- this.$$rewrite = function(url) {
- if(stripHash(appBase) == stripHash(url)) {
- return url;
- }
- };
- }
- function LocationHashbangInHtml5Url(appBase, hashPrefix) {
- this.$$html5 = true;
- LocationHashbangUrl.apply(this, arguments);
- var appBaseNoFile = stripFile(appBase);
- this.$$rewrite = function(url) {
- var appUrl;
- if ( appBase == stripHash(url) ) {
- return url;
- } else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
- return appBase + hashPrefix + appUrl;
- } else if ( appBaseNoFile === url + '/') {
- return appBaseNoFile;
- }
- };
- this.$$compose = function() {
- var search = toKeyValue(this.$$search),
- hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
- this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
-
- this.$$absUrl = appBase + hashPrefix + this.$$url;
- };
- }
- LocationHashbangInHtml5Url.prototype =
- LocationHashbangUrl.prototype =
- LocationHtml5Url.prototype = {
-
- $$html5: false,
-
- $$replace: false,
-
- absUrl: locationGetter('$$absUrl'),
-
- url: function(url, replace) {
- if (isUndefined(url))
- return this.$$url;
- var match = PATH_MATCH.exec(url);
- if (match[1]) this.path(decodeURIComponent(match[1]));
- if (match[2] || match[1]) this.search(match[3] || '');
- this.hash(match[5] || '', replace);
- return this;
- },
-
- protocol: locationGetter('$$protocol'),
-
- host: locationGetter('$$host'),
-
- port: locationGetter('$$port'),
-
- path: locationGetterSetter('$$path', function(path) {
- return path.charAt(0) == '/' ? path : '/' + path;
- }),
-
- search: function(search, paramValue) {
- switch (arguments.length) {
- case 0:
- return this.$$search;
- case 1:
- if (isString(search)) {
- this.$$search = parseKeyValue(search);
- } else if (isObject(search)) {
-
- forEach(search, function(value, key) {
- if (value == null) delete search[key];
- });
- this.$$search = search;
- } else {
- throw $locationMinErr('isrcharg',
- 'The first argument of the `$location#search()` call must be a string or an object.');
- }
- break;
- default:
- if (isUndefined(paramValue) || paramValue === null) {
- delete this.$$search[search];
- } else {
- this.$$search[search] = paramValue;
- }
- }
- this.$$compose();
- return this;
- },
-
- hash: locationGetterSetter('$$hash', identity),
-
- replace: function() {
- this.$$replace = true;
- return this;
- }
- };
- function locationGetter(property) {
- return function() {
- return this[property];
- };
- }
- function locationGetterSetter(property, preprocess) {
- return function(value) {
- if (isUndefined(value))
- return this[property];
- this[property] = preprocess(value);
- this.$$compose();
- return this;
- };
- }
- function $LocationProvider(){
- var hashPrefix = '',
- html5Mode = false;
-
- this.hashPrefix = function(prefix) {
- if (isDefined(prefix)) {
- hashPrefix = prefix;
- return this;
- } else {
- return hashPrefix;
- }
- };
-
- this.html5Mode = function(mode) {
- if (isDefined(mode)) {
- html5Mode = mode;
- return this;
- } else {
- return html5Mode;
- }
- };
-
-
- this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
- function( $rootScope, $browser, $sniffer, $rootElement) {
- var $location,
- LocationMode,
- baseHref = $browser.baseHref(),
- initialUrl = $browser.url(),
- appBase;
- if (html5Mode) {
- appBase = serverBase(initialUrl) + (baseHref || '/');
- LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
- } else {
- appBase = stripHash(initialUrl);
- LocationMode = LocationHashbangUrl;
- }
- $location = new LocationMode(appBase, '#' + hashPrefix);
- $location.$$parse($location.$$rewrite(initialUrl));
- $rootElement.on('click', function(event) {
-
-
- if (event.ctrlKey || event.metaKey || event.which == 2) return;
- var elm = jqLite(event.target);
-
- while (lowercase(elm[0].nodeName) !== 'a') {
-
- if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
- }
- var absHref = elm.prop('href');
- if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
-
-
- absHref = urlResolve(absHref.animVal).href;
- }
-
-
-
- if (LocationMode === LocationHashbangInHtml5Url) {
-
-
- var href = elm.attr('href') || elm.attr('xlink:href');
- if (href.indexOf('://') < 0) {
- var prefix = '#' + hashPrefix;
- if (href[0] == '/') {
-
- absHref = appBase + prefix + href;
- } else if (href[0] == '#') {
-
- absHref = appBase + prefix + ($location.path() || '/') + href;
- } else {
-
- var stack = $location.path().split("/"),
- parts = href.split("/");
- for (var i=0; i<parts.length; i++) {
- if (parts[i] == ".")
- continue;
- else if (parts[i] == "..")
- stack.pop();
- else if (parts[i].length)
- stack.push(parts[i]);
- }
- absHref = appBase + prefix + stack.join('/');
- }
- }
- }
- var rewrittenUrl = $location.$$rewrite(absHref);
- if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
- event.preventDefault();
- if (rewrittenUrl != $browser.url()) {
-
- $location.$$parse(rewrittenUrl);
- $rootScope.$apply();
-
- window.angular['ff-684208-preventDefault'] = true;
- }
- }
- });
-
- if ($location.absUrl() != initialUrl) {
- $browser.url($location.absUrl(), true);
- }
-
- $browser.onUrlChange(function(newUrl) {
- if ($location.absUrl() != newUrl) {
- $rootScope.$evalAsync(function() {
- var oldUrl = $location.absUrl();
- $location.$$parse(newUrl);
- if ($rootScope.$broadcast('$locationChangeStart', newUrl,
- oldUrl).defaultPrevented) {
- $location.$$parse(oldUrl);
- $browser.url(oldUrl);
- } else {
- afterLocationChange(oldUrl);
- }
- });
- if (!$rootScope.$$phase) $rootScope.$digest();
- }
- });
-
- var changeCounter = 0;
- $rootScope.$watch(function $locationWatch() {
- var oldUrl = $browser.url();
- var currentReplace = $location.$$replace;
- if (!changeCounter || oldUrl != $location.absUrl()) {
- changeCounter++;
- $rootScope.$evalAsync(function() {
- if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
- defaultPrevented) {
- $location.$$parse(oldUrl);
- } else {
- $browser.url($location.absUrl(), currentReplace);
- afterLocationChange(oldUrl);
- }
- });
- }
- $location.$$replace = false;
- return changeCounter;
- });
- return $location;
- function afterLocationChange(oldUrl) {
- $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);
- }
- }];
- }
- function $LogProvider(){
- var debug = true,
- self = this;
-
- this.debugEnabled = function(flag) {
- if (isDefined(flag)) {
- debug = flag;
- return this;
- } else {
- return debug;
- }
- };
- this.$get = ['$window', function($window){
- return {
-
- log: consoleLog('log'),
-
- info: consoleLog('info'),
-
- warn: consoleLog('warn'),
-
- error: consoleLog('error'),
-
- debug: (function () {
- var fn = consoleLog('debug');
- return function() {
- if (debug) {
- fn.apply(self, arguments);
- }
- };
- }())
- };
- function formatError(arg) {
- if (arg instanceof Error) {
- if (arg.stack) {
- arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
- ? 'Error: ' + arg.message + '\n' + arg.stack
- : arg.stack;
- } else if (arg.sourceURL) {
- arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
- }
- }
- return arg;
- }
- function consoleLog(type) {
- var console = $window.console || {},
- logFn = console[type] || console.log || noop,
- hasApply = false;
-
-
- try {
- hasApply = !!logFn.apply;
- } catch (e) {}
- if (hasApply) {
- return function() {
- var args = [];
- forEach(arguments, function(arg) {
- args.push(formatError(arg));
- });
- return logFn.apply(console, args);
- };
- }
-
-
- return function(arg1, arg2) {
- logFn(arg1, arg2 == null ? '' : arg2);
- };
- }
- }];
- }
- var $parseMinErr = minErr('$parse');
- var promiseWarningCache = {};
- var promiseWarning;
- function ensureSafeMemberName(name, fullExpression) {
- if (name === "__defineGetter__" || name === "__defineSetter__"
- || name === "__lookupGetter__" || name === "__lookupSetter__"
- || name === "__proto__") {
- throw $parseMinErr('isecfld',
- 'Attempting to access a disallowed field in Angular expressions! '
- +'Expression: {0}', fullExpression);
- }
- return name;
- }
- function ensureSafeObject(obj, fullExpression) {
-
- if (obj) {
- if (obj.constructor === obj) {
- throw $parseMinErr('isecfn',
- 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (
- obj.document && obj.location && obj.alert && obj.setInterval) {
- throw $parseMinErr('isecwindow',
- 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (
- obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
- throw $parseMinErr('isecdom',
- 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (
- obj === Object) {
- throw $parseMinErr('isecobj',
- 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- }
- }
- return obj;
- }
- var CALL = Function.prototype.call;
- var APPLY = Function.prototype.apply;
- var BIND = Function.prototype.bind;
- function ensureSafeFunction(obj, fullExpression) {
- if (obj) {
- if (obj.constructor === obj) {
- throw $parseMinErr('isecfn',
- 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- } else if (obj === CALL || obj === APPLY || (BIND && obj === BIND)) {
- throw $parseMinErr('isecff',
- 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
- fullExpression);
- }
- }
- }
- var OPERATORS = {
-
- 'null':function(){return null;},
- 'true':function(){return true;},
- 'false':function(){return false;},
- undefined:noop,
- '+':function(self, locals, a,b){
- a=a(self, locals); b=b(self, locals);
- if (isDefined(a)) {
- if (isDefined(b)) {
- return a + b;
- }
- return a;
- }
- return isDefined(b)?b:undefined;},
- '-':function(self, locals, a,b){
- a=a(self, locals); b=b(self, locals);
- return (isDefined(a)?a:0)-(isDefined(b)?b:0);
- },
- '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
- '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
- '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
- '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
- '=':noop,
- '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},
- '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},
- '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
- '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
- '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},
- '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},
- '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},
- '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},
- '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},
- '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},
- '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},
- '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},
- '!':function(self, locals, a){return !a(self, locals);}
- };
- var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
- var Lexer = function (options) {
- this.options = options;
- };
- Lexer.prototype = {
- constructor: Lexer,
- lex: function (text) {
- this.text = text;
- this.index = 0;
- this.ch = undefined;
- this.lastCh = ':';
- this.tokens = [];
- while (this.index < this.text.length) {
- this.ch = this.text.charAt(this.index);
- if (this.is('"\'')) {
- this.readString(this.ch);
- } else if (this.isNumber(this.ch) || this.is('.') && this.isNumber(this.peek())) {
- this.readNumber();
- } else if (this.isIdent(this.ch)) {
- this.readIdent();
- } else if (this.is('(){}[].,;:?')) {
- this.tokens.push({
- index: this.index,
- text: this.ch
- });
- this.index++;
- } else if (this.isWhitespace(this.ch)) {
- this.index++;
- continue;
- } else {
- var ch2 = this.ch + this.peek();
- var ch3 = ch2 + this.peek(2);
- var fn = OPERATORS[this.ch];
- var fn2 = OPERATORS[ch2];
- var fn3 = OPERATORS[ch3];
- if (fn3) {
- this.tokens.push({index: this.index, text: ch3, fn: fn3});
- this.index += 3;
- } else if (fn2) {
- this.tokens.push({index: this.index, text: ch2, fn: fn2});
- this.index += 2;
- } else if (fn) {
- this.tokens.push({
- index: this.index,
- text: this.ch,
- fn: fn
- });
- this.index += 1;
- } else {
- this.throwError('Unexpected next character ', this.index, this.index + 1);
- }
- }
- this.lastCh = this.ch;
- }
- return this.tokens;
- },
- is: function(chars) {
- return chars.indexOf(this.ch) !== -1;
- },
- was: function(chars) {
- return chars.indexOf(this.lastCh) !== -1;
- },
- peek: function(i) {
- var num = i || 1;
- return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
- },
- isNumber: function(ch) {
- return ('0' <= ch && ch <= '9');
- },
- isWhitespace: function(ch) {
-
- return (ch === ' ' || ch === '\r' || ch === '\t' ||
- ch === '\n' || ch === '\v' || ch === '\u00A0');
- },
- isIdent: function(ch) {
- return ('a' <= ch && ch <= 'z' ||
- 'A' <= ch && ch <= 'Z' ||
- '_' === ch || ch === '$');
- },
- isExpOperator: function(ch) {
- return (ch === '-' || ch === '+' || this.isNumber(ch));
- },
- throwError: function(error, start, end) {
- end = end || this.index;
- var colStr = (isDefined(start)
- ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'
- : ' ' + end);
- throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
- error, colStr, this.text);
- },
- readNumber: function() {
- var number = '';
- var start = this.index;
- while (this.index < this.text.length) {
- var ch = lowercase(this.text.charAt(this.index));
- if (ch == '.' || this.isNumber(ch)) {
- number += ch;
- } else {
- var peekCh = this.peek();
- if (ch == 'e' && this.isExpOperator(peekCh)) {
- number += ch;
- } else if (this.isExpOperator(ch) &&
- peekCh && this.isNumber(peekCh) &&
- number.charAt(number.length - 1) == 'e') {
- number += ch;
- } else if (this.isExpOperator(ch) &&
- (!peekCh || !this.isNumber(peekCh)) &&
- number.charAt(number.length - 1) == 'e') {
- this.throwError('Invalid exponent');
- } else {
- break;
- }
- }
- this.index++;
- }
- number = 1 * number;
- this.tokens.push({
- index: start,
- text: number,
- literal: true,
- constant: true,
- fn: function() { return number; }
- });
- },
- readIdent: function() {
- var parser = this;
- var ident = '';
- var start = this.index;
- var lastDot, peekIndex, methodName, ch;
- while (this.index < this.text.length) {
- ch = this.text.charAt(this.index);
- if (ch === '.' || this.isIdent(ch) || this.isNumber(ch)) {
- if (ch === '.') lastDot = this.index;
- ident += ch;
- } else {
- break;
- }
- this.index++;
- }
-
- if (lastDot) {
- peekIndex = this.index;
- while (peekIndex < this.text.length) {
- ch = this.text.charAt(peekIndex);
- if (ch === '(') {
- methodName = ident.substr(lastDot - start + 1);
- ident = ident.substr(0, lastDot - start);
- this.index = peekIndex;
- break;
- }
- if (this.isWhitespace(ch)) {
- peekIndex++;
- } else {
- break;
- }
- }
- }
- var token = {
- index: start,
- text: ident
- };
-
- if (OPERATORS.hasOwnProperty(ident)) {
- token.fn = OPERATORS[ident];
- token.literal = true;
- token.constant = true;
- } else {
- var getter = getterFn(ident, this.options, this.text);
- token.fn = extend(function(self, locals) {
- return (getter(self, locals));
- }, {
- assign: function(self, value) {
- return setter(self, ident, value, parser.text, parser.options);
- }
- });
- }
- this.tokens.push(token);
- if (methodName) {
- this.tokens.push({
- index:lastDot,
- text: '.'
- });
- this.tokens.push({
- index: lastDot + 1,
- text: methodName
- });
- }
- },
- readString: function(quote) {
- var start = this.index;
- this.index++;
- var string = '';
- var rawString = quote;
- var escape = false;
- while (this.index < this.text.length) {
- var ch = this.text.charAt(this.index);
- rawString += ch;
- if (escape) {
- if (ch === 'u') {
- var hex = this.text.substring(this.index + 1, this.index + 5);
- if (!hex.match(/[\da-f]{4}/i))
- this.throwError('Invalid unicode escape [\\u' + hex + ']');
- this.index += 4;
- string += String.fromCharCode(parseInt(hex, 16));
- } else {
- var rep = ESCAPE[ch];
- string = string + (rep || ch);
- }
- escape = false;
- } else if (ch === '\\') {
- escape = true;
- } else if (ch === quote) {
- this.index++;
- this.tokens.push({
- index: start,
- text: rawString,
- string: string,
- literal: true,
- constant: true,
- fn: function() { return string; }
- });
- return;
- } else {
- string += ch;
- }
- this.index++;
- }
- this.throwError('Unterminated quote', start);
- }
- };
- var Parser = function (lexer, $filter, options) {
- this.lexer = lexer;
- this.$filter = $filter;
- this.options = options;
- };
- Parser.ZERO = extend(function () {
- return 0;
- }, {
- constant: true
- });
- Parser.prototype = {
- constructor: Parser,
- parse: function (text) {
- this.text = text;
- this.tokens = this.lexer.lex(text);
- var value = this.statements();
- if (this.tokens.length !== 0) {
- this.throwError('is an unexpected token', this.tokens[0]);
- }
- value.literal = !!value.literal;
- value.constant = !!value.constant;
- return value;
- },
- primary: function () {
- var primary;
- if (this.expect('(')) {
- primary = this.filterChain();
- this.consume(')');
- } else if (this.expect('[')) {
- primary = this.arrayDeclaration();
- } else if (this.expect('{')) {
- primary = this.object();
- } else {
- var token = this.expect();
- primary = token.fn;
- if (!primary) {
- this.throwError('not a primary expression', token);
- }
- primary.literal = !!token.literal;
- primary.constant = !!token.constant;
- }
- var next, context;
- while ((next = this.expect('(', '[', '.'))) {
- if (next.text === '(') {
- primary = this.functionCall(primary, context);
- context = null;
- } else if (next.text === '[') {
- context = primary;
- primary = this.objectIndex(primary);
- } else if (next.text === '.') {
- context = primary;
- primary = this.fieldAccess(primary);
- } else {
- this.throwError('IMPOSSIBLE');
- }
- }
- return primary;
- },
- throwError: function(msg, token) {
- throw $parseMinErr('syntax',
- 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
- token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
- },
- peekToken: function() {
- if (this.tokens.length === 0)
- throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
- return this.tokens[0];
- },
- peek: function(e1, e2, e3, e4) {
- if (this.tokens.length > 0) {
- var token = this.tokens[0];
- var t = token.text;
- if (t === e1 || t === e2 || t === e3 || t === e4 ||
- (!e1 && !e2 && !e3 && !e4)) {
- return token;
- }
- }
- return false;
- },
- expect: function(e1, e2, e3, e4){
- var token = this.peek(e1, e2, e3, e4);
- if (token) {
- this.tokens.shift();
- return token;
- }
- return false;
- },
- consume: function(e1){
- if (!this.expect(e1)) {
- this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
- }
- },
- unaryFn: function(fn, right) {
- return extend(function(self, locals) {
- return fn(self, locals, right);
- }, {
- constant:right.constant
- });
- },
- ternaryFn: function(left, middle, right){
- return extend(function(self, locals){
- return left(self, locals) ? middle(self, locals) : right(self, locals);
- }, {
- constant: left.constant && middle.constant && right.constant
- });
- },
- binaryFn: function(left, fn, right) {
- return extend(function(self, locals) {
- return fn(self, locals, left, right);
- }, {
- constant:left.constant && right.constant
- });
- },
- statements: function() {
- var statements = [];
- while (true) {
- if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
- statements.push(this.filterChain());
- if (!this.expect(';')) {
-
-
- return (statements.length === 1)
- ? statements[0]
- : function(self, locals) {
- var value;
- for (var i = 0; i < statements.length; i++) {
- var statement = statements[i];
- if (statement) {
- value = statement(self, locals);
- }
- }
- return value;
- };
- }
- }
- },
- filterChain: function() {
- var left = this.expression();
- var token;
- while (true) {
- if ((token = this.expect('|'))) {
- left = this.binaryFn(left, token.fn, this.filter());
- } else {
- return left;
- }
- }
- },
- filter: function() {
- var token = this.expect();
- var fn = this.$filter(token.text);
- var argsFn = [];
- while (true) {
- if ((token = this.expect(':'))) {
- argsFn.push(this.expression());
- } else {
- var fnInvoke = function(self, locals, input) {
- var args = [input];
- for (var i = 0; i < argsFn.length; i++) {
- args.push(argsFn[i](self, locals));
- }
- return fn.apply(self, args);
- };
- return function() {
- return fnInvoke;
- };
- }
- }
- },
- expression: function() {
- return this.assignment();
- },
- assignment: function() {
- var left = this.ternary();
- var right;
- var token;
- if ((token = this.expect('='))) {
- if (!left.assign) {
- this.throwError('implies assignment but [' +
- this.text.substring(0, token.index) + '] can not be assigned to', token);
- }
- right = this.ternary();
- return function(scope, locals) {
- return left.assign(scope, right(scope, locals), locals);
- };
- }
- return left;
- },
- ternary: function() {
- var left = this.logicalOR();
- var middle;
- var token;
- if ((token = this.expect('?'))) {
- middle = this.ternary();
- if ((token = this.expect(':'))) {
- return this.ternaryFn(left, middle, this.ternary());
- } else {
- this.throwError('expected :', token);
- }
- } else {
- return left;
- }
- },
- logicalOR: function() {
- var left = this.logicalAND();
- var token;
- while (true) {
- if ((token = this.expect('||'))) {
- left = this.binaryFn(left, token.fn, this.logicalAND());
- } else {
- return left;
- }
- }
- },
- logicalAND: function() {
- var left = this.equality();
- var token;
- if ((token = this.expect('&&'))) {
- left = this.binaryFn(left, token.fn, this.logicalAND());
- }
- return left;
- },
- equality: function() {
- var left = this.relational();
- var token;
- if ((token = this.expect('==','!=','===','!=='))) {
- left = this.binaryFn(left, token.fn, this.equality());
- }
- return left;
- },
- relational: function() {
- var left = this.additive();
- var token;
- if ((token = this.expect('<', '>', '<=', '>='))) {
- left = this.binaryFn(left, token.fn, this.relational());
- }
- return left;
- },
- additive: function() {
- var left = this.multiplicative();
- var token;
- while ((token = this.expect('+','-'))) {
- left = this.binaryFn(left, token.fn, this.multiplicative());
- }
- return left;
- },
- multiplicative: function() {
- var left = this.unary();
- var token;
- while ((token = this.expect('*','/','%'))) {
- left = this.binaryFn(left, token.fn, this.unary());
- }
- return left;
- },
- unary: function() {
- var token;
- if (this.expect('+')) {
- return this.primary();
- } else if ((token = this.expect('-'))) {
- return this.binaryFn(Parser.ZERO, token.fn, this.unary());
- } else if ((token = this.expect('!'))) {
- return this.unaryFn(token.fn, this.unary());
- } else {
- return this.primary();
- }
- },
- fieldAccess: function(object) {
- var parser = this;
- var field = this.expect().text;
- var getter = getterFn(field, this.options, this.text);
- return extend(function(scope, locals, self) {
- return getter(self || object(scope, locals));
- }, {
- assign: function(scope, value, locals) {
- return setter(object(scope, locals), field, value, parser.text, parser.options);
- }
- });
- },
- objectIndex: function(obj) {
- var parser = this;
- var indexFn = this.expression();
- this.consume(']');
- return extend(function(self, locals) {
- var o = obj(self, locals),
- i = indexFn(self, locals),
- v, p;
- ensureSafeMemberName(i, parser.text);
- if (!o) return undefined;
- v = ensureSafeObject(o[i], parser.text);
- if (v && v.then && parser.options.unwrapPromises) {
- p = v;
- if (!('$$v' in v)) {
- p.$$v = undefined;
- p.then(function(val) { p.$$v = val; });
- }
- v = v.$$v;
- }
- return v;
- }, {
- assign: function(self, value, locals) {
- var key = indexFn(self, locals);
-
- var safe = ensureSafeObject(obj(self, locals), parser.text);
- return safe[key] = value;
- }
- });
- },
- functionCall: function(fn, contextGetter) {
- var argsFn = [];
- if (this.peekToken().text !== ')') {
- do {
- argsFn.push(this.expression());
- } while (this.expect(','));
- }
- this.consume(')');
- var parser = this;
- return function(scope, locals) {
- var args = [];
- var context = contextGetter ? contextGetter(scope, locals) : scope;
- for (var i = 0; i < argsFn.length; i++) {
- args.push(argsFn[i](scope, locals));
- }
- var fnPtr = fn(scope, locals, context) || noop;
- ensureSafeObject(context, parser.text);
- ensureSafeFunction(fnPtr, parser.text);
-
- var v = fnPtr.apply
- ? fnPtr.apply(context, args)
- : fnPtr(args[0], args[1], args[2], args[3], args[4]);
- return ensureSafeObject(v, parser.text);
- };
- },
-
- arrayDeclaration: function () {
- var elementFns = [];
- var allConstant = true;
- if (this.peekToken().text !== ']') {
- do {
- if (this.peek(']')) {
-
- break;
- }
- var elementFn = this.expression();
- elementFns.push(elementFn);
- if (!elementFn.constant) {
- allConstant = false;
- }
- } while (this.expect(','));
- }
- this.consume(']');
- return extend(function(self, locals) {
- var array = [];
- for (var i = 0; i < elementFns.length; i++) {
- array.push(elementFns[i](self, locals));
- }
- return array;
- }, {
- literal: true,
- constant: allConstant
- });
- },
- object: function () {
- var keyValues = [];
- var allConstant = true;
- if (this.peekToken().text !== '}') {
- do {
- if (this.peek('}')) {
-
- break;
- }
- var token = this.expect(),
- key = token.string || token.text;
- this.consume(':');
- var value = this.expression();
- keyValues.push({key: key, value: value});
- if (!value.constant) {
- allConstant = false;
- }
- } while (this.expect(','));
- }
- this.consume('}');
- return extend(function(self, locals) {
- var object = {};
- for (var i = 0; i < keyValues.length; i++) {
- var keyValue = keyValues[i];
- object[keyValue.key] = keyValue.value(self, locals);
- }
- return object;
- }, {
- literal: true,
- constant: allConstant
- });
- }
- };
- function setter(obj, path, setValue, fullExp, options) {
-
- options = options || {};
- var element = path.split('.'), key;
- for (var i = 0; element.length > 1; i++) {
- key = ensureSafeMemberName(element.shift(), fullExp);
- var propertyObj = obj[key];
- if (!propertyObj) {
- propertyObj = {};
- obj[key] = propertyObj;
- }
- obj = propertyObj;
- if (obj.then && options.unwrapPromises) {
- promiseWarning(fullExp);
- if (!("$$v" in obj)) {
- (function(promise) {
- promise.then(function(val) { promise.$$v = val; }); }
- )(obj);
- }
- if (obj.$$v === undefined) {
- obj.$$v = {};
- }
- obj = obj.$$v;
- }
- }
- key = ensureSafeMemberName(element.shift(), fullExp);
- ensureSafeObject(obj, fullExp);
- ensureSafeObject(obj[key], fullExp);
- obj[key] = setValue;
- return setValue;
- }
- var getterFnCache = {};
- function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
- ensureSafeMemberName(key0, fullExp);
- ensureSafeMemberName(key1, fullExp);
- ensureSafeMemberName(key2, fullExp);
- ensureSafeMemberName(key3, fullExp);
- ensureSafeMemberName(key4, fullExp);
- return !options.unwrapPromises
- ? function cspSafeGetter(scope, locals) {
- var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
- if (pathVal == null) return pathVal;
- pathVal = pathVal[key0];
- if (!key1) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key1];
- if (!key2) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key2];
- if (!key3) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key3];
- if (!key4) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key4];
- return pathVal;
- }
- : function cspSafePromiseEnabledGetter(scope, locals) {
- var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
- promise;
- if (pathVal == null) return pathVal;
- pathVal = pathVal[key0];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- if (!key1) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key1];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- if (!key2) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key2];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- if (!key3) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key3];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- if (!key4) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key4];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- return pathVal;
- };
- }
- function getterFn(path, options, fullExp) {
-
-
-
- if (getterFnCache.hasOwnProperty(path)) {
- return getterFnCache[path];
- }
- var pathKeys = path.split('.'),
- pathKeysLength = pathKeys.length,
- fn;
-
- if (options.csp) {
- if (pathKeysLength < 6) {
- fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
- options);
- } else {
- fn = function(scope, locals) {
- var i = 0, val;
- do {
- val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
- pathKeys[i++], fullExp, options)(scope, locals);
- locals = undefined;
- scope = val;
- } while (i < pathKeysLength);
- return val;
- };
- }
- } else {
- var code = 'var p;\n';
- forEach(pathKeys, function(key, index) {
- ensureSafeMemberName(key, fullExp);
- code += 'if(s == null) return undefined;\n' +
- 's='+ (index
-
- ? 's'
-
- : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' +
- (options.unwrapPromises
- ? 'if (s && s.then) {\n' +
- ' pw("' + fullExp.replace(/(["\r\n])/g, '\\$1') + '");\n' +
- ' if (!("$$v" in s)) {\n' +
- ' p=s;\n' +
- ' p.$$v = undefined;\n' +
- ' p.then(function(v) {p.$$v=v;});\n' +
- '}\n' +
- ' s=s.$$v\n' +
- '}\n'
- : '');
- });
- code += 'return s;';
-
- var evaledFnGetter = new Function('s', 'k', 'pw', code);
-
- evaledFnGetter.toString = valueFn(code);
- fn = options.unwrapPromises ? function(scope, locals) {
- return evaledFnGetter(scope, locals, promiseWarning);
- } : evaledFnGetter;
- }
-
-
- if (path !== 'hasOwnProperty') {
- getterFnCache[path] = fn;
- }
- return fn;
- }
- function $ParseProvider() {
- var cache = {};
- var $parseOptions = {
- csp: false,
- unwrapPromises: false,
- logPromiseWarnings: true
- };
-
- this.unwrapPromises = function(value) {
- if (isDefined(value)) {
- $parseOptions.unwrapPromises = !!value;
- return this;
- } else {
- return $parseOptions.unwrapPromises;
- }
- };
-
- this.logPromiseWarnings = function(value) {
- if (isDefined(value)) {
- $parseOptions.logPromiseWarnings = value;
- return this;
- } else {
- return $parseOptions.logPromiseWarnings;
- }
- };
- this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) {
- $parseOptions.csp = $sniffer.csp;
- promiseWarning = function promiseWarningFn(fullExp) {
- if (!$parseOptions.logPromiseWarnings || promiseWarningCache.hasOwnProperty(fullExp)) return;
- promiseWarningCache[fullExp] = true;
- $log.warn('[$parse] Promise found in the expression `' + fullExp + '`. ' +
- 'Automatic unwrapping of promises in Angular expressions is deprecated.');
- };
- return function(exp) {
- var parsedExpression;
- switch (typeof exp) {
- case 'string':
- if (cache.hasOwnProperty(exp)) {
- return cache[exp];
- }
- var lexer = new Lexer($parseOptions);
- var parser = new Parser(lexer, $filter, $parseOptions);
- parsedExpression = parser.parse(exp);
- if (exp !== 'hasOwnProperty') {
-
-
- cache[exp] = parsedExpression;
- }
- return parsedExpression;
- case 'function':
- return exp;
- default:
- return noop;
- }
- };
- }];
- }
- function $QProvider() {
- this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
- return qFactory(function(callback) {
- $rootScope.$evalAsync(callback);
- }, $exceptionHandler);
- }];
- }
- function qFactory(nextTick, exceptionHandler) {
-
- var defer = function() {
- var pending = [],
- value, deferred;
- deferred = {
- resolve: function(val) {
- if (pending) {
- var callbacks = pending;
- pending = undefined;
- value = ref(val);
- if (callbacks.length) {
- nextTick(function() {
- var callback;
- for (var i = 0, ii = callbacks.length; i < ii; i++) {
- callback = callbacks[i];
- value.then(callback[0], callback[1], callback[2]);
- }
- });
- }
- }
- },
- reject: function(reason) {
- deferred.resolve(createInternalRejectedPromise(reason));
- },
- notify: function(progress) {
- if (pending) {
- var callbacks = pending;
- if (pending.length) {
- nextTick(function() {
- var callback;
- for (var i = 0, ii = callbacks.length; i < ii; i++) {
- callback = callbacks[i];
- callback[2](progress);
- }
- });
- }
- }
- },
- promise: {
- then: function(callback, errback, progressback) {
- var result = defer();
- var wrappedCallback = function(value) {
- try {
- result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
- } catch(e) {
- result.reject(e);
- exceptionHandler(e);
- }
- };
- var wrappedErrback = function(reason) {
- try {
- result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
- } catch(e) {
- result.reject(e);
- exceptionHandler(e);
- }
- };
- var wrappedProgressback = function(progress) {
- try {
- result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
- } catch(e) {
- exceptionHandler(e);
- }
- };
- if (pending) {
- pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
- } else {
- value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
- }
- return result.promise;
- },
- "catch": function(callback) {
- return this.then(null, callback);
- },
- "finally": function(callback) {
- function makePromise(value, resolved) {
- var result = defer();
- if (resolved) {
- result.resolve(value);
- } else {
- result.reject(value);
- }
- return result.promise;
- }
- function handleCallback(value, isResolved) {
- var callbackOutput = null;
- try {
- callbackOutput = (callback ||defaultCallback)();
- } catch(e) {
- return makePromise(e, false);
- }
- if (isPromiseLike(callbackOutput)) {
- return callbackOutput.then(function() {
- return makePromise(value, isResolved);
- }, function(error) {
- return makePromise(error, false);
- });
- } else {
- return makePromise(value, isResolved);
- }
- }
- return this.then(function(value) {
- return handleCallback(value, true);
- }, function(error) {
- return handleCallback(error, false);
- });
- }
- }
- };
- return deferred;
- };
- var ref = function(value) {
- if (isPromiseLike(value)) return value;
- return {
- then: function(callback) {
- var result = defer();
- nextTick(function() {
- result.resolve(callback(value));
- });
- return result.promise;
- }
- };
- };
-
- var reject = function(reason) {
- var result = defer();
- result.reject(reason);
- return result.promise;
- };
- var createInternalRejectedPromise = function(reason) {
- return {
- then: function(callback, errback) {
- var result = defer();
- nextTick(function() {
- try {
- result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
- } catch(e) {
- result.reject(e);
- exceptionHandler(e);
- }
- });
- return result.promise;
- }
- };
- };
-
- var when = function(value, callback, errback, progressback) {
- var result = defer(),
- done;
- var wrappedCallback = function(value) {
- try {
- return (isFunction(callback) ? callback : defaultCallback)(value);
- } catch (e) {
- exceptionHandler(e);
- return reject(e);
- }
- };
- var wrappedErrback = function(reason) {
- try {
- return (isFunction(errback) ? errback : defaultErrback)(reason);
- } catch (e) {
- exceptionHandler(e);
- return reject(e);
- }
- };
- var wrappedProgressback = function(progress) {
- try {
- return (isFunction(progressback) ? progressback : defaultCallback)(progress);
- } catch (e) {
- exceptionHandler(e);
- }
- };
- nextTick(function() {
- ref(value).then(function(value) {
- if (done) return;
- done = true;
- result.resolve(ref(value).then(wrappedCallback, wrappedErrback, wrappedProgressback));
- }, function(reason) {
- if (done) return;
- done = true;
- result.resolve(wrappedErrback(reason));
- }, function(progress) {
- if (done) return;
- result.notify(wrappedProgressback(progress));
- });
- });
- return result.promise;
- };
- function defaultCallback(value) {
- return value;
- }
- function defaultErrback(reason) {
- return reject(reason);
- }
-
- function all(promises) {
- var deferred = defer(),
- counter = 0,
- results = isArray(promises) ? [] : {};
- forEach(promises, function(promise, key) {
- counter++;
- ref(promise).then(function(value) {
- if (results.hasOwnProperty(key)) return;
- results[key] = value;
- if (!(--counter)) deferred.resolve(results);
- }, function(reason) {
- if (results.hasOwnProperty(key)) return;
- deferred.reject(reason);
- });
- });
- if (counter === 0) {
- deferred.resolve(results);
- }
- return deferred.promise;
- }
- return {
- defer: defer,
- reject: reject,
- when: when,
- all: all
- };
- }
- function $$RAFProvider(){
- this.$get = ['$window', '$timeout', function($window, $timeout) {
- var requestAnimationFrame = $window.requestAnimationFrame ||
- $window.webkitRequestAnimationFrame ||
- $window.mozRequestAnimationFrame;
- var cancelAnimationFrame = $window.cancelAnimationFrame ||
- $window.webkitCancelAnimationFrame ||
- $window.mozCancelAnimationFrame ||
- $window.webkitCancelRequestAnimationFrame;
- var rafSupported = !!requestAnimationFrame;
- var raf = rafSupported
- ? function(fn) {
- var id = requestAnimationFrame(fn);
- return function() {
- cancelAnimationFrame(id);
- };
- }
- : function(fn) {
- var timer = $timeout(fn, 16.66, false);
- return function() {
- $timeout.cancel(timer);
- };
- };
- raf.supported = rafSupported;
- return raf;
- }];
- }
- function $RootScopeProvider(){
- var TTL = 10;
- var $rootScopeMinErr = minErr('$rootScope');
- var lastDirtyWatch = null;
- this.digestTtl = function(value) {
- if (arguments.length) {
- TTL = value;
- }
- return TTL;
- };
- this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
- function( $injector, $exceptionHandler, $parse, $browser) {
-
- function Scope() {
- this.$id = nextUid();
- this.$$phase = this.$parent = this.$$watchers =
- this.$$nextSibling = this.$$prevSibling =
- this.$$childHead = this.$$childTail = null;
- this['this'] = this.$root = this;
- this.$$destroyed = false;
- this.$$asyncQueue = [];
- this.$$postDigestQueue = [];
- this.$$listeners = {};
- this.$$listenerCount = {};
- this.$$isolateBindings = {};
- }
-
- Scope.prototype = {
- constructor: Scope,
-
- $new: function(isolate) {
- var ChildScope,
- child;
- if (isolate) {
- child = new Scope();
- child.$root = this.$root;
-
- child.$$asyncQueue = this.$$asyncQueue;
- child.$$postDigestQueue = this.$$postDigestQueue;
- } else {
-
-
- if (!this.$$childScopeClass) {
- this.$$childScopeClass = function() {
- this.$$watchers = this.$$nextSibling =
- this.$$childHead = this.$$childTail = null;
- this.$$listeners = {};
- this.$$listenerCount = {};
- this.$id = nextUid();
- this.$$childScopeClass = null;
- };
- this.$$childScopeClass.prototype = this;
- }
- child = new this.$$childScopeClass();
- }
- child['this'] = child;
- child.$parent = this;
- child.$$prevSibling = this.$$childTail;
- if (this.$$childHead) {
- this.$$childTail.$$nextSibling = child;
- this.$$childTail = child;
- } else {
- this.$$childHead = this.$$childTail = child;
- }
- return child;
- },
-
- $watch: function(watchExp, listener, objectEquality) {
- var scope = this,
- get = compileToFn(watchExp, 'watch'),
- array = scope.$$watchers,
- watcher = {
- fn: listener,
- last: initWatchVal,
- get: get,
- exp: watchExp,
- eq: !!objectEquality
- };
- lastDirtyWatch = null;
- // in the case user pass string, we need to compile it, do we really need this ?
- if (!isFunction(listener)) {
- var listenFn = compileToFn(listener || noop, 'listener');
- watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};
- }
- if (typeof watchExp == 'string' && get.constant) {
- var originalFn = watcher.fn;
- watcher.fn = function(newVal, oldVal, scope) {
- originalFn.call(this, newVal, oldVal, scope);
- arrayRemove(array, watcher);
- };
- }
- if (!array) {
- array = scope.$$watchers = [];
- }
-
-
- array.unshift(watcher);
- return function deregisterWatch() {
- arrayRemove(array, watcher);
- lastDirtyWatch = null;
- };
- },
-
- $watchCollection: function(obj, listener) {
- var self = this;
-
- var newValue;
-
-
- var oldValue;
-
- var veryOldValue;
-
- var trackVeryOldValue = (listener.length > 1);
- var changeDetected = 0;
- var objGetter = $parse(obj);
- var internalArray = [];
- var internalObject = {};
- var initRun = true;
- var oldLength = 0;
- function $watchCollectionWatch() {
- newValue = objGetter(self);
- var newLength, key, bothNaN;
- if (!isObject(newValue)) {
- if (oldValue !== newValue) {
- oldValue = newValue;
- changeDetected++;
- }
- } else if (isArrayLike(newValue)) {
- if (oldValue !== internalArray) {
-
- oldValue = internalArray;
- oldLength = oldValue.length = 0;
- changeDetected++;
- }
- newLength = newValue.length;
- if (oldLength !== newLength) {
-
- changeDetected++;
- oldValue.length = oldLength = newLength;
- }
-
- for (var i = 0; i < newLength; i++) {
- bothNaN = (oldValue[i] !== oldValue[i]) &&
- (newValue[i] !== newValue[i]);
- if (!bothNaN && (oldValue[i] !== newValue[i])) {
- changeDetected++;
- oldValue[i] = newValue[i];
- }
- }
- } else {
- if (oldValue !== internalObject) {
-
- oldValue = internalObject = {};
- oldLength = 0;
- changeDetected++;
- }
-
- newLength = 0;
- for (key in newValue) {
- if (newValue.hasOwnProperty(key)) {
- newLength++;
- if (oldValue.hasOwnProperty(key)) {
- bothNaN = (oldValue[key] !== oldValue[key]) &&
- (newValue[key] !== newValue[key]);
- if (!bothNaN && (oldValue[key] !== newValue[key])) {
- changeDetected++;
- oldValue[key] = newValue[key];
- }
- } else {
- oldLength++;
- oldValue[key] = newValue[key];
- changeDetected++;
- }
- }
- }
- if (oldLength > newLength) {
-
- changeDetected++;
- for(key in oldValue) {
- if (oldValue.hasOwnProperty(key) && !newValue.hasOwnProperty(key)) {
- oldLength--;
- delete oldValue[key];
- }
- }
- }
- }
- return changeDetected;
- }
- function $watchCollectionAction() {
- if (initRun) {
- initRun = false;
- listener(newValue, newValue, self);
- } else {
- listener(newValue, veryOldValue, self);
- }
-
- if (trackVeryOldValue) {
- if (!isObject(newValue)) {
-
- veryOldValue = newValue;
- } else if (isArrayLike(newValue)) {
- veryOldValue = new Array(newValue.length);
- for (var i = 0; i < newValue.length; i++) {
- veryOldValue[i] = newValue[i];
- }
- } else {
- veryOldValue = {};
- for (var key in newValue) {
- if (hasOwnProperty.call(newValue, key)) {
- veryOldValue[key] = newValue[key];
- }
- }
- }
- }
- }
- return this.$watch($watchCollectionWatch, $watchCollectionAction);
- },
-
- $digest: function() {
- var watch, value, last,
- watchers,
- asyncQueue = this.$$asyncQueue,
- postDigestQueue = this.$$postDigestQueue,
- length,
- dirty, ttl = TTL,
- next, current, target = this,
- watchLog = [],
- logIdx, logMsg, asyncTask;
- beginPhase('$digest');
- lastDirtyWatch = null;
- do {
- dirty = false;
- current = target;
- while(asyncQueue.length) {
- try {
- asyncTask = asyncQueue.shift();
- asyncTask.scope.$eval(asyncTask.expression);
- } catch (e) {
- clearPhase();
- $exceptionHandler(e);
- }
- lastDirtyWatch = null;
- }
- traverseScopesLoop:
- do {
- if ((watchers = current.$$watchers)) {
-
- length = watchers.length;
- while (length--) {
- try {
- watch = watchers[length];
-
-
- if (watch) {
- if ((value = watch.get(current)) !== (last = watch.last) &&
- !(watch.eq
- ? equals(value, last)
- : (typeof value === 'number' && typeof last === 'number'
- && isNaN(value) && isNaN(last)))) {
- dirty = true;
- lastDirtyWatch = watch;
- watch.last = watch.eq ? copy(value, null) : value;
- watch.fn(value, ((last === initWatchVal) ? value : last), current);
- if (ttl < 5) {
- logIdx = 4 - ttl;
- if (!watchLog[logIdx]) watchLog[logIdx] = [];
- logMsg = (isFunction(watch.exp))
- ? 'fn: ' + (watch.exp.name || watch.exp.toString())
- : watch.exp;
- logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
- watchLog[logIdx].push(logMsg);
- }
- } else if (watch === lastDirtyWatch) {
-
-
- dirty = false;
- break traverseScopesLoop;
- }
- }
- } catch (e) {
- clearPhase();
- $exceptionHandler(e);
- }
- }
- }
-
-
-
- if (!(next = (current.$$childHead ||
- (current !== target && current.$$nextSibling)))) {
- while(current !== target && !(next = current.$$nextSibling)) {
- current = current.$parent;
- }
- }
- } while ((current = next));
-
- if((dirty || asyncQueue.length) && !(ttl--)) {
- clearPhase();
- throw $rootScopeMinErr('infdig',
- '{0} $digest() iterations reached. Aborting!\n' +
- 'Watchers fired in the last 5 iterations: {1}',
- TTL, toJson(watchLog));
- }
- } while (dirty || asyncQueue.length);
- clearPhase();
- while(postDigestQueue.length) {
- try {
- postDigestQueue.shift()();
- } catch (e) {
- $exceptionHandler(e);
- }
- }
- },
-
-
- $destroy: function() {
-
- if (this.$$destroyed) return;
- var parent = this.$parent;
- this.$broadcast('$destroy');
- this.$$destroyed = true;
- if (this === $rootScope) return;
- forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));
-
-
- if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
- if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
- if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
- if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
-
-
-
-
-
-
-
- this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
- this.$$childTail = this.$root = null;
-
- this.$$listeners = {};
- this.$$watchers = this.$$asyncQueue = this.$$postDigestQueue = [];
-
- this.$destroy = this.$digest = this.$apply = noop;
- this.$on = this.$watch = function() { return noop; };
- },
-
- $eval: function(expr, locals) {
- return $parse(expr)(this, locals);
- },
-
- $evalAsync: function(expr) {
-
-
- if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) {
- $browser.defer(function() {
- if ($rootScope.$$asyncQueue.length) {
- $rootScope.$digest();
- }
- });
- }
- this.$$asyncQueue.push({scope: this, expression: expr});
- },
- $$postDigest : function(fn) {
- this.$$postDigestQueue.push(fn);
- },
-
- $apply: function(expr) {
- try {
- beginPhase('$apply');
- return this.$eval(expr);
- } catch (e) {
- $exceptionHandler(e);
- } finally {
- clearPhase();
- try {
- $rootScope.$digest();
- } catch (e) {
- $exceptionHandler(e);
- throw e;
- }
- }
- },
-
- $on: function(name, listener) {
- var namedListeners = this.$$listeners[name];
- if (!namedListeners) {
- this.$$listeners[name] = namedListeners = [];
- }
- namedListeners.push(listener);
- var current = this;
- do {
- if (!current.$$listenerCount[name]) {
- current.$$listenerCount[name] = 0;
- }
- current.$$listenerCount[name]++;
- } while ((current = current.$parent));
- var self = this;
- return function() {
- namedListeners[indexOf(namedListeners, listener)] = null;
- decrementListenerCount(self, 1, name);
- };
- },
-
- $emit: function(name, args) {
- var empty = [],
- namedListeners,
- scope = this,
- stopPropagation = false,
- event = {
- name: name,
- targetScope: scope,
- stopPropagation: function() {stopPropagation = true;},
- preventDefault: function() {
- event.defaultPrevented = true;
- },
- defaultPrevented: false
- },
- listenerArgs = concat([event], arguments, 1),
- i, length;
- do {
- namedListeners = scope.$$listeners[name] || empty;
- event.currentScope = scope;
- for (i=0, length=namedListeners.length; i<length; i++) {
-
- if (!namedListeners[i]) {
- namedListeners.splice(i, 1);
- i--;
- length--;
- continue;
- }
- try {
-
- namedListeners[i].apply(null, listenerArgs);
- } catch (e) {
- $exceptionHandler(e);
- }
- }
-
- if (stopPropagation) return event;
-
- scope = scope.$parent;
- } while (scope);
- return event;
- },
-
- $broadcast: function(name, args) {
- var target = this,
- current = target,
- next = target,
- event = {
- name: name,
- targetScope: target,
- preventDefault: function() {
- event.defaultPrevented = true;
- },
- defaultPrevented: false
- },
- listenerArgs = concat([event], arguments, 1),
- listeners, i, length;
-
- while ((current = next)) {
- event.currentScope = current;
- listeners = current.$$listeners[name] || [];
- for (i=0, length = listeners.length; i<length; i++) {
-
- if (!listeners[i]) {
- listeners.splice(i, 1);
- i--;
- length--;
- continue;
- }
- try {
- listeners[i].apply(null, listenerArgs);
- } catch(e) {
- $exceptionHandler(e);
- }
- }
-
-
-
-
- if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
- (current !== target && current.$$nextSibling)))) {
- while(current !== target && !(next = current.$$nextSibling)) {
- current = current.$parent;
- }
- }
- }
- return event;
- }
- };
- var $rootScope = new Scope();
- return $rootScope;
- function beginPhase(phase) {
- if ($rootScope.$$phase) {
- throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
- }
- $rootScope.$$phase = phase;
- }
- function clearPhase() {
- $rootScope.$$phase = null;
- }
- function compileToFn(exp, name) {
- var fn = $parse(exp);
- assertArgFn(fn, name);
- return fn;
- }
- function decrementListenerCount(current, count, name) {
- do {
- current.$$listenerCount[name] -= count;
- if (current.$$listenerCount[name] === 0) {
- delete current.$$listenerCount[name];
- }
- } while ((current = current.$parent));
- }
-
- function initWatchVal() {}
- }];
- }
- function $$SanitizeUriProvider() {
- var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
- imgSrcSanitizationWhitelist = /^\s*(https?|ftp|file):|data:image\//;
-
- this.aHrefSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- aHrefSanitizationWhitelist = regexp;
- return this;
- }
- return aHrefSanitizationWhitelist;
- };
-
- this.imgSrcSanitizationWhitelist = function(regexp) {
- if (isDefined(regexp)) {
- imgSrcSanitizationWhitelist = regexp;
- return this;
- }
- return imgSrcSanitizationWhitelist;
- };
- this.$get = function() {
- return function sanitizeUri(uri, isImage) {
- var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
- var normalizedVal;
-
- if (!msie || msie >= 8 ) {
- normalizedVal = urlResolve(uri).href;
- if (normalizedVal !== '' && !normalizedVal.match(regex)) {
- return 'unsafe:'+normalizedVal;
- }
- }
- return uri;
- };
- };
- }
- var $sceMinErr = minErr('$sce');
- var SCE_CONTEXTS = {
- HTML: 'html',
- CSS: 'css',
- URL: 'url',
-
-
- RESOURCE_URL: 'resourceUrl',
- JS: 'js'
- };
- function escapeForRegexp(s) {
- return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
- replace(/\x08/g, '\\x08');
- }
- function adjustMatcher(matcher) {
- if (matcher === 'self') {
- return matcher;
- } else if (isString(matcher)) {
-
-
-
-
- if (matcher.indexOf('***') > -1) {
- throw $sceMinErr('iwcard',
- 'Illegal sequence *** in string matcher. String: {0}', matcher);
- }
- matcher = escapeForRegexp(matcher).
- replace('\\*\\*', '.*').
- replace('\\*', '[^:/.?&;]*');
- return new RegExp('^' + matcher + '$');
- } else if (isRegExp(matcher)) {
-
-
-
- return new RegExp('^' + matcher.source + '$');
- } else {
- throw $sceMinErr('imatcher',
- 'Matchers may only be "self", string patterns or RegExp objects');
- }
- }
- function adjustMatchers(matchers) {
- var adjustedMatchers = [];
- if (isDefined(matchers)) {
- forEach(matchers, function(matcher) {
- adjustedMatchers.push(adjustMatcher(matcher));
- });
- }
- return adjustedMatchers;
- }
- function $SceDelegateProvider() {
- this.SCE_CONTEXTS = SCE_CONTEXTS;
-
- var resourceUrlWhitelist = ['self'],
- resourceUrlBlacklist = [];
-
- this.resourceUrlWhitelist = function (value) {
- if (arguments.length) {
- resourceUrlWhitelist = adjustMatchers(value);
- }
- return resourceUrlWhitelist;
- };
-
- this.resourceUrlBlacklist = function (value) {
- if (arguments.length) {
- resourceUrlBlacklist = adjustMatchers(value);
- }
- return resourceUrlBlacklist;
- };
- this.$get = ['$injector', function($injector) {
- var htmlSanitizer = function htmlSanitizer(html) {
- throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
- };
- if ($injector.has('$sanitize')) {
- htmlSanitizer = $injector.get('$sanitize');
- }
- function matchUrl(matcher, parsedUrl) {
- if (matcher === 'self') {
- return urlIsSameOrigin(parsedUrl);
- } else {
-
- return !!matcher.exec(parsedUrl.href);
- }
- }
- function isResourceUrlAllowedByPolicy(url) {
- var parsedUrl = urlResolve(url.toString());
- var i, n, allowed = false;
-
- for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
- if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
- allowed = true;
- break;
- }
- }
- if (allowed) {
-
- for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
- if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
- allowed = false;
- break;
- }
- }
- }
- return allowed;
- }
- function generateHolderType(Base) {
- var holderType = function TrustedValueHolderType(trustedValue) {
- this.$$unwrapTrustedValue = function() {
- return trustedValue;
- };
- };
- if (Base) {
- holderType.prototype = new Base();
- }
- holderType.prototype.valueOf = function sceValueOf() {
- return this.$$unwrapTrustedValue();
- };
- holderType.prototype.toString = function sceToString() {
- return this.$$unwrapTrustedValue().toString();
- };
- return holderType;
- }
- var trustedValueHolderBase = generateHolderType(),
- byType = {};
- byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
- byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
-
- function trustAs(type, trustedValue) {
- var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
- if (!Constructor) {
- throw $sceMinErr('icontext',
- 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
- type, trustedValue);
- }
- if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
- return trustedValue;
- }
-
-
- if (typeof trustedValue !== 'string') {
- throw $sceMinErr('itype',
- 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
- type);
- }
- return new Constructor(trustedValue);
- }
-
- function valueOf(maybeTrusted) {
- if (maybeTrusted instanceof trustedValueHolderBase) {
- return maybeTrusted.$$unwrapTrustedValue();
- } else {
- return maybeTrusted;
- }
- }
-
- function getTrusted(type, maybeTrusted) {
- if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
- return maybeTrusted;
- }
- var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
- if (constructor && maybeTrusted instanceof constructor) {
- return maybeTrusted.$$unwrapTrustedValue();
- }
-
-
-
- if (type === SCE_CONTEXTS.RESOURCE_URL) {
- if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
- return maybeTrusted;
- } else {
- throw $sceMinErr('insecurl',
- 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',
- maybeTrusted.toString());
- }
- } else if (type === SCE_CONTEXTS.HTML) {
- return htmlSanitizer(maybeTrusted);
- }
- throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
- }
- return { trustAs: trustAs,
- getTrusted: getTrusted,
- valueOf: valueOf };
- }];
- }
- function $SceProvider() {
- var enabled = true;
-
- this.enabled = function (value) {
- if (arguments.length) {
- enabled = !!value;
- }
- return enabled;
- };
-
- this.$get = ['$parse', '$sniffer', '$sceDelegate', function(
- $parse, $sniffer, $sceDelegate) {
-
-
- if (enabled && $sniffer.msie && $sniffer.msieDocumentMode < 8) {
- throw $sceMinErr('iequirks',
- 'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' +
- 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
- 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
- }
- var sce = shallowCopy(SCE_CONTEXTS);
-
- sce.isEnabled = function () {
- return enabled;
- };
- sce.trustAs = $sceDelegate.trustAs;
- sce.getTrusted = $sceDelegate.getTrusted;
- sce.valueOf = $sceDelegate.valueOf;
- if (!enabled) {
- sce.trustAs = sce.getTrusted = function(type, value) { return value; };
- sce.valueOf = identity;
- }
-
- sce.parseAs = function sceParseAs(type, expr) {
- var parsed = $parse(expr);
- if (parsed.literal && parsed.constant) {
- return parsed;
- } else {
- return function sceParseAsTrusted(self, locals) {
- return sce.getTrusted(type, parsed(self, locals));
- };
- }
- };
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- var parse = sce.parseAs,
- getTrusted = sce.getTrusted,
- trustAs = sce.trustAs;
- forEach(SCE_CONTEXTS, function (enumValue, name) {
- var lName = lowercase(name);
- sce[camelCase("parse_as_" + lName)] = function (expr) {
- return parse(enumValue, expr);
- };
- sce[camelCase("get_trusted_" + lName)] = function (value) {
- return getTrusted(enumValue, value);
- };
- sce[camelCase("trust_as_" + lName)] = function (value) {
- return trustAs(enumValue, value);
- };
- });
- return sce;
- }];
- }
- function $SnifferProvider() {
- this.$get = ['$window', '$document', function($window, $document) {
- var eventSupport = {},
- android =
- int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
- boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
- document = $document[0] || {},
- documentMode = document.documentMode,
- vendorPrefix,
- vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,
- bodyStyle = document.body && document.body.style,
- transitions = false,
- animations = false,
- match;
- if (bodyStyle) {
- for(var prop in bodyStyle) {
- if(match = vendorRegex.exec(prop)) {
- vendorPrefix = match[0];
- vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
- break;
- }
- }
- if(!vendorPrefix) {
- vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
- }
- transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
- animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
- if (android && (!transitions||!animations)) {
- transitions = isString(document.body.style.webkitTransition);
- animations = isString(document.body.style.webkitAnimation);
- }
- }
- return {
-
-
-
-
-
-
-
-
- history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
-
- hashchange: 'onhashchange' in $window &&
-
- (!documentMode || documentMode > 7),
- hasEvent: function(event) {
-
-
-
- if (event == 'input' && msie == 9) return false;
- if (isUndefined(eventSupport[event])) {
- var divElm = document.createElement('div');
- eventSupport[event] = 'on' + event in divElm;
- }
- return eventSupport[event];
- },
- csp: csp(),
- vendorPrefix: vendorPrefix,
- transitions : transitions,
- animations : animations,
- android: android,
- msie : msie,
- msieDocumentMode: documentMode
- };
- }];
- }
- function $TimeoutProvider() {
- this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',
- function($rootScope, $browser, $q, $exceptionHandler) {
- var deferreds = {};
-
- function timeout(fn, delay, invokeApply) {
- var deferred = $q.defer(),
- promise = deferred.promise,
- skipApply = (isDefined(invokeApply) && !invokeApply),
- timeoutId;
- timeoutId = $browser.defer(function() {
- try {
- deferred.resolve(fn());
- } catch(e) {
- deferred.reject(e);
- $exceptionHandler(e);
- }
- finally {
- delete deferreds[promise.$$timeoutId];
- }
- if (!skipApply) $rootScope.$apply();
- }, delay);
- promise.$$timeoutId = timeoutId;
- deferreds[timeoutId] = deferred;
- return promise;
- }
-
- timeout.cancel = function(promise) {
- if (promise && promise.$$timeoutId in deferreds) {
- deferreds[promise.$$timeoutId].reject('canceled');
- delete deferreds[promise.$$timeoutId];
- return $browser.defer.cancel(promise.$$timeoutId);
- }
- return false;
- };
- return timeout;
- }];
- }
- var urlParsingNode = document.createElement("a");
- var originUrl = urlResolve(window.location.href, true);
- function urlResolve(url, base) {
- var href = url;
- if (msie) {
-
-
- urlParsingNode.setAttribute("href", href);
- href = urlParsingNode.href;
- }
- urlParsingNode.setAttribute('href', href);
-
- return {
- href: urlParsingNode.href,
- protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
- host: urlParsingNode.host,
- search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
- hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
- hostname: urlParsingNode.hostname,
- port: urlParsingNode.port,
- pathname: (urlParsingNode.pathname.charAt(0) === '/')
- ? urlParsingNode.pathname
- : '/' + urlParsingNode.pathname
- };
- }
- function urlIsSameOrigin(requestUrl) {
- var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
- return (parsed.protocol === originUrl.protocol &&
- parsed.host === originUrl.host);
- }
- function $WindowProvider(){
- this.$get = valueFn(window);
- }
- /* global currencyFilter: true,
- dateFilter: true,
- filterFilter: true,
- jsonFilter: true,
- limitToFilter: true,
- lowercaseFilter: true,
- numberFilter: true,
- orderByFilter: true,
- uppercaseFilter: true,
- */
- /**
- * @ngdoc provider
- * @name $filterProvider
- * @description
- *
- * Filters are just functions which transform input to an output. However filters need to be
- * Dependency Injected. To achieve this a filter definition consists of a factory function which is
- * annotated with dependencies and is responsible for creating a filter function.
- *
- * ```js
- * // Filter registration
- * function MyModule($provide, $filterProvider) {
- *
- * $provide.value('greet', function(name){
- * return 'Hello ' + name + '!';
- * });
- *
- *
- *
- * $filterProvider.register('greet', function(greet){
- *
- *
- * return function(text) {
- *
- * return text && greet(text) || text;
- * };
- * });
- * }
- * ```
- *
- * The filter function is registered with the `$injector` under the filter name suffix with
- * `Filter`.
- *
- * ```js
- * it('should be the same instance', inject(
- * function($filterProvider) {
- * $filterProvider.register('reverse', function(){
- * return ...;
- * });
- * },
- * function($filter, reverseFilter) {
- * expect($filter('reverse')).toBe(reverseFilter);
- * });
- * ```
- *
- *
- * For more information about how angular filters work, and how to create your own filters, see
- * {@link guide/filter Filters} in the Angular Developer Guide.
- */
- /**
- * @ngdoc method
- * @name $filterProvider#register
- * @description
- * Register filter factory function.
- *
- * @param {String} name Name of the filter.
- * @param {Function} fn The filter factory function which is injectable.
- */
- /**
- * @ngdoc service
- * @name $filter
- * @kind function
- * @description
- * Filters are used for formatting data displayed to the user.
- *
- * The general syntax in templates is as follows:
- *
- * {{ expression [| filter_name[:parameter_value] ... ] }}
- *
- * @param {String} name Name of the filter function to retrieve
- * @return {Function} the filter function
- * @example
- <example name="$filter" module="filterExample">
- <file name="index.html">
- <div ng-controller="MainCtrl">
- <h3>{{ originalText }}</h3>
- <h3>{{ filteredText }}</h3>
- </div>
- </file>
- <file name="script.js">
- angular.module('filterExample', [])
- .controller('MainCtrl', function($scope, $filter) {
- $scope.originalText = 'hello';
- $scope.filteredText = $filter('uppercase')($scope.originalText);
- });
- </file>
- </example>
- */
- $FilterProvider.$inject = ['$provide'];
- function $FilterProvider($provide) {
- var suffix = 'Filter';
- /**
- * @ngdoc method
- * @name $controllerProvider#register
- * @param {string|Object} name Name of the filter function, or an object map of filters where
- * the keys are the filter names and the values are the filter factories.
- * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
- * of the registered filter instances.
- */
- function register(name, factory) {
- if(isObject(name)) {
- var filters = {};
- forEach(name, function(filter, key) {
- filters[key] = register(key, filter);
- });
- return filters;
- } else {
- return $provide.factory(name + suffix, factory);
- }
- }
- this.register = register;
- this.$get = ['$injector', function($injector) {
- return function(name) {
- return $injector.get(name + suffix);
- };
- }];
- ////////////////////////////////////////
- /* global
- currencyFilter: false,
- dateFilter: false,
- filterFilter: false,
- jsonFilter: false,
- limitToFilter: false,
- lowercaseFilter: false,
- numberFilter: false,
- orderByFilter: false,
- uppercaseFilter: false,
- */
- register('currency', currencyFilter);
- register('date', dateFilter);
- register('filter', filterFilter);
- register('json', jsonFilter);
- register('limitTo', limitToFilter);
- register('lowercase', lowercaseFilter);
- register('number', numberFilter);
- register('orderBy', orderByFilter);
- register('uppercase', uppercaseFilter);
- }
- /**
- * @ngdoc filter
- * @name filter
- * @kind function
- *
- * @description
- * Selects a subset of items from `array` and returns it as a new array.
- *
- * @param {Array} array The source array.
- * @param {string|Object|function()} expression The predicate to be used for selecting items from
- * `array`.
- *
- * Can be one of:
- *
- * - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
- * the contents of the `array`. All strings or objects with string properties in `array` that contain this string
- * will be returned. The predicate can be negated by prefixing the string with `!`.
- *
- * - `Object`: A pattern object can be used to filter specific properties on objects contained
- * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
- * which have property `name` containing "M" and property `phone` containing "1". A special
- * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
- * property of the object. That's equivalent to the simple substring match with a `string`
- * as described above.
- *
- * - `function(value)`: A predicate function can be used to write arbitrary filters. The function is
- * called for each element of `array`. The final result is an array of those elements that
- * the predicate returned true for.
- *
- * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
- * determining if the expected value (from the filter expression) and actual value (from
- * the object in the array) should be considered a match.
- *
- * Can be one of:
- *
- * - `function(actual, expected)`:
- * The function will be given the object value and the predicate value to compare and
- * should return true if the item should be included in filtered result.
- *
- * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
- * this is essentially strict comparison of expected and actual.
- *
- * - `false|undefined`: A short hand for a function which will look for a substring match in case
- * insensitive way.
- *
- * @example
- <example>
- <file name="index.html">
- <div ng-init="friends = [{name:'John', phone:'555-1276'},
- {name:'Mary', phone:'800-BIG-MARY'},
- {name:'Mike', phone:'555-4321'},
- {name:'Adam', phone:'555-5678'},
- {name:'Julie', phone:'555-8765'},
- {name:'Juliette', phone:'555-5678'}]"></div>
- Search: <input ng-model="searchText">
- <table id="searchTextResults">
- <tr><th>Name</th><th>Phone</th></tr>
- <tr ng-repeat="friend in friends | filter:searchText">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- </tr>
- </table>
- <hr>
- Any: <input ng-model="search.$"> <br>
- Name only <input ng-model="search.name"><br>
- Phone only <input ng-model="search.phone"><br>
- Equality <input type="checkbox" ng-model="strict"><br>
- <table id="searchObjResults">
- <tr><th>Name</th><th>Phone</th></tr>
- <tr ng-repeat="friendObj in friends | filter:search:strict">
- <td>{{friendObj.name}}</td>
- <td>{{friendObj.phone}}</td>
- </tr>
- </table>
- </file>
- <file name="protractor.js" type="protractor">
- var expectFriendNames = function(expectedNames, key) {
- element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
- arr.forEach(function(wd, i) {
- expect(wd.getText()).toMatch(expectedNames[i]);
- });
- });
- };
- it('should search across all fields when filtering with a string', function() {
- var searchText = element(by.model('searchText'));
- searchText.clear();
- searchText.sendKeys('m');
- expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');
- searchText.clear();
- searchText.sendKeys('76');
- expectFriendNames(['John', 'Julie'], 'friend');
- });
- it('should search in specific fields when filtering with a predicate object', function() {
- var searchAny = element(by.model('search.$'));
- searchAny.clear();
- searchAny.sendKeys('i');
- expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
- });
- it('should use a equal comparison when comparator is true', function() {
- var searchName = element(by.model('search.name'));
- var strict = element(by.model('strict'));
- searchName.clear();
- searchName.sendKeys('Julie');
- strict.click();
- expectFriendNames(['Julie'], 'friendObj');
- });
- </file>
- </example>
- */
- function filterFilter() {
- return function(array, expression, comparator) {
- if (!isArray(array)) return array;
- var comparatorType = typeof(comparator),
- predicates = [];
- predicates.check = function(value) {
- for (var j = 0; j < predicates.length; j++) {
- if(!predicates[j](value)) {
- return false;
- }
- }
- return true;
- };
- if (comparatorType !== 'function') {
- if (comparatorType === 'boolean' && comparator) {
- comparator = function(obj, text) {
- return angular.equals(obj, text);
- };
- } else {
- comparator = function(obj, text) {
- if (obj && text && typeof obj === 'object' && typeof text === 'object') {
- for (var objKey in obj) {
- if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
- comparator(obj[objKey], text[objKey])) {
- return true;
- }
- }
- return false;
- }
- text = (''+text).toLowerCase();
- return (''+obj).toLowerCase().indexOf(text) > -1;
- };
- }
- }
- var search = function(obj, text){
- if (typeof text == 'string' && text.charAt(0) === '!') {
- return !search(obj, text.substr(1));
- }
- switch (typeof obj) {
- case "boolean":
- case "number":
- case "string":
- return comparator(obj, text);
- case "object":
- switch (typeof text) {
- case "object":
- return comparator(obj, text);
- default:
- for ( var objKey in obj) {
- if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
- return true;
- }
- }
- break;
- }
- return false;
- case "array":
- for ( var i = 0; i < obj.length; i++) {
- if (search(obj[i], text)) {
- return true;
- }
- }
- return false;
- default:
- return false;
- }
- };
- switch (typeof expression) {
- case "boolean":
- case "number":
- case "string":
- // Set up expression object and fall through
- expression = {$:expression};
- // jshint -W086
- case "object":
- // jshint +W086
- for (var key in expression) {
- (function(path) {
- if (typeof expression[path] === 'undefined') return;
- predicates.push(function(value) {
- return search(path == '$' ? value : (value && value[path]), expression[path]);
- });
- })(key);
- }
- break;
- case 'function':
- predicates.push(expression);
- break;
- default:
- return array;
- }
- var filtered = [];
- for ( var j = 0; j < array.length; j++) {
- var value = array[j];
- if (predicates.check(value)) {
- filtered.push(value);
- }
- }
- return filtered;
- };
- }
- /**
- * @ngdoc filter
- * @name currency
- * @kind function
- *
- * @description
- * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
- * symbol for current locale is used.
- *
- * @param {number} amount Input to filter.
- * @param {string=} symbol Currency symbol or identifier to be displayed.
- * @returns {string} Formatted number.
- *
- *
- * @example
- <example module="currencyExample">
- <file name="index.html">
- <script>
- angular.module('currencyExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.amount = 1234.56;
- }]);
- </script>
- <div ng-controller="ExampleController">
- <input type="number" ng-model="amount"> <br>
- default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
- custom currency identifier (USD$): <span>{{amount | currency:"USD$"}}</span>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should init with 1234.56', function() {
- expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
- expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('USD$1,234.56');
- });
- it('should update', function() {
- if (browser.params.browser == 'safari') {
- // Safari does not understand the minus key. See
- // https://github.com/angular/protractor/issues/481
- return;
- }
- element(by.model('amount')).clear();
- element(by.model('amount')).sendKeys('-1234');
- expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
- expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('(USD$1,234.00)');
- });
- </file>
- </example>
- */
- currencyFilter.$inject = ['$locale'];
- function currencyFilter($locale) {
- var formats = $locale.NUMBER_FORMATS;
- return function(amount, currencySymbol){
- if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;
- return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).
- replace(/\u00A4/g, currencySymbol);
- };
- }
- /**
- * @ngdoc filter
- * @name number
- * @kind function
- *
- * @description
- * Formats a number as text.
- *
- * If the input is not a number an empty string is returned.
- *
- * @param {number|string} number Number to format.
- * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
- * If this is not provided then the fraction size is computed from the current locale's number
- * formatting pattern. In the case of the default locale, it will be 3.
- * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
- *
- * @example
- <example module="numberFilterExample">
- <file name="index.html">
- <script>
- angular.module('numberFilterExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.val = 1234.56789;
- }]);
- </script>
- <div ng-controller="ExampleController">
- Enter number: <input ng-model='val'><br>
- Default formatting: <span id='number-default'>{{val | number}}</span><br>
- No fractions: <span>{{val | number:0}}</span><br>
- Negative number: <span>{{-val | number:4}}</span>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should format numbers', function() {
- expect(element(by.id('number-default')).getText()).toBe('1,234.568');
- expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
- expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
- });
- it('should update', function() {
- element(by.model('val')).clear();
- element(by.model('val')).sendKeys('3374.333');
- expect(element(by.id('number-default')).getText()).toBe('3,374.333');
- expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
- expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
- });
- </file>
- </example>
- */
- numberFilter.$inject = ['$locale'];
- function numberFilter($locale) {
- var formats = $locale.NUMBER_FORMATS;
- return function(number, fractionSize) {
- return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
- fractionSize);
- };
- }
- var DECIMAL_SEP = '.';
- function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
- if (number == null || !isFinite(number) || isObject(number)) return '';
- var isNegative = number < 0;
- number = Math.abs(number);
- var numStr = number + '',
- formatedText = '',
- parts = [];
- var hasExponent = false;
- if (numStr.indexOf('e') !== -1) {
- var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
- if (match && match[2] == '-' && match[3] > fractionSize + 1) {
- numStr = '0';
- number = 0;
- } else {
- formatedText = numStr;
- hasExponent = true;
- }
- }
- if (!hasExponent) {
- var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
- // determine fractionSize if it is not specified
- if (isUndefined(fractionSize)) {
- fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
- }
- // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
- // inspired by:
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
- number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
- var fraction = ('' + number).split(DECIMAL_SEP);
- var whole = fraction[0];
- fraction = fraction[1] || '';
- var i, pos = 0,
- lgroup = pattern.lgSize,
- group = pattern.gSize;
- if (whole.length >= (lgroup + group)) {
- pos = whole.length - lgroup;
- for (i = 0; i < pos; i++) {
- if ((pos - i)%group === 0 && i !== 0) {
- formatedText += groupSep;
- }
- formatedText += whole.charAt(i);
- }
- }
- for (i = pos; i < whole.length; i++) {
- if ((whole.length - i)%lgroup === 0 && i !== 0) {
- formatedText += groupSep;
- }
- formatedText += whole.charAt(i);
- }
- // format fraction part.
- while(fraction.length < fractionSize) {
- fraction += '0';
- }
- if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
- } else {
- if (fractionSize > 0 && number > -1 && number < 1) {
- formatedText = number.toFixed(fractionSize);
- }
- }
- parts.push(isNegative ? pattern.negPre : pattern.posPre);
- parts.push(formatedText);
- parts.push(isNegative ? pattern.negSuf : pattern.posSuf);
- return parts.join('');
- }
- function padNumber(num, digits, trim) {
- var neg = '';
- if (num < 0) {
- neg = '-';
- num = -num;
- }
- num = '' + num;
- while(num.length < digits) num = '0' + num;
- if (trim)
- num = num.substr(num.length - digits);
- return neg + num;
- }
- function dateGetter(name, size, offset, trim) {
- offset = offset || 0;
- return function(date) {
- var value = date['get' + name]();
- if (offset > 0 || value > -offset)
- value += offset;
- if (value === 0 && offset == -12 ) value = 12;
- return padNumber(value, size, trim);
- };
- }
- function dateStrGetter(name, shortForm) {
- return function(date, formats) {
- var value = date['get' + name]();
- var get = uppercase(shortForm ? ('SHORT' + name) : name);
- return formats[get][value];
- };
- }
- function timeZoneGetter(date) {
- var zone = -1 * date.getTimezoneOffset();
- var paddedZone = (zone >= 0) ? "+" : "";
- paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
- padNumber(Math.abs(zone % 60), 2);
- return paddedZone;
- }
- function ampmGetter(date, formats) {
- return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
- }
- var DATE_FORMATS = {
- yyyy: dateGetter('FullYear', 4),
- yy: dateGetter('FullYear', 2, 0, true),
- y: dateGetter('FullYear', 1),
- MMMM: dateStrGetter('Month'),
- MMM: dateStrGetter('Month', true),
- MM: dateGetter('Month', 2, 1),
- M: dateGetter('Month', 1, 1),
- dd: dateGetter('Date', 2),
- d: dateGetter('Date', 1),
- HH: dateGetter('Hours', 2),
- H: dateGetter('Hours', 1),
- hh: dateGetter('Hours', 2, -12),
- h: dateGetter('Hours', 1, -12),
- mm: dateGetter('Minutes', 2),
- m: dateGetter('Minutes', 1),
- ss: dateGetter('Seconds', 2),
- s: dateGetter('Seconds', 1),
- // while ISO 8601 requires fractions to be prefixed with `.` or `,`
- // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
- sss: dateGetter('Milliseconds', 3),
- EEEE: dateStrGetter('Day'),
- EEE: dateStrGetter('Day', true),
- a: ampmGetter,
- Z: timeZoneGetter
- };
- var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
- NUMBER_STRING = /^\-?\d+$/;
- /**
- * @ngdoc filter
- * @name date
- * @kind function
- *
- * @description
- * Formats `date` to a string based on the requested `format`.
- *
- * `format` string can be composed of the following elements:
- *
- * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
- * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
- * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
- * * `'MMMM'`: Month in year (January-December)
- * * `'MMM'`: Month in year (Jan-Dec)
- * * `'MM'`: Month in year, padded (01-12)
- * * `'M'`: Month in year (1-12)
- * * `'dd'`: Day in month, padded (01-31)
- * * `'d'`: Day in month (1-31)
- * * `'EEEE'`: Day in Week,(Sunday-Saturday)
- * * `'EEE'`: Day in Week, (Sun-Sat)
- * * `'HH'`: Hour in day, padded (00-23)
- * * `'H'`: Hour in day (0-23)
- * * `'hh'`: Hour in am/pm, padded (01-12)
- * * `'h'`: Hour in am/pm, (1-12)
- * * `'mm'`: Minute in hour, padded (00-59)
- * * `'m'`: Minute in hour (0-59)
- * * `'ss'`: Second in minute, padded (00-59)
- * * `'s'`: Second in minute (0-59)
- * * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
- * * `'a'`: am/pm marker
- * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
- *
- * `format` string can also be one of the following predefined
- * {@link guide/i18n localizable formats}:
- *
- * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
- * (e.g. Sep 3, 2010 12:05:08 pm)
- * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 pm)
- * * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US locale
- * (e.g. Friday, September 3, 2010)
- * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)
- * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
- * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
- * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)
- * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)
- *
- * `format` string can contain literal values. These need to be quoted with single quotes (e.g.
- * `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence
- * (e.g. `"h 'o''clock'"`).
- *
- * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
- * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its
- * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
- * specified in the string input, the time is considered to be in the local timezone.
- * @param {string=} format Formatting rules (see Description). If not specified,
- * `mediumDate` is used.
- * @returns {string} Formatted string or the input if input is not recognized as date/millis.
- *
- * @example
- <example>
- <file name="index.html">
- <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
- <span>{{1288323623006 | date:'medium'}}</span><br>
- <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
- <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
- <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
- <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
- </file>
- <file name="protractor.js" type="protractor">
- it('should format date', function() {
- expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
- toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
- expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
- toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
- expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
- toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
- });
- </file>
- </example>
- */
- dateFilter.$inject = ['$locale'];
- function dateFilter($locale) {
- var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
- // 1 2 3 4 5 6 7 8 9 10 11
- function jsonStringToDate(string) {
- var match;
- if (match = string.match(R_ISO8601_STR)) {
- var date = new Date(0),
- tzHour = 0,
- tzMin = 0,
- dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
- timeSetter = match[8] ? date.setUTCHours : date.setHours;
- if (match[9]) {
- tzHour = int(match[9] + match[10]);
- tzMin = int(match[9] + match[11]);
- }
- dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
- var h = int(match[4]||0) - tzHour;
- var m = int(match[5]||0) - tzMin;
- var s = int(match[6]||0);
- var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);
- timeSetter.call(date, h, m, s, ms);
- return date;
- }
- return string;
- }
- return function(date, format) {
- var text = '',
- parts = [],
- fn, match;
- format = format || 'mediumDate';
- format = $locale.DATETIME_FORMATS[format] || format;
- if (isString(date)) {
- date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);
- }
- if (isNumber(date)) {
- date = new Date(date);
- }
- if (!isDate(date)) {
- return date;
- }
- while(format) {
- match = DATE_FORMATS_SPLIT.exec(format);
- if (match) {
- parts = concat(parts, match, 1);
- format = parts.pop();
- } else {
- parts.push(format);
- format = null;
- }
- }
- forEach(parts, function(value){
- fn = DATE_FORMATS[value];
- text += fn ? fn(date, $locale.DATETIME_FORMATS)
- : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
- });
- return text;
- };
- }
- /**
- * @ngdoc filter
- * @name json
- * @kind function
- *
- * @description
- * Allows you to convert a JavaScript object into JSON string.
- *
- * This filter is mostly useful for debugging. When using the double curly {{value}} notation
- * the binding is automatically converted to JSON.
- *
- * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
- * @returns {string} JSON string.
- *
- *
- * @example
- <example>
- <file name="index.html">
- <pre>{{ {'name':'value'} | json }}</pre>
- </file>
- <file name="protractor.js" type="protractor">
- it('should jsonify filtered objects', function() {
- expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n "name": ?"value"\n}/);
- });
- </file>
- </example>
- *
- */
- function jsonFilter() {
- return function(object) {
- return toJson(object, true);
- };
- }
- /**
- * @ngdoc filter
- * @name lowercase
- * @kind function
- * @description
- * Converts string to lowercase.
- * @see angular.lowercase
- */
- var lowercaseFilter = valueFn(lowercase);
- /**
- * @ngdoc filter
- * @name uppercase
- * @kind function
- * @description
- * Converts string to uppercase.
- * @see angular.uppercase
- */
- var uppercaseFilter = valueFn(uppercase);
- /**
- * @ngdoc filter
- * @name limitTo
- * @kind function
- *
- * @description
- * Creates a new array or string containing only a specified number of elements. The elements
- * are taken from either the beginning or the end of the source array or string, as specified by
- * the value and sign (positive or negative) of `limit`.
- *
- * @param {Array|string} input Source array or string to be limited.
- * @param {string|number} limit The length of the returned array or string. If the `limit` number
- * is positive, `limit` number of items from the beginning of the source array/string are copied.
- * If the number is negative, `limit` number of items from the end of the source array/string
- * are copied. The `limit` will be trimmed if it exceeds `array.length`
- * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
- * had less than `limit` elements.
- *
- * @example
- <example module="limitToExample">
- <file name="index.html">
- <script>
- angular.module('limitToExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.numbers = [1,2,3,4,5,6,7,8,9];
- $scope.letters = "abcdefghi";
- $scope.numLimit = 3;
- $scope.letterLimit = 3;
- }]);
- </script>
- <div ng-controller="ExampleController">
- Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
- <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
- Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
- <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- var numLimitInput = element(by.model('numLimit'));
- var letterLimitInput = element(by.model('letterLimit'));
- var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
- var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));
- it('should limit the number array to first three items', function() {
- expect(numLimitInput.getAttribute('value')).toBe('3');
- expect(letterLimitInput.getAttribute('value')).toBe('3');
- expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
- expect(limitedLetters.getText()).toEqual('Output letters: abc');
- });
- it('should update the output when -3 is entered', function() {
- numLimitInput.clear();
- numLimitInput.sendKeys('-3');
- letterLimitInput.clear();
- letterLimitInput.sendKeys('-3');
- expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
- expect(limitedLetters.getText()).toEqual('Output letters: ghi');
- });
- it('should not exceed the maximum size of input array', function() {
- numLimitInput.clear();
- numLimitInput.sendKeys('100');
- letterLimitInput.clear();
- letterLimitInput.sendKeys('100');
- expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
- expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
- });
- </file>
- </example>
- */
- function limitToFilter(){
- return function(input, limit) {
- if (!isArray(input) && !isString(input)) return input;
- if (Math.abs(Number(limit)) === Infinity) {
- limit = Number(limit);
- } else {
- limit = int(limit);
- }
- if (isString(input)) {
- //NaN check on limit
- if (limit) {
- return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);
- } else {
- return "";
- }
- }
- var out = [],
- i, n;
- // if abs(limit) exceeds maximum length, trim it
- if (limit > input.length)
- limit = input.length;
- else if (limit < -input.length)
- limit = -input.length;
- if (limit > 0) {
- i = 0;
- n = limit;
- } else {
- i = input.length + limit;
- n = input.length;
- }
- for (; i<n; i++) {
- out.push(input[i]);
- }
- return out;
- };
- }
- /**
- * @ngdoc filter
- * @name orderBy
- * @kind function
- *
- * @description
- * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
- * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
- * correctly, make sure they are actually being saved as numbers and not strings.
- *
- * @param {Array} array The array to sort.
- * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
- * used by the comparator to determine the order of elements.
- *
- * Can be one of:
- *
- * - `function`: Getter function. The result of this function will be sorted using the
- * `<`, `=`, `>` operator.
- * - `string`: An Angular expression which evaluates to an object to order by, such as 'name'
- * to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
- * ascending or descending sort order (for example, +name or -name).
- * - `Array`: An array of function or string predicates. The first predicate in the array
- * is used for sorting, but when two items are equivalent, the next predicate is used.
- *
- * @param {boolean=} reverse Reverse the order of the array.
- * @returns {Array} Sorted copy of the source array.
- *
- * @example
- <example module="orderByExample">
- <file name="index.html">
- <script>
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.friends =
- [{name:'John', phone:'555-1212', age:10},
- {name:'Mary', phone:'555-9876', age:19},
- {name:'Mike', phone:'555-4321', age:21},
- {name:'Adam', phone:'555-5678', age:35},
- {name:'Julie', phone:'555-8765', age:29}];
- $scope.predicate = '-age';
- }]);
- </script>
- <div ng-controller="ExampleController">
- <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
- <hr/>
- [ <a href="" ng-click="predicate=''">unsorted</a> ]
- <table class="friend">
- <tr>
- <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
- (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
- <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
- <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
- </tr>
- <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- <td>{{friend.age}}</td>
- </tr>
- </table>
- </div>
- </file>
- </example>
- *
- * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
- * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
- * desired parameters.
- *
- * Example:
- *
- * @example
- <example module="orderByExample">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <table class="friend">
- <tr>
- <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
- (<a href="" ng-click="order('-name',false)">^</a>)</th>
- <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
- <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
- </tr>
- <tr ng-repeat="friend in friends">
- <td>{{friend.name}}</td>
- <td>{{friend.phone}}</td>
- <td>{{friend.age}}</td>
- </tr>
- </table>
- </div>
- </file>
- <file name="script.js">
- angular.module('orderByExample', [])
- .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
- var orderBy = $filter('orderBy');
- $scope.friends = [
- { name: 'John', phone: '555-1212', age: 10 },
- { name: 'Mary', phone: '555-9876', age: 19 },
- { name: 'Mike', phone: '555-4321', age: 21 },
- { name: 'Adam', phone: '555-5678', age: 35 },
- { name: 'Julie', phone: '555-8765', age: 29 }
- ];
- $scope.order = function(predicate, reverse) {
- $scope.friends = orderBy($scope.friends, predicate, reverse);
- };
- $scope.order('-age',false);
- }]);
- </file>
- </example>
- */
- orderByFilter.$inject = ['$parse'];
- function orderByFilter($parse){
- return function(array, sortPredicate, reverseOrder) {
- if (!isArray(array)) return array;
- if (!sortPredicate) return array;
- sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
- sortPredicate = map(sortPredicate, function(predicate){
- var descending = false, get = predicate || identity;
- if (isString(predicate)) {
- if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
- descending = predicate.charAt(0) == '-';
- predicate = predicate.substring(1);
- }
- get = $parse(predicate);
- if (get.constant) {
- var key = get();
- return reverseComparator(function(a,b) {
- return compare(a[key], b[key]);
- }, descending);
- }
- }
- return reverseComparator(function(a,b){
- return compare(get(a),get(b));
- }, descending);
- });
- var arrayCopy = [];
- for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
- return arrayCopy.sort(reverseComparator(comparator, reverseOrder));
- function comparator(o1, o2){
- for ( var i = 0; i < sortPredicate.length; i++) {
- var comp = sortPredicate[i](o1, o2);
- if (comp !== 0) return comp;
- }
- return 0;
- }
- function reverseComparator(comp, descending) {
- return toBoolean(descending)
- ? function(a,b){return comp(b,a);}
- : comp;
- }
- function compare(v1, v2){
- var t1 = typeof v1;
- var t2 = typeof v2;
- if (t1 == t2) {
- if (isDate(v1) && isDate(v2)) {
- v1 = v1.valueOf();
- v2 = v2.valueOf();
- }
- if (t1 == "string") {
- v1 = v1.toLowerCase();
- v2 = v2.toLowerCase();
- }
- if (v1 === v2) return 0;
- return v1 < v2 ? -1 : 1;
- } else {
- return t1 < t2 ? -1 : 1;
- }
- }
- };
- }
- function ngDirective(directive) {
- if (isFunction(directive)) {
- directive = {
- link: directive
- };
- }
- directive.restrict = directive.restrict || 'AC';
- return valueFn(directive);
- }
- var htmlAnchorDirective = valueFn({
- restrict: 'E',
- compile: function(element, attr) {
- if (msie <= 8) {
-
-
- if (!attr.href && !attr.name) {
- attr.$set('href', '');
- }
- // add a comment node to anchors to workaround IE bug that causes element content to be reset
- // to new attribute content if attribute is updated with value containing @ and element also
- // contains value with @
- // see issue #1949
- element.append(document.createComment('IE fix'));
- }
- if (!attr.href && !attr.xlinkHref && !attr.name) {
- return function(scope, element) {
-
- var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
- 'xlink:href' : 'href';
- element.on('click', function(event){
-
- if (!element.attr(href)) {
- event.preventDefault();
- }
- });
- };
- }
- }
- });
- var ngAttributeAliasDirectives = {};
- forEach(BOOLEAN_ATTR, function(propName, attrName) {
-
- if (propName == "multiple") return;
- var normalized = directiveNormalize('ng-' + attrName);
- ngAttributeAliasDirectives[normalized] = function() {
- return {
- priority: 100,
- link: function(scope, element, attr) {
- scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
- attr.$set(attrName, !!value);
- });
- }
- };
- };
- });
- // ng-src, ng-srcset, ng-href are interpolated
- forEach(['src', 'srcset', 'href'], function(attrName) {
- var normalized = directiveNormalize('ng-' + attrName);
- ngAttributeAliasDirectives[normalized] = function() {
- return {
- priority: 99,
- link: function(scope, element, attr) {
- var propName = attrName,
- name = attrName;
- if (attrName === 'href' &&
- toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
- name = 'xlinkHref';
- attr.$attr[name] = 'xlink:href';
- propName = null;
- }
- attr.$observe(normalized, function(value) {
- if (!value)
- return;
- attr.$set(name, value);
- // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
- // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
- // to set the property as well to achieve the desired effect.
- // we use attr[attrName] value since $set can sanitize the url.
- if (msie && propName) element.prop(propName, attr[name]);
- });
- }
- };
- };
- });
- /* global -nullFormCtrl */
- var nullFormCtrl = {
- $addControl: noop,
- $removeControl: noop,
- $setValidity: noop,
- $setDirty: noop,
- $setPristine: noop
- };
- FormController.$inject = ['$element', '$attrs', '$scope', '$animate'];
- function FormController(element, attrs, $scope, $animate) {
- var form = this,
- parentForm = element.parent().controller('form') || nullFormCtrl,
- invalidCount = 0,
- errors = form.$error = {},
- controls = [];
-
- form.$name = attrs.name || attrs.ngForm;
- form.$dirty = false;
- form.$pristine = true;
- form.$valid = true;
- form.$invalid = false;
- parentForm.$addControl(form);
-
- element.addClass(PRISTINE_CLASS);
- toggleValidCss(true);
-
- function toggleValidCss(isValid, validationErrorKey) {
- validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
- $animate.removeClass(element, (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
- $animate.addClass(element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
- }
-
- form.$addControl = function(control) {
-
-
- assertNotHasOwnProperty(control.$name, 'input');
- controls.push(control);
- if (control.$name) {
- form[control.$name] = control;
- }
- };
-
- form.$removeControl = function(control) {
- if (control.$name && form[control.$name] === control) {
- delete form[control.$name];
- }
- forEach(errors, function(queue, validationToken) {
- form.$setValidity(validationToken, true, control);
- });
- arrayRemove(controls, control);
- };
-
- form.$setValidity = function(validationToken, isValid, control) {
- var queue = errors[validationToken];
- if (isValid) {
- if (queue) {
- arrayRemove(queue, control);
- if (!queue.length) {
- invalidCount--;
- if (!invalidCount) {
- toggleValidCss(isValid);
- form.$valid = true;
- form.$invalid = false;
- }
- errors[validationToken] = false;
- toggleValidCss(true, validationToken);
- parentForm.$setValidity(validationToken, true, form);
- }
- }
- } else {
- if (!invalidCount) {
- toggleValidCss(isValid);
- }
- if (queue) {
- if (includes(queue, control)) return;
- } else {
- errors[validationToken] = queue = [];
- invalidCount++;
- toggleValidCss(false, validationToken);
- parentForm.$setValidity(validationToken, false, form);
- }
- queue.push(control);
- form.$valid = false;
- form.$invalid = true;
- }
- };
-
- form.$setDirty = function() {
- $animate.removeClass(element, PRISTINE_CLASS);
- $animate.addClass(element, DIRTY_CLASS);
- form.$dirty = true;
- form.$pristine = false;
- parentForm.$setDirty();
- };
-
- form.$setPristine = function () {
- $animate.removeClass(element, DIRTY_CLASS);
- $animate.addClass(element, PRISTINE_CLASS);
- form.$dirty = false;
- form.$pristine = true;
- forEach(controls, function(control) {
- control.$setPristine();
- });
- };
- }
-
- var formDirectiveFactory = function(isNgForm) {
- return ['$timeout', function($timeout) {
- var formDirective = {
- name: 'form',
- restrict: isNgForm ? 'EAC' : 'E',
- controller: FormController,
- compile: function() {
- return {
- pre: function(scope, formElement, attr, controller) {
- if (!attr.action) {
-
-
-
-
-
-
- var preventDefaultListener = function(event) {
- event.preventDefault
- ? event.preventDefault()
- : event.returnValue = false;
- };
- addEventListenerFn(formElement[0], 'submit', preventDefaultListener);
-
-
- formElement.on('$destroy', function() {
- $timeout(function() {
- removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);
- }, 0, false);
- });
- }
- var parentFormCtrl = formElement.parent().controller('form'),
- alias = attr.name || attr.ngForm;
- if (alias) {
- setter(scope, alias, controller, alias);
- }
- if (parentFormCtrl) {
- formElement.on('$destroy', function() {
- parentFormCtrl.$removeControl(controller);
- if (alias) {
- setter(scope, alias, undefined, alias);
- }
- extend(controller, nullFormCtrl);
- });
- }
- }
- };
- }
- };
- return formDirective;
- }];
- };
- var formDirective = formDirectiveFactory();
- var ngFormDirective = formDirectiveFactory(true);
- var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
- var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
- var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
- var inputType = {
-
- 'text': textInputType,
-
- 'number': numberInputType,
-
- 'url': urlInputType,
-
- 'email': emailInputType,
-
- 'radio': radioInputType,
-
- 'checkbox': checkboxInputType,
- 'hidden': noop,
- 'button': noop,
- 'submit': noop,
- 'reset': noop,
- 'file': noop
- };
- function validate(ctrl, validatorName, validity, value){
- ctrl.$setValidity(validatorName, validity);
- return validity ? value : undefined;
- }
- function testFlags(validity, flags) {
- var i, flag;
- if (flags) {
- for (i=0; i<flags.length; ++i) {
- flag = flags[i];
- if (validity[flag]) {
- return true;
- }
- }
- }
- return false;
- }
- function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, validity) {
- if (isObject(validity)) {
- ctrl.$$hasNativeValidators = true;
- var validator = function(value) {
-
-
- if (!ctrl.$error[validatorName] &&
- !testFlags(validity, ignoreFlags) &&
- testFlags(validity, badFlags)) {
- ctrl.$setValidity(validatorName, false);
- return;
- }
- return value;
- };
- ctrl.$parsers.push(validator);
- }
- }
- function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- var validity = element.prop(VALIDITY_STATE_PROPERTY);
- var placeholder = element[0].placeholder, noevent = {};
- ctrl.$$validityState = validity;
-
-
-
- if (!$sniffer.android) {
- var composing = false;
- element.on('compositionstart', function(data) {
- composing = true;
- });
- element.on('compositionend', function() {
- composing = false;
- listener();
- });
- }
- var listener = function(ev) {
- if (composing) return;
- var value = element.val();
-
-
-
-
- if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {
- placeholder = element[0].placeholder;
- return;
- }
-
-
-
- if (toBoolean(attr.ngTrim || 'T')) {
- value = trim(value);
- }
-
-
-
- var revalidate = validity && ctrl.$$hasNativeValidators;
- if (ctrl.$viewValue !== value || (value === '' && revalidate)) {
- if (scope.$$phase) {
- ctrl.$setViewValue(value);
- } else {
- scope.$apply(function() {
- ctrl.$setViewValue(value);
- });
- }
- }
- };
-
-
- if ($sniffer.hasEvent('input')) {
- element.on('input', listener);
- } else {
- var timeout;
- var deferListener = function() {
- if (!timeout) {
- timeout = $browser.defer(function() {
- listener();
- timeout = null;
- });
- }
- };
- element.on('keydown', function(event) {
- var key = event.keyCode;
-
-
- if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
- deferListener();
- });
-
- if ($sniffer.hasEvent('paste')) {
- element.on('paste cut', deferListener);
- }
- }
-
-
- element.on('change', listener);
- ctrl.$render = function() {
- element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
- };
-
- var pattern = attr.ngPattern,
- patternValidator,
- match;
- if (pattern) {
- var validateRegex = function(regexp, value) {
- return validate(ctrl, 'pattern', ctrl.$isEmpty(value) || regexp.test(value), value);
- };
- match = pattern.match(/^\/(.*)\/([gim]*)$/);
- if (match) {
- pattern = new RegExp(match[1], match[2]);
- patternValidator = function(value) {
- return validateRegex(pattern, value);
- };
- } else {
- patternValidator = function(value) {
- var patternObj = scope.$eval(pattern);
- if (!patternObj || !patternObj.test) {
- throw minErr('ngPattern')('noregexp',
- 'Expected {0} to be a RegExp but was {1}. Element: {2}', pattern,
- patternObj, startingTag(element));
- }
- return validateRegex(patternObj, value);
- };
- }
- ctrl.$formatters.push(patternValidator);
- ctrl.$parsers.push(patternValidator);
- }
-
- if (attr.ngMinlength) {
- var minlength = int(attr.ngMinlength);
- var minLengthValidator = function(value) {
- return validate(ctrl, 'minlength', ctrl.$isEmpty(value) || value.length >= minlength, value);
- };
- ctrl.$parsers.push(minLengthValidator);
- ctrl.$formatters.push(minLengthValidator);
- }
-
- if (attr.ngMaxlength) {
- var maxlength = int(attr.ngMaxlength);
- var maxLengthValidator = function(value) {
- return validate(ctrl, 'maxlength', ctrl.$isEmpty(value) || value.length <= maxlength, value);
- };
- ctrl.$parsers.push(maxLengthValidator);
- ctrl.$formatters.push(maxLengthValidator);
- }
- }
- var numberBadFlags = ['badInput'];
- function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- textInputType(scope, element, attr, ctrl, $sniffer, $browser);
- ctrl.$parsers.push(function(value) {
- var empty = ctrl.$isEmpty(value);
- if (empty || NUMBER_REGEXP.test(value)) {
- ctrl.$setValidity('number', true);
- return value === '' ? null : (empty ? value : parseFloat(value));
- } else {
- ctrl.$setValidity('number', false);
- return undefined;
- }
- });
- addNativeHtml5Validators(ctrl, 'number', numberBadFlags, null, ctrl.$$validityState);
- ctrl.$formatters.push(function(value) {
- return ctrl.$isEmpty(value) ? '' : '' + value;
- });
- if (attr.min) {
- var minValidator = function(value) {
- var min = parseFloat(attr.min);
- return validate(ctrl, 'min', ctrl.$isEmpty(value) || value >= min, value);
- };
- ctrl.$parsers.push(minValidator);
- ctrl.$formatters.push(minValidator);
- }
- if (attr.max) {
- var maxValidator = function(value) {
- var max = parseFloat(attr.max);
- return validate(ctrl, 'max', ctrl.$isEmpty(value) || value <= max, value);
- };
- ctrl.$parsers.push(maxValidator);
- ctrl.$formatters.push(maxValidator);
- }
- ctrl.$formatters.push(function(value) {
- return validate(ctrl, 'number', ctrl.$isEmpty(value) || isNumber(value), value);
- });
- }
- function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- textInputType(scope, element, attr, ctrl, $sniffer, $browser);
- var urlValidator = function(value) {
- return validate(ctrl, 'url', ctrl.$isEmpty(value) || URL_REGEXP.test(value), value);
- };
- ctrl.$formatters.push(urlValidator);
- ctrl.$parsers.push(urlValidator);
- }
- function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
- textInputType(scope, element, attr, ctrl, $sniffer, $browser);
- var emailValidator = function(value) {
- return validate(ctrl, 'email', ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value), value);
- };
- ctrl.$formatters.push(emailValidator);
- ctrl.$parsers.push(emailValidator);
- }
- function radioInputType(scope, element, attr, ctrl) {
-
- if (isUndefined(attr.name)) {
- element.attr('name', nextUid());
- }
- element.on('click', function() {
- if (element[0].checked) {
- scope.$apply(function() {
- ctrl.$setViewValue(attr.value);
- });
- }
- });
- ctrl.$render = function() {
- var value = attr.value;
- element[0].checked = (value == ctrl.$viewValue);
- };
- attr.$observe('value', ctrl.$render);
- }
- function checkboxInputType(scope, element, attr, ctrl) {
- var trueValue = attr.ngTrueValue,
- falseValue = attr.ngFalseValue;
- if (!isString(trueValue)) trueValue = true;
- if (!isString(falseValue)) falseValue = false;
- element.on('click', function() {
- scope.$apply(function() {
- ctrl.$setViewValue(element[0].checked);
- });
- });
- ctrl.$render = function() {
- element[0].checked = ctrl.$viewValue;
- };
-
- ctrl.$isEmpty = function(value) {
- return value !== trueValue;
- };
- ctrl.$formatters.push(function(value) {
- return value === trueValue;
- });
- ctrl.$parsers.push(function(value) {
- return value ? trueValue : falseValue;
- });
- }
- var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {
- return {
- restrict: 'E',
- require: '?ngModel',
- link: function(scope, element, attr, ctrl) {
- if (ctrl) {
- (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,
- $browser);
- }
- }
- };
- }];
- var VALID_CLASS = 'ng-valid',
- INVALID_CLASS = 'ng-invalid',
- PRISTINE_CLASS = 'ng-pristine',
- DIRTY_CLASS = 'ng-dirty';
- var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate',
- function($scope, $exceptionHandler, $attr, $element, $parse, $animate) {
- this.$viewValue = Number.NaN;
- this.$modelValue = Number.NaN;
- this.$parsers = [];
- this.$formatters = [];
- this.$viewChangeListeners = [];
- this.$pristine = true;
- this.$dirty = false;
- this.$valid = true;
- this.$invalid = false;
- this.$name = $attr.name;
- var ngModelGet = $parse($attr.ngModel),
- ngModelSet = ngModelGet.assign;
- if (!ngModelSet) {
- throw minErr('ngModel')('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
- $attr.ngModel, startingTag($element));
- }
-
- this.$render = noop;
-
- this.$isEmpty = function(value) {
- return isUndefined(value) || value === '' || value === null || value !== value;
- };
- var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
- invalidCount = 0,
- $error = this.$error = {};
-
- $element.addClass(PRISTINE_CLASS);
- toggleValidCss(true);
-
- function toggleValidCss(isValid, validationErrorKey) {
- validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
- $animate.removeClass($element, (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);
- $animate.addClass($element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
- }
-
- this.$setValidity = function(validationErrorKey, isValid) {
-
-
- if ($error[validationErrorKey] === !isValid) return;
-
- if (isValid) {
- if ($error[validationErrorKey]) invalidCount--;
- if (!invalidCount) {
- toggleValidCss(true);
- this.$valid = true;
- this.$invalid = false;
- }
- } else {
- toggleValidCss(false);
- this.$invalid = true;
- this.$valid = false;
- invalidCount++;
- }
- $error[validationErrorKey] = !isValid;
- toggleValidCss(isValid, validationErrorKey);
- parentForm.$setValidity(validationErrorKey, isValid, this);
- };
-
- this.$setPristine = function () {
- this.$dirty = false;
- this.$pristine = true;
- $animate.removeClass($element, DIRTY_CLASS);
- $animate.addClass($element, PRISTINE_CLASS);
- };
-
- this.$setViewValue = function(value) {
- this.$viewValue = value;
-
- if (this.$pristine) {
- this.$dirty = true;
- this.$pristine = false;
- $animate.removeClass($element, PRISTINE_CLASS);
- $animate.addClass($element, DIRTY_CLASS);
- parentForm.$setDirty();
- }
- forEach(this.$parsers, function(fn) {
- value = fn(value);
- });
- if (this.$modelValue !== value) {
- this.$modelValue = value;
- ngModelSet($scope, value);
- forEach(this.$viewChangeListeners, function(listener) {
- try {
- listener();
- } catch(e) {
- $exceptionHandler(e);
- }
- });
- }
- };
-
- var ctrl = this;
- $scope.$watch(function ngModelWatch() {
- var value = ngModelGet($scope);
-
- if (ctrl.$modelValue !== value) {
- var formatters = ctrl.$formatters,
- idx = formatters.length;
- ctrl.$modelValue = value;
- while(idx--) {
- value = formatters[idx](value);
- }
- if (ctrl.$viewValue !== value) {
- ctrl.$viewValue = value;
- ctrl.$render();
- }
- }
- return value;
- });
- }];
- var ngModelDirective = function() {
- return {
- require: ['ngModel', '^?form'],
- controller: NgModelController,
- link: function(scope, element, attr, ctrls) {
-
- var modelCtrl = ctrls[0],
- formCtrl = ctrls[1] || nullFormCtrl;
- formCtrl.$addControl(modelCtrl);
- scope.$on('$destroy', function() {
- formCtrl.$removeControl(modelCtrl);
- });
- }
- };
- };
- var ngChangeDirective = valueFn({
- require: 'ngModel',
- link: function(scope, element, attr, ctrl) {
- ctrl.$viewChangeListeners.push(function() {
- scope.$eval(attr.ngChange);
- });
- }
- });
- var requiredDirective = function() {
- return {
- require: '?ngModel',
- link: function(scope, elm, attr, ctrl) {
- if (!ctrl) return;
- attr.required = true;
- var validator = function(value) {
- if (attr.required && ctrl.$isEmpty(value)) {
- ctrl.$setValidity('required', false);
- return;
- } else {
- ctrl.$setValidity('required', true);
- return value;
- }
- };
- ctrl.$formatters.push(validator);
- ctrl.$parsers.unshift(validator);
- attr.$observe('required', function() {
- validator(ctrl.$viewValue);
- });
- }
- };
- };
- var ngListDirective = function() {
- return {
- require: 'ngModel',
- link: function(scope, element, attr, ctrl) {
- var match = /\/(.*)\//.exec(attr.ngList),
- separator = match && new RegExp(match[1]) || attr.ngList || ',';
- var parse = function(viewValue) {
-
- if (isUndefined(viewValue)) return;
- var list = [];
- if (viewValue) {
- forEach(viewValue.split(separator), function(value) {
- if (value) list.push(trim(value));
- });
- }
- return list;
- };
- ctrl.$parsers.push(parse);
- ctrl.$formatters.push(function(value) {
- if (isArray(value)) {
- return value.join(', ');
- }
- return undefined;
- });
-
- ctrl.$isEmpty = function(value) {
- return !value || !value.length;
- };
- }
- };
- };
- var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
- var ngValueDirective = function() {
- return {
- priority: 100,
- compile: function(tpl, tplAttr) {
- if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
- return function ngValueConstantLink(scope, elm, attr) {
- attr.$set('value', scope.$eval(attr.ngValue));
- };
- } else {
- return function ngValueLink(scope, elm, attr) {
- scope.$watch(attr.ngValue, function valueWatchAction(value) {
- attr.$set('value', value);
- });
- };
- }
- }
- };
- };
- /**
- * @ngdoc directive
- * @name ngBind
- * @restrict AC
- *
- * @description
- * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
- * with the value of a given expression, and to update the text content when the value of that
- * expression changes.
- *
- * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
- * `{{ expression }}` which is similar but less verbose.
- *
- * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
- * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
- * element attribute, it makes the bindings invisible to the user while the page is loading.
- *
- * An alternative solution to this problem would be using the
- * {@link ng.directive:ngCloak ngCloak} directive.
- *
- *
- * @element ANY
- * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
- *
- * @example
- * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
- <example module="bindExample">
- <file name="index.html">
- <script>
- angular.module('bindExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.name = 'Whirled';
- }]);
- </script>
- <div ng-controller="ExampleController">
- Enter name: <input type="text" ng-model="name"><br>
- Hello <span ng-bind="name"></span>!
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-bind', function() {
- var nameInput = element(by.model('name'));
- expect(element(by.binding('name')).getText()).toBe('Whirled');
- nameInput.clear();
- nameInput.sendKeys('world');
- expect(element(by.binding('name')).getText()).toBe('world');
- });
- </file>
- </example>
- */
- var ngBindDirective = ngDirective({
- compile: function(templateElement) {
- templateElement.addClass('ng-binding');
- return function (scope, element, attr) {
- element.data('$binding', attr.ngBind);
- scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
- // We are purposefully using == here rather than === because we want to
- // catch when value is "null or undefined"
- // jshint -W041
- element.text(value == undefined ? '' : value);
- });
- };
- }
- });
- /**
- * @ngdoc directive
- * @name ngBindTemplate
- *
- * @description
- * The `ngBindTemplate` directive specifies that the element
- * text content should be replaced with the interpolation of the template
- * in the `ngBindTemplate` attribute.
- * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
- * expressions. This directive is needed since some HTML elements
- * (such as TITLE and OPTION) cannot contain SPAN elements.
- *
- * @element ANY
- * @param {string} ngBindTemplate template of form
- * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
- *
- * @example
- * Try it here: enter text in text box and watch the greeting change.
- <example module="bindExample">
- <file name="index.html">
- <script>
- angular.module('bindExample', [])
- .controller('ExampleController', ['$scope', function ($scope) {
- $scope.salutation = 'Hello';
- $scope.name = 'World';
- }]);
- </script>
- <div ng-controller="ExampleController">
- Salutation: <input type="text" ng-model="salutation"><br>
- Name: <input type="text" ng-model="name"><br>
- <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
- </div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-bind', function() {
- var salutationElem = element(by.binding('salutation'));
- var salutationInput = element(by.model('salutation'));
- var nameInput = element(by.model('name'));
- expect(salutationElem.getText()).toBe('Hello World!');
- salutationInput.clear();
- salutationInput.sendKeys('Greetings');
- nameInput.clear();
- nameInput.sendKeys('user');
- expect(salutationElem.getText()).toBe('Greetings user!');
- });
- </file>
- </example>
- */
- var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
- return function(scope, element, attr) {
- // TODO: move this to scenario runner
- var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
- element.addClass('ng-binding').data('$binding', interpolateFn);
- attr.$observe('ngBindTemplate', function(value) {
- element.text(value);
- });
- };
- }];
- /**
- * @ngdoc directive
- * @name ngBindHtml
- *
- * @description
- * Creates a binding that will innerHTML the result of evaluating the `expression` into the current
- * element in a secure way. By default, the innerHTML-ed content will be sanitized using the {@link
- * ngSanitize.$sanitize $sanitize} service. To utilize this functionality, ensure that `$sanitize`
- * is available, for example, by including {@link ngSanitize} in your module's dependencies (not in
- * core Angular.) You may also bypass sanitization for values you know are safe. To do so, bind to
- * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example
- * under {@link ng.$sce#Example Strict Contextual Escaping (SCE)}.
- *
- * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
- * will have an exception (instead of an exploit.)
- *
- * @element ANY
- * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
- *
- * @example
- Try it here: enter text in text box and watch the greeting change.
- <example module="bindHtmlExample" deps="angular-sanitize.js">
- <file name="index.html">
- <div ng-controller="ExampleController">
- <p ng-bind-html="myHTML"></p>
- </div>
- </file>
- <file name="script.js">
- angular.module('bindHtmlExample', ['ngSanitize'])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.myHTML =
- 'I am an <code>HTML</code>string with ' +
- '<a href="#">links!</a> and other <em>stuff</em>';
- }]);
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-bind-html', function() {
- expect(element(by.binding('myHTML')).getText()).toBe(
- 'I am an HTMLstring with links! and other stuff');
- });
- </file>
- </example>
- */
- var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {
- return {
- compile: function (tElement) {
- tElement.addClass('ng-binding');
- return function (scope, element, attr) {
- element.data('$binding', attr.ngBindHtml);
- var parsed = $parse(attr.ngBindHtml);
- function getStringValue() {
- return (parsed(scope) || '').toString();
- }
- scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {
- element.html($sce.getTrustedHtml(parsed(scope)) || '');
- });
- };
- }
- };
- }];
- function classDirective(name, selector) {
- name = 'ngClass' + name;
- return ['$animate', function($animate) {
- return {
- restrict: 'AC',
- link: function(scope, element, attr) {
- var oldVal;
- scope.$watch(attr[name], ngClassWatchAction, true);
- attr.$observe('class', function(value) {
- ngClassWatchAction(scope.$eval(attr[name]));
- });
- if (name !== 'ngClass') {
- scope.$watch('$index', function($index, old$index) {
- // jshint bitwise: false
- var mod = $index & 1;
- if (mod !== (old$index & 1)) {
- var classes = arrayClasses(scope.$eval(attr[name]));
- mod === selector ?
- addClasses(classes) :
- removeClasses(classes);
- }
- });
- }
- function addClasses(classes) {
- var newClasses = digestClassCounts(classes, 1);
- attr.$addClass(newClasses);
- }
- function removeClasses(classes) {
- var newClasses = digestClassCounts(classes, -1);
- attr.$removeClass(newClasses);
- }
- function digestClassCounts (classes, count) {
- var classCounts = element.data('$classCounts') || {};
- var classesToUpdate = [];
- forEach(classes, function (className) {
- if (count > 0 || classCounts[className]) {
- classCounts[className] = (classCounts[className] || 0) + count;
- if (classCounts[className] === +(count > 0)) {
- classesToUpdate.push(className);
- }
- }
- });
- element.data('$classCounts', classCounts);
- return classesToUpdate.join(' ');
- }
- function updateClasses (oldClasses, newClasses) {
- var toAdd = arrayDifference(newClasses, oldClasses);
- var toRemove = arrayDifference(oldClasses, newClasses);
- toRemove = digestClassCounts(toRemove, -1);
- toAdd = digestClassCounts(toAdd, 1);
- if (toAdd.length === 0) {
- $animate.removeClass(element, toRemove);
- } else if (toRemove.length === 0) {
- $animate.addClass(element, toAdd);
- } else {
- $animate.setClass(element, toAdd, toRemove);
- }
- }
- function ngClassWatchAction(newVal) {
- if (selector === true || scope.$index % 2 === selector) {
- var newClasses = arrayClasses(newVal || []);
- if (!oldVal) {
- addClasses(newClasses);
- } else if (!equals(newVal,oldVal)) {
- var oldClasses = arrayClasses(oldVal);
- updateClasses(oldClasses, newClasses);
- }
- }
- oldVal = shallowCopy(newVal);
- }
- }
- };
- function arrayDifference(tokens1, tokens2) {
- var values = [];
- outer:
- for(var i = 0; i < tokens1.length; i++) {
- var token = tokens1[i];
- for(var j = 0; j < tokens2.length; j++) {
- if(token == tokens2[j]) continue outer;
- }
- values.push(token);
- }
- return values;
- }
- function arrayClasses (classVal) {
- if (isArray(classVal)) {
- return classVal;
- } else if (isString(classVal)) {
- return classVal.split(' ');
- } else if (isObject(classVal)) {
- var classes = [], i = 0;
- forEach(classVal, function(v, k) {
- if (v) {
- classes = classes.concat(k.split(' '));
- }
- });
- return classes;
- }
- return classVal;
- }
- }];
- }
- /**
- * @ngdoc directive
- * @name ngClass
- * @restrict AC
- *
- * @description
- * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
- * an expression that represents all classes to be added.
- *
- * The directive operates in three different ways, depending on which of three types the expression
- * evaluates to:
- *
- * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
- * names.
- *
- * 2. If the expression evaluates to an array, each element of the array should be a string that is
- * one or more space-delimited class names.
- *
- * 3. If the expression evaluates to an object, then for each key-value pair of the
- * object with a truthy value the corresponding key is used as a class name.
- *
- * The directive won't add duplicate classes if a particular class was already set.
- *
- * When the expression changes, the previously added classes are removed and only then the
- * new classes are added.
- *
- * @animations
- * add - happens just before the class is applied to the element
- * remove - happens just before the class is removed from the element
- *
- * @element ANY
- * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
- * of the evaluation can be a string representing space delimited class
- * names, an array, or a map of class names to boolean values. In the case of a map, the
- * names of the properties whose values are truthy will be added as css classes to the
- * element.
- *
- * @example Example that demonstrates basic bindings via ngClass directive.
- <example>
- <file name="index.html">
- <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
- <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br>
- <input type="checkbox" ng-model="important"> important (apply "bold" class)<br>
- <input type="checkbox" ng-model="error"> error (apply "red" class)
- <hr>
- <p ng-class="style">Using String Syntax</p>
- <input type="text" ng-model="style" placeholder="Type: bold strike red">
- <hr>
- <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
- <input ng-model="style1" placeholder="Type: bold, strike or red"><br>
- <input ng-model="style2" placeholder="Type: bold, strike or red"><br>
- <input ng-model="style3" placeholder="Type: bold, strike or red"><br>
- </file>
- <file name="style.css">
- .strike {
- text-decoration: line-through;
- }
- .bold {
- font-weight: bold;
- }
- .red {
- color: red;
- }
- </file>
- <file name="protractor.js" type="protractor">
- var ps = element.all(by.css('p'));
- it('should let you toggle the class', function() {
- expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
- expect(ps.first().getAttribute('class')).not.toMatch(/red/);
- element(by.model('important')).click();
- expect(ps.first().getAttribute('class')).toMatch(/bold/);
- element(by.model('error')).click();
- expect(ps.first().getAttribute('class')).toMatch(/red/);
- });
- it('should let you toggle string example', function() {
- expect(ps.get(1).getAttribute('class')).toBe('');
- element(by.model('style')).clear();
- element(by.model('style')).sendKeys('red');
- expect(ps.get(1).getAttribute('class')).toBe('red');
- });
- it('array example should have 3 classes', function() {
- expect(ps.last().getAttribute('class')).toBe('');
- element(by.model('style1')).sendKeys('bold');
- element(by.model('style2')).sendKeys('strike');
- element(by.model('style3')).sendKeys('red');
- expect(ps.last().getAttribute('class')).toBe('bold strike red');
- });
- </file>
- </example>
- ## Animations
- The example below demonstrates how to perform animations using ngClass.
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
- <file name="index.html">
- <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
- <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
- <br>
- <span class="base-class" ng-class="myVar">Sample Text</span>
- </file>
- <file name="style.css">
- .base-class {
- -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
- }
- .base-class.my-class {
- color: red;
- font-size:3em;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class', function() {
- expect(element(by.css('.base-class')).getAttribute('class')).not.
- toMatch(/my-class/);
- element(by.id('setbtn')).click();
- expect(element(by.css('.base-class')).getAttribute('class')).
- toMatch(/my-class/);
- element(by.id('clearbtn')).click();
- expect(element(by.css('.base-class')).getAttribute('class')).not.
- toMatch(/my-class/);
- });
- </file>
- </example>
- ## ngClass and pre-existing CSS3 Transitions/Animations
- The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
- Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
- any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
- to view the step by step details of {@link ngAnimate.$animate#addclass $animate.addClass} and
- {@link ngAnimate.$animate#removeclass $animate.removeClass}.
- */
- var ngClassDirective = classDirective('', true);
- /**
- * @ngdoc directive
- * @name ngClassOdd
- * @restrict AC
- *
- * @description
- * The `ngClassOdd` and `ngClassEven` directives work exactly as
- * {@link ng.directive:ngClass ngClass}, except they work in
- * conjunction with `ngRepeat` and take effect only on odd (even) rows.
- *
- * This directive can be applied only within the scope of an
- * {@link ng.directive:ngRepeat ngRepeat}.
- *
- * @element ANY
- * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
- * of the evaluation can be a string representing space delimited class names or an array.
- *
- * @example
- <example>
- <file name="index.html">
- <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
- <li ng-repeat="name in names">
- <span ng-class-odd="'odd'" ng-class-even="'even'">
- {{name}}
- </span>
- </li>
- </ol>
- </file>
- <file name="style.css">
- .odd {
- color: red;
- }
- .even {
- color: blue;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class-odd and ng-class-even', function() {
- expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
- toMatch(/odd/);
- expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
- toMatch(/even/);
- });
- </file>
- </example>
- */
- var ngClassOddDirective = classDirective('Odd', 0);
- /**
- * @ngdoc directive
- * @name ngClassEven
- * @restrict AC
- *
- * @description
- * The `ngClassOdd` and `ngClassEven` directives work exactly as
- * {@link ng.directive:ngClass ngClass}, except they work in
- * conjunction with `ngRepeat` and take effect only on odd (even) rows.
- *
- * This directive can be applied only within the scope of an
- * {@link ng.directive:ngRepeat ngRepeat}.
- *
- * @element ANY
- * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
- * result of the evaluation can be a string representing space delimited class names or an array.
- *
- * @example
- <example>
- <file name="index.html">
- <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
- <li ng-repeat="name in names">
- <span ng-class-odd="'odd'" ng-class-even="'even'">
- {{name}}
- </span>
- </li>
- </ol>
- </file>
- <file name="style.css">
- .odd {
- color: red;
- }
- .even {
- color: blue;
- }
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-class-odd and ng-class-even', function() {
- expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
- toMatch(/odd/);
- expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
- toMatch(/even/);
- });
- </file>
- </example>
- */
- var ngClassEvenDirective = classDirective('Even', 1);
- /**
- * @ngdoc directive
- * @name ngCloak
- * @restrict AC
- *
- * @description
- * The `ngCloak` directive is used to prevent the Angular html template from being briefly
- * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
- * directive to avoid the undesirable flicker effect caused by the html template display.
- *
- * The directive can be applied to the `<body>` element, but the preferred usage is to apply
- * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
- * of the browser view.
- *
- * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
- * `angular.min.js`.
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * ```css
- * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
- * display: none !important;
- * }
- * ```
- *
- * When this css rule is loaded by the browser, all html elements (including their children) that
- * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
- * during the compilation of the template it deletes the `ngCloak` element attribute, making
- * the compiled element visible.
- *
- * For the best result, the `angular.js` script must be loaded in the head section of the html
- * document; alternatively, the css rule above must be included in the external stylesheet of the
- * application.
- *
- * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
- * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
- * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.
- *
- * @element ANY
- *
- * @example
- <example>
- <file name="index.html">
- <div id="template1" ng-cloak>{{ 'hello' }}</div>
- <div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div>
- </file>
- <file name="protractor.js" type="protractor">
- it('should remove the template directive and css class', function() {
- expect($('#template1').getAttribute('ng-cloak')).
- toBeNull();
- expect($('#template2').getAttribute('ng-cloak')).
- toBeNull();
- });
- </file>
- </example>
- *
- */
- var ngCloakDirective = ngDirective({
- compile: function(element, attr) {
- attr.$set('ngCloak', undefined);
- element.removeClass('ng-cloak');
- }
- });
- /**
- * @ngdoc directive
- * @name ngController
- *
- * @description
- * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
- * supports the principles behind the Model-View-Controller design pattern.
- *
- * MVC components in angular:
- *
- * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
- * are accessed through bindings.
- * * View — The template (HTML with data bindings) that is rendered into the View.
- * * Controller — The `ngController` directive specifies a Controller class; the class contains business
- * logic behind the application to decorate the scope with functions and values
- *
- * Note that you can also attach controllers to the DOM by declaring it in a route definition
- * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
- * again using `ng-controller` in the template itself. This will cause the controller to be attached
- * and executed twice.
- *
- * @element ANY
- * @scope
- * @param {expression} ngController Name of a globally accessible constructor function or an
- * {@link guide/expression expression} that on the current scope evaluates to a
- * constructor function. The controller instance can be published into a scope property
- * by specifying `as propertyName`.
- *
- * @example
- * Here is a simple form for editing user contact information. Adding, removing, clearing, and
- * greeting are methods declared on the controller (see source tab). These methods can
- * easily be called from the angular markup. Any changes to the data are automatically reflected
- * in the View without the need for a manual update.
- *
- * Two different declaration styles are included below:
- *
- * * one binds methods and properties directly onto the controller using `this`:
- * `ng-controller="SettingsController1 as settings"`
- * * one injects `$scope` into the controller:
- * `ng-controller="SettingsController2"`
- *
- * The second option is more common in the Angular community, and is generally used in boilerplates
- * and in this guide. However, there are advantages to binding properties directly to the controller
- * and avoiding scope.
- *
- * * Using `controller as` makes it obvious which controller you are accessing in the template when
- * multiple controllers apply to an element.
- * * If you are writing your controllers as classes you have easier access to the properties and
- * methods, which will appear on the scope, from inside the controller code.
- * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
- * inheritance masking primitives.
- *
- * This example demonstrates the `controller as` syntax.
- *
- * <example name="ngControllerAs" module="controllerAsExample">
- * <file name="index.html">
- * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
- * Name: <input type="text" ng-model="settings.name"/>
- * [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
- * Contact:
- * <ul>
- * <li ng-repeat="contact in settings.contacts">
- * <select ng-model="contact.type">
- * <option>phone</option>
- * <option>email</option>
- * </select>
- * <input type="text" ng-model="contact.value"/>
- * [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
- * | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
- * </li>
- * <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
- * </ul>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('controllerAsExample', [])
- * .controller('SettingsController1', SettingsController1);
- *
- * function SettingsController1() {
- * this.name = "John Smith";
- * this.contacts = [
- * {type: 'phone', value: '408 555 1212'},
- * {type: 'email', value: 'john.smith@example.org'} ];
- * }
- *
- * SettingsController1.prototype.greet = function() {
- * alert(this.name);
- * };
- *
- * SettingsController1.prototype.addContact = function() {
- * this.contacts.push({type: 'email', value: 'yourname@example.org'});
- * };
- *
- * SettingsController1.prototype.removeContact = function(contactToRemove) {
- * var index = this.contacts.indexOf(contactToRemove);
- * this.contacts.splice(index, 1);
- * };
- *
- * SettingsController1.prototype.clearContact = function(contact) {
- * contact.type = 'phone';
- * contact.value = '';
- * };
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should check controller as', function() {
- * var container = element(by.id('ctrl-as-exmpl'));
- * expect(container.element(by.model('settings.name'))
- * .getAttribute('value')).toBe('John Smith');
- *
- * var firstRepeat =
- * container.element(by.repeater('contact in settings.contacts').row(0));
- * var secondRepeat =
- * container.element(by.repeater('contact in settings.contacts').row(1));
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('408 555 1212');
- *
- * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('john.smith@example.org');
- *
- * firstRepeat.element(by.linkText('clear')).click();
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('');
- *
- * container.element(by.linkText('add')).click();
- *
- * expect(container.element(by.repeater('contact in settings.contacts').row(2))
- * .element(by.model('contact.value'))
- * .getAttribute('value'))
- * .toBe('yourname@example.org');
- * });
- * </file>
- * </example>
- *
- * This example demonstrates the "attach to `$scope`" style of controller.
- *
- * <example name="ngController" module="controllerExample">
- * <file name="index.html">
- * <div id="ctrl-exmpl" ng-controller="SettingsController2">
- * Name: <input type="text" ng-model="name"/>
- * [ <a href="" ng-click="greet()">greet</a> ]<br/>
- * Contact:
- * <ul>
- * <li ng-repeat="contact in contacts">
- * <select ng-model="contact.type">
- * <option>phone</option>
- * <option>email</option>
- * </select>
- * <input type="text" ng-model="contact.value"/>
- * [ <a href="" ng-click="clearContact(contact)">clear</a>
- * | <a href="" ng-click="removeContact(contact)">X</a> ]
- * </li>
- * <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
- * </ul>
- * </div>
- * </file>
- * <file name="app.js">
- * angular.module('controllerExample', [])
- * .controller('SettingsController2', ['$scope', SettingsController2]);
- *
- * function SettingsController2($scope) {
- * $scope.name = "John Smith";
- * $scope.contacts = [
- * {type:'phone', value:'408 555 1212'},
- * {type:'email', value:'john.smith@example.org'} ];
- *
- * $scope.greet = function() {
- * alert($scope.name);
- * };
- *
- * $scope.addContact = function() {
- * $scope.contacts.push({type:'email', value:'yourname@example.org'});
- * };
- *
- * $scope.removeContact = function(contactToRemove) {
- * var index = $scope.contacts.indexOf(contactToRemove);
- * $scope.contacts.splice(index, 1);
- * };
- *
- * $scope.clearContact = function(contact) {
- * contact.type = 'phone';
- * contact.value = '';
- * };
- * }
- * </file>
- * <file name="protractor.js" type="protractor">
- * it('should check controller', function() {
- * var container = element(by.id('ctrl-exmpl'));
- *
- * expect(container.element(by.model('name'))
- * .getAttribute('value')).toBe('John Smith');
- *
- * var firstRepeat =
- * container.element(by.repeater('contact in contacts').row(0));
- * var secondRepeat =
- * container.element(by.repeater('contact in contacts').row(1));
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('408 555 1212');
- * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('john.smith@example.org');
- *
- * firstRepeat.element(by.linkText('clear')).click();
- *
- * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
- * .toBe('');
- *
- * container.element(by.linkText('add')).click();
- *
- * expect(container.element(by.repeater('contact in contacts').row(2))
- * .element(by.model('contact.value'))
- * .getAttribute('value'))
- * .toBe('yourname@example.org');
- * });
- * </file>
- *</example>
- */
- var ngControllerDirective = [function() {
- return {
- scope: true,
- controller: '@',
- priority: 500
- };
- }];
- /**
- * @ngdoc directive
- * @name ngCsp
- *
- * @element html
- * @description
- * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
- *
- * This is necessary when developing things like Google Chrome Extensions.
- *
- * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
- * For Angular to be CSP compatible there are only two things that we need to do differently:
- *
- * - don't use `Function` constructor to generate optimized value getters
- * - don't inject custom stylesheet into the document
- *
- * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
- * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
- * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
- * be raised.
- *
- * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
- * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
- * To make those directives work in CSP mode, include the `angular-csp.css` manually.
- *
- * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
- * autodetection however triggers a CSP error to be logged in the console:
- *
- * ```
- * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
- * script in the following Content Security Policy directive: "default-src 'self'". Note that
- * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
- * ```
- *
- * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
- * directive on the root element of the application or on the `angular.js` script tag, whichever
- * appears first in the html document.
- *
- * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
- *
- * @example
- * This example shows how to apply the `ngCsp` directive to the `html` tag.
- ```html
- <!doctype html>
- <html ng-app ng-csp>
- ...
- ...
- </html>
- ```
- */
- // ngCsp is not implemented as a proper directive any more, because we need it be processed while we
- // bootstrap the system (before $parse is instantiated), for this reason we just have
- // the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc
- /**
- * @ngdoc directive
- * @name ngClick
- *
- * @description
- * The ngClick directive allows you to specify custom behavior when
- * an element is clicked.
- *
- * @element ANY
- * @priority 0
- * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
- * click. ({@link guide/expression#-event- Event object is available as `$event`})
- *
- * @example
- <example>
- <file name="index.html">
- <button ng-click="count = count + 1" ng-init="count=0">
- Increment
- </button>
- count: {{count}}
- </file>
- <file name="protractor.js" type="protractor">
- it('should check ng-click', function() {
- expect(element(by.binding('count')).getText()).toMatch('0');
- element(by.css('button')).click();
- expect(element(by.binding('count')).getText()).toMatch('1');
- });
- </file>
- </example>
- */
- var ngEventDirectives = {};
- forEach(
- 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
- function(name) {
- var directiveName = directiveNormalize('ng-' + name);
- ngEventDirectives[directiveName] = ['$parse', function($parse) {
- return {
- compile: function($element, attr) {
- var fn = $parse(attr[directiveName]);
- return function ngEventHandler(scope, element) {
- element.on(lowercase(name), function(event) {
- scope.$apply(function() {
- fn(scope, {$event:event});
- });
- });
- };
- }
- };
- }];
- }
- );
- var ngIfDirective = ['$animate', function($animate) {
- return {
- transclude: 'element',
- priority: 600,
- terminal: true,
- restrict: 'A',
- $$tlb: true,
- link: function ($scope, $element, $attr, ctrl, $transclude) {
- var block, childScope, previousElements;
- $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
- if (toBoolean(value)) {
- if (!childScope) {
- childScope = $scope.$new();
- $transclude(childScope, function (clone) {
- clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
-
-
-
- block = {
- clone: clone
- };
- $animate.enter(clone, $element.parent(), $element);
- });
- }
- } else {
- if(previousElements) {
- previousElements.remove();
- previousElements = null;
- }
- if(childScope) {
- childScope.$destroy();
- childScope = null;
- }
- if(block) {
- previousElements = getBlockElements(block.clone);
- $animate.leave(previousElements, function() {
- previousElements = null;
- });
- block = null;
- }
- }
- });
- }
- };
- }];
- var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',
- function($http, $templateCache, $anchorScroll, $animate, $sce) {
- return {
- restrict: 'ECA',
- priority: 400,
- terminal: true,
- transclude: 'element',
- controller: angular.noop,
- compile: function(element, attr) {
- var srcExp = attr.ngInclude || attr.src,
- onloadExp = attr.onload || '',
- autoScrollExp = attr.autoscroll;
- return function(scope, $element, $attr, ctrl, $transclude) {
- var changeCounter = 0,
- currentScope,
- previousElement,
- currentElement;
- var cleanupLastIncludeContent = function() {
- if(previousElement) {
- previousElement.remove();
- previousElement = null;
- }
- if(currentScope) {
- currentScope.$destroy();
- currentScope = null;
- }
- if(currentElement) {
- $animate.leave(currentElement, function() {
- previousElement = null;
- });
- previousElement = currentElement;
- currentElement = null;
- }
- };
- scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
- var afterAnimation = function() {
- if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
- $anchorScroll();
- }
- };
- var thisChangeId = ++changeCounter;
- if (src) {
- $http.get(src, {cache: $templateCache}).success(function(response) {
- if (thisChangeId !== changeCounter) return;
- var newScope = scope.$new();
- ctrl.template = response;
-
-
-
-
-
-
- var clone = $transclude(newScope, function(clone) {
- cleanupLastIncludeContent();
- $animate.enter(clone, null, $element, afterAnimation);
- });
- currentScope = newScope;
- currentElement = clone;
- currentScope.$emit('$includeContentLoaded');
- scope.$eval(onloadExp);
- }).error(function() {
- if (thisChangeId === changeCounter) cleanupLastIncludeContent();
- });
- scope.$emit('$includeContentRequested');
- } else {
- cleanupLastIncludeContent();
- ctrl.template = null;
- }
- });
- };
- }
- };
- }];
- var ngIncludeFillContentDirective = ['$compile',
- function($compile) {
- return {
- restrict: 'ECA',
- priority: -400,
- require: 'ngInclude',
- link: function(scope, $element, $attr, ctrl) {
- $element.html(ctrl.template);
- $compile($element.contents())(scope);
- }
- };
- }];
- var ngInitDirective = ngDirective({
- priority: 450,
- compile: function() {
- return {
- pre: function(scope, element, attrs) {
- scope.$eval(attrs.ngInit);
- }
- };
- }
- });
- var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
- var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
- var BRACE = /{}/g;
- return {
- restrict: 'EA',
- link: function(scope, element, attr) {
- var numberExp = attr.count,
- whenExp = attr.$attr.when && element.attr(attr.$attr.when),
- offset = attr.offset || 0,
- whens = scope.$eval(whenExp) || {},
- whensExpFns = {},
- startSymbol = $interpolate.startSymbol(),
- endSymbol = $interpolate.endSymbol(),
- isWhen = /^when(Minus)?(.+)$/;
- forEach(attr, function(expression, attributeName) {
- if (isWhen.test(attributeName)) {
- whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =
- element.attr(attr.$attr[attributeName]);
- }
- });
- forEach(whens, function(expression, key) {
- whensExpFns[key] =
- $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
- offset + endSymbol));
- });
- scope.$watch(function ngPluralizeWatch() {
- var value = parseFloat(scope.$eval(numberExp));
- if (!isNaN(value)) {
-
-
- if (!(value in whens)) value = $locale.pluralCat(value - offset);
- return whensExpFns[value](scope, element, true);
- } else {
- return '';
- }
- }, function ngPluralizeWatchAction(newVal) {
- element.text(newVal);
- });
- }
- };
- }];
- var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
- var NG_REMOVED = '$$NG_REMOVED';
- var ngRepeatMinErr = minErr('ngRepeat');
- return {
- transclude: 'element',
- priority: 1000,
- terminal: true,
- $$tlb: true,
- link: function($scope, $element, $attr, ctrl, $transclude){
- var expression = $attr.ngRepeat;
- var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),
- trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
- lhs, rhs, valueIdentifier, keyIdentifier,
- hashFnLocals = {$id: hashKey};
- if (!match) {
- throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
- expression);
- }
- lhs = match[1];
- rhs = match[2];
- trackByExp = match[3];
- if (trackByExp) {
- trackByExpGetter = $parse(trackByExp);
- trackByIdExpFn = function(key, value, index) {
-
- if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
- hashFnLocals[valueIdentifier] = value;
- hashFnLocals.$index = index;
- return trackByExpGetter($scope, hashFnLocals);
- };
- } else {
- trackByIdArrayFn = function(key, value) {
- return hashKey(value);
- };
- trackByIdObjFn = function(key) {
- return key;
- };
- }
- match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
- if (!match) {
- throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
- lhs);
- }
- valueIdentifier = match[3] || match[1];
- keyIdentifier = match[2];
-
-
-
-
-
- var lastBlockMap = {};
-
- $scope.$watchCollection(rhs, function ngRepeatAction(collection){
- var index, length,
- previousNode = $element[0],
- nextNode,
-
-
- nextBlockMap = {},
- arrayLength,
- childScope,
- key, value,
- trackById,
- trackByIdFn,
- collectionKeys,
- block,
- nextBlockOrder = [],
- elementsToRemove;
- if (isArrayLike(collection)) {
- collectionKeys = collection;
- trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
- } else {
- trackByIdFn = trackByIdExpFn || trackByIdObjFn;
-
- collectionKeys = [];
- for (key in collection) {
- if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {
- collectionKeys.push(key);
- }
- }
- collectionKeys.sort();
- }
- arrayLength = collectionKeys.length;
-
- length = nextBlockOrder.length = collectionKeys.length;
- for(index = 0; index < length; index++) {
- key = (collection === collectionKeys) ? index : collectionKeys[index];
- value = collection[key];
- trackById = trackByIdFn(key, value, index);
- assertNotHasOwnProperty(trackById, '`track by` id');
- if(lastBlockMap.hasOwnProperty(trackById)) {
- block = lastBlockMap[trackById];
- delete lastBlockMap[trackById];
- nextBlockMap[trackById] = block;
- nextBlockOrder[index] = block;
- } else if (nextBlockMap.hasOwnProperty(trackById)) {
-
- forEach(nextBlockOrder, function(block) {
- if (block && block.scope) lastBlockMap[block.id] = block;
- });
-
- throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
- expression, trackById);
- } else {
-
- nextBlockOrder[index] = { id: trackById };
- nextBlockMap[trackById] = false;
- }
- }
-
- for (key in lastBlockMap) {
-
- if (lastBlockMap.hasOwnProperty(key)) {
- block = lastBlockMap[key];
- elementsToRemove = getBlockElements(block.clone);
- $animate.leave(elementsToRemove);
- forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; });
- block.scope.$destroy();
- }
- }
-
- for (index = 0, length = collectionKeys.length; index < length; index++) {
- key = (collection === collectionKeys) ? index : collectionKeys[index];
- value = collection[key];
- block = nextBlockOrder[index];
- if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]);
- if (block.scope) {
-
-
- childScope = block.scope;
- nextNode = previousNode;
- do {
- nextNode = nextNode.nextSibling;
- } while(nextNode && nextNode[NG_REMOVED]);
- if (getBlockStart(block) != nextNode) {
-
- $animate.move(getBlockElements(block.clone), null, jqLite(previousNode));
- }
- previousNode = getBlockEnd(block);
- } else {
-
- childScope = $scope.$new();
- }
- childScope[valueIdentifier] = value;
- if (keyIdentifier) childScope[keyIdentifier] = key;
- childScope.$index = index;
- childScope.$first = (index === 0);
- childScope.$last = (index === (arrayLength - 1));
- childScope.$middle = !(childScope.$first || childScope.$last);
-
- childScope.$odd = !(childScope.$even = (index&1) === 0);
-
- if (!block.scope) {
- $transclude(childScope, function(clone) {
- clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
- $animate.enter(clone, null, jqLite(previousNode));
- previousNode = clone;
- block.scope = childScope;
-
-
-
- block.clone = clone;
- nextBlockMap[block.id] = block;
- });
- }
- }
- lastBlockMap = nextBlockMap;
- });
- }
- };
- function getBlockStart(block) {
- return block.clone[0];
- }
- function getBlockEnd(block) {
- return block.clone[block.clone.length - 1];
- }
- }];
- var ngShowDirective = ['$animate', function($animate) {
- return function(scope, element, attr) {
- scope.$watch(attr.ngShow, function ngShowWatchAction(value){
- $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
- });
- };
- }];
- var ngHideDirective = ['$animate', function($animate) {
- return function(scope, element, attr) {
- scope.$watch(attr.ngHide, function ngHideWatchAction(value){
- $animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
- });
- };
- }];
- var ngStyleDirective = ngDirective(function(scope, element, attr) {
- scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
- if (oldStyles && (newStyles !== oldStyles)) {
- forEach(oldStyles, function(val, style) { element.css(style, '');});
- }
- if (newStyles) element.css(newStyles);
- }, true);
- });
- var ngSwitchDirective = ['$animate', function($animate) {
- return {
- restrict: 'EA',
- require: 'ngSwitch',
-
- controller: ['$scope', function ngSwitchController() {
- this.cases = {};
- }],
- link: function(scope, element, attr, ngSwitchController) {
- var watchExpr = attr.ngSwitch || attr.on,
- selectedTranscludes = [],
- selectedElements = [],
- previousElements = [],
- selectedScopes = [];
- scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
- var i, ii;
- for (i = 0, ii = previousElements.length; i < ii; ++i) {
- previousElements[i].remove();
- }
- previousElements.length = 0;
- for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
- var selected = selectedElements[i];
- selectedScopes[i].$destroy();
- previousElements[i] = selected;
- $animate.leave(selected, function() {
- previousElements.splice(i, 1);
- });
- }
- selectedElements.length = 0;
- selectedScopes.length = 0;
- if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
- scope.$eval(attr.change);
- forEach(selectedTranscludes, function(selectedTransclude) {
- var selectedScope = scope.$new();
- selectedScopes.push(selectedScope);
- selectedTransclude.transclude(selectedScope, function(caseElement) {
- var anchor = selectedTransclude.element;
- selectedElements.push(caseElement);
- $animate.enter(caseElement, anchor.parent(), anchor);
- });
- });
- }
- });
- }
- };
- }];
- var ngSwitchWhenDirective = ngDirective({
- transclude: 'element',
- priority: 800,
- require: '^ngSwitch',
- link: function(scope, element, attrs, ctrl, $transclude) {
- ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
- ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
- }
- });
- var ngSwitchDefaultDirective = ngDirective({
- transclude: 'element',
- priority: 800,
- require: '^ngSwitch',
- link: function(scope, element, attr, ctrl, $transclude) {
- ctrl.cases['?'] = (ctrl.cases['?'] || []);
- ctrl.cases['?'].push({ transclude: $transclude, element: element });
- }
- });
- var ngTranscludeDirective = ngDirective({
- link: function($scope, $element, $attrs, controller, $transclude) {
- if (!$transclude) {
- throw minErr('ngTransclude')('orphan',
- 'Illegal use of ngTransclude directive in the template! ' +
- 'No parent directive that requires a transclusion found. ' +
- 'Element: {0}',
- startingTag($element));
- }
- $transclude(function(clone) {
- $element.empty();
- $element.append(clone);
- });
- }
- });
- var scriptDirective = ['$templateCache', function($templateCache) {
- return {
- restrict: 'E',
- terminal: true,
- compile: function(element, attr) {
- if (attr.type == 'text/ng-template') {
- var templateUrl = attr.id,
-
- text = element[0].text;
- $templateCache.put(templateUrl, text);
- }
- }
- };
- }];
- var ngOptionsMinErr = minErr('ngOptions');
- var ngOptionsDirective = valueFn({ terminal: true });
- var selectDirective = ['$compile', '$parse', function($compile, $parse) {
-
- var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
- nullModelCtrl = {$setViewValue: noop};
- return {
- restrict: 'E',
- require: ['select', '?ngModel'],
- controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
- var self = this,
- optionsMap = {},
- ngModelCtrl = nullModelCtrl,
- nullOption,
- unknownOption;
- self.databound = $attrs.ngModel;
- self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {
- ngModelCtrl = ngModelCtrl_;
- nullOption = nullOption_;
- unknownOption = unknownOption_;
- };
- self.addOption = function(value) {
- assertNotHasOwnProperty(value, '"option value"');
- optionsMap[value] = true;
- if (ngModelCtrl.$viewValue == value) {
- $element.val(value);
- if (unknownOption.parent()) unknownOption.remove();
- }
- };
- self.removeOption = function(value) {
- if (this.hasOption(value)) {
- delete optionsMap[value];
- if (ngModelCtrl.$viewValue == value) {
- this.renderUnknownOption(value);
- }
- }
- };
- self.renderUnknownOption = function(val) {
- var unknownVal = '? ' + hashKey(val) + ' ?';
- unknownOption.val(unknownVal);
- $element.prepend(unknownOption);
- $element.val(unknownVal);
- unknownOption.prop('selected', true);
- };
- self.hasOption = function(value) {
- return optionsMap.hasOwnProperty(value);
- };
- $scope.$on('$destroy', function() {
-
- self.renderUnknownOption = noop;
- });
- }],
- link: function(scope, element, attr, ctrls) {
-
- if (!ctrls[1]) return;
- var selectCtrl = ctrls[0],
- ngModelCtrl = ctrls[1],
- multiple = attr.multiple,
- optionsExp = attr.ngOptions,
- nullOption = false,
- emptyOption,
-
-
- optionTemplate = jqLite(document.createElement('option')),
- optGroupTemplate =jqLite(document.createElement('optgroup')),
- unknownOption = optionTemplate.clone();
-
- for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
- if (children[i].value === '') {
- emptyOption = nullOption = children.eq(i);
- break;
- }
- }
- selectCtrl.init(ngModelCtrl, nullOption, unknownOption);
-
- if (multiple) {
- ngModelCtrl.$isEmpty = function(value) {
- return !value || value.length === 0;
- };
- }
- if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);
- else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);
- else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);
-
- function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
- ngModelCtrl.$render = function() {
- var viewValue = ngModelCtrl.$viewValue;
- if (selectCtrl.hasOption(viewValue)) {
- if (unknownOption.parent()) unknownOption.remove();
- selectElement.val(viewValue);
- if (viewValue === '') emptyOption.prop('selected', true);
- } else {
- if (isUndefined(viewValue) && emptyOption) {
- selectElement.val('');
- } else {
- selectCtrl.renderUnknownOption(viewValue);
- }
- }
- };
- selectElement.on('change', function() {
- scope.$apply(function() {
- if (unknownOption.parent()) unknownOption.remove();
- ngModelCtrl.$setViewValue(selectElement.val());
- });
- });
- }
- function setupAsMultiple(scope, selectElement, ctrl) {
- var lastView;
- ctrl.$render = function() {
- var items = new HashMap(ctrl.$viewValue);
- forEach(selectElement.find('option'), function(option) {
- option.selected = isDefined(items.get(option.value));
- });
- };
-
-
- scope.$watch(function selectMultipleWatch() {
- if (!equals(lastView, ctrl.$viewValue)) {
- lastView = shallowCopy(ctrl.$viewValue);
- ctrl.$render();
- }
- });
- selectElement.on('change', function() {
- scope.$apply(function() {
- var array = [];
- forEach(selectElement.find('option'), function(option) {
- if (option.selected) {
- array.push(option.value);
- }
- });
- ctrl.$setViewValue(array);
- });
- });
- }
- function setupAsOptions(scope, selectElement, ctrl) {
- var match;
- if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {
- throw ngOptionsMinErr('iexp',
- "Expected expression in form of " +
- "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
- " but got '{0}'. Element: {1}",
- optionsExp, startingTag(selectElement));
- }
- var displayFn = $parse(match[2] || match[1]),
- valueName = match[4] || match[6],
- keyName = match[5],
- groupByFn = $parse(match[3] || ''),
- valueFn = $parse(match[2] ? match[1] : valueName),
- valuesFn = $parse(match[7]),
- track = match[8],
- trackFn = track ? $parse(match[8]) : null,
-
-
-
-
- optionGroupsCache = [[{element: selectElement, label:''}]];
- if (nullOption) {
-
- $compile(nullOption)(scope);
-
-
- nullOption.removeClass('ng-scope');
-
-
- nullOption.remove();
- }
-
- selectElement.empty();
- selectElement.on('change', function() {
- scope.$apply(function() {
- var optionGroup,
- collection = valuesFn(scope) || [],
- locals = {},
- key, value, optionElement, index, groupIndex, length, groupLength, trackIndex;
- if (multiple) {
- value = [];
- for (groupIndex = 0, groupLength = optionGroupsCache.length;
- groupIndex < groupLength;
- groupIndex++) {
-
- optionGroup = optionGroupsCache[groupIndex];
- for(index = 1, length = optionGroup.length; index < length; index++) {
- if ((optionElement = optionGroup[index].element)[0].selected) {
- key = optionElement.val();
- if (keyName) locals[keyName] = key;
- if (trackFn) {
- for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {
- locals[valueName] = collection[trackIndex];
- if (trackFn(scope, locals) == key) break;
- }
- } else {
- locals[valueName] = collection[key];
- }
- value.push(valueFn(scope, locals));
- }
- }
- }
- } else {
- key = selectElement.val();
- if (key == '?') {
- value = undefined;
- } else if (key === ''){
- value = null;
- } else {
- if (trackFn) {
- for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {
- locals[valueName] = collection[trackIndex];
- if (trackFn(scope, locals) == key) {
- value = valueFn(scope, locals);
- break;
- }
- }
- } else {
- locals[valueName] = collection[key];
- if (keyName) locals[keyName] = key;
- value = valueFn(scope, locals);
- }
- }
-
- if (optionGroupsCache[0].length > 1) {
- if (optionGroupsCache[0][1].id !== key) {
- optionGroupsCache[0][1].selected = false;
- }
- }
- }
- ctrl.$setViewValue(value);
- });
- });
- ctrl.$render = render;
-
- scope.$watch(render);
- function render() {
-
- var optionGroups = {'':[]},
- optionGroupNames = [''],
- optionGroupName,
- optionGroup,
- option,
- existingParent, existingOptions, existingOption,
- modelValue = ctrl.$modelValue,
- values = valuesFn(scope) || [],
- keys = keyName ? sortedKeys(values) : values,
- key,
- groupLength, length,
- groupIndex, index,
- locals = {},
- selected,
- selectedSet = false,
- lastElement,
- element,
- label;
- if (multiple) {
- if (trackFn && isArray(modelValue)) {
- selectedSet = new HashMap([]);
- for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {
- locals[valueName] = modelValue[trackIndex];
- selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);
- }
- } else {
- selectedSet = new HashMap(modelValue);
- }
- }
-
- for (index = 0; length = keys.length, index < length; index++) {
- key = index;
- if (keyName) {
- key = keys[index];
- if ( key.charAt(0) === '$' ) continue;
- locals[keyName] = key;
- }
- locals[valueName] = values[key];
- optionGroupName = groupByFn(scope, locals) || '';
- if (!(optionGroup = optionGroups[optionGroupName])) {
- optionGroup = optionGroups[optionGroupName] = [];
- optionGroupNames.push(optionGroupName);
- }
- if (multiple) {
- selected = isDefined(
- selectedSet.remove(trackFn ? trackFn(scope, locals) : valueFn(scope, locals))
- );
- } else {
- if (trackFn) {
- var modelCast = {};
- modelCast[valueName] = modelValue;
- selected = trackFn(scope, modelCast) === trackFn(scope, locals);
- } else {
- selected = modelValue === valueFn(scope, locals);
- }
- selectedSet = selectedSet || selected;
- }
- label = displayFn(scope, locals);
-
- label = isDefined(label) ? label : '';
- optionGroup.push({
-
- id: trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index),
- label: label,
- selected: selected
- });
- }
- if (!multiple) {
- if (nullOption || modelValue === null) {
-
- optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
- } else if (!selectedSet) {
-
- optionGroups[''].unshift({id:'?', label:'', selected:true});
- }
- }
-
- for (groupIndex = 0, groupLength = optionGroupNames.length;
- groupIndex < groupLength;
- groupIndex++) {
-
- optionGroupName = optionGroupNames[groupIndex];
-
- optionGroup = optionGroups[optionGroupName];
- if (optionGroupsCache.length <= groupIndex) {
-
- existingParent = {
- element: optGroupTemplate.clone().attr('label', optionGroupName),
- label: optionGroup.label
- };
- existingOptions = [existingParent];
- optionGroupsCache.push(existingOptions);
- selectElement.append(existingParent.element);
- } else {
- existingOptions = optionGroupsCache[groupIndex];
- existingParent = existingOptions[0];
-
- if (existingParent.label != optionGroupName) {
- existingParent.element.attr('label', existingParent.label = optionGroupName);
- }
- }
- lastElement = null;
- for(index = 0, length = optionGroup.length; index < length; index++) {
- option = optionGroup[index];
- if ((existingOption = existingOptions[index+1])) {
-
- lastElement = existingOption.element;
- if (existingOption.label !== option.label) {
- lastElement.text(existingOption.label = option.label);
- }
- if (existingOption.id !== option.id) {
- lastElement.val(existingOption.id = option.id);
- }
-
- if (existingOption.selected !== option.selected) {
- lastElement.prop('selected', (existingOption.selected = option.selected));
- if (msie) {
-
-
-
- lastElement.prop('selected', existingOption.selected);
- }
- }
- } else {
-
-
- if (option.id === '' && nullOption) {
-
- element = nullOption;
- } else {
-
-
-
- (element = optionTemplate.clone())
- .val(option.id)
- .prop('selected', option.selected)
- .text(option.label);
- }
- existingOptions.push(existingOption = {
- element: element,
- label: option.label,
- id: option.id,
- selected: option.selected
- });
- if (lastElement) {
- lastElement.after(element);
- } else {
- existingParent.element.append(element);
- }
- lastElement = element;
- }
- }
-
- index++;
- while(existingOptions.length > index) {
- existingOptions.pop().element.remove();
- }
- }
-
- while(optionGroupsCache.length > groupIndex) {
- optionGroupsCache.pop()[0].element.remove();
- }
- }
- }
- }
- };
- }];
- var optionDirective = ['$interpolate', function($interpolate) {
- var nullSelectCtrl = {
- addOption: noop,
- removeOption: noop
- };
- return {
- restrict: 'E',
- priority: 100,
- compile: function(element, attr) {
- if (isUndefined(attr.value)) {
- var interpolateFn = $interpolate(element.text(), true);
- if (!interpolateFn) {
- attr.$set('value', element.text());
- }
- }
- return function (scope, element, attr) {
- var selectCtrlName = '$selectController',
- parent = element.parent(),
- selectCtrl = parent.data(selectCtrlName) ||
- parent.parent().data(selectCtrlName);
- if (selectCtrl && selectCtrl.databound) {
-
-
- element.prop('selected', false);
- } else {
- selectCtrl = nullSelectCtrl;
- }
- if (interpolateFn) {
- scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
- attr.$set('value', newVal);
- if (newVal !== oldVal) selectCtrl.removeOption(oldVal);
- selectCtrl.addOption(newVal);
- });
- } else {
- selectCtrl.addOption(attr.value);
- }
- element.on('$destroy', function() {
- selectCtrl.removeOption(attr.value);
- });
- };
- }
- };
- }];
- var styleDirective = valueFn({
- restrict: 'E',
- terminal: true
- });
- if (window.angular.bootstrap) {
-
- console.log('WARNING: Tried to load angular more than once.');
- return;
- }
-
-
- bindJQuery();
- publishExternalAPI(angular);
- jqLite(document).ready(function() {
- angularInit(document, bootstrap);
- });
- })(window, document);
- !window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}.ng-hide-add-active,.ng-hide-remove{display:block!important;}</style>');
|