Dashboard sipadu mbip
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

simpleyui-debug.js 541KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134
  1. /*
  2. Copyright (c) 2010, Yahoo! Inc. All rights reserved.
  3. Code licensed under the BSD License:
  4. http://developer.yahoo.com/yui/license.html
  5. version: 3.4.0
  6. build: nightly
  7. */
  8. /**
  9. * The YUI module contains the components required for building the YUI seed
  10. * file. This includes the script loading mechanism, a simple queue, and
  11. * the core utilities for the library.
  12. * @module yui
  13. * @submodule yui-base
  14. */
  15. if (typeof YUI != 'undefined') {
  16. YUI._YUI = YUI;
  17. }
  18. /**
  19. * The YUI global namespace object. If YUI is already defined, the
  20. * existing YUI object will not be overwritten so that defined
  21. * namespaces are preserved. It is the constructor for the object
  22. * the end user interacts with. As indicated below, each instance
  23. * has full custom event support, but only if the event system
  24. * is available. This is a self-instantiable factory function. You
  25. * can invoke it directly like this:
  26. *
  27. * YUI().use('*', function(Y) {
  28. * // ready
  29. * });
  30. *
  31. * But it also works like this:
  32. *
  33. * var Y = YUI();
  34. *
  35. * @class YUI
  36. * @constructor
  37. * @global
  38. * @uses EventTarget
  39. * @param o* {object} 0..n optional configuration objects. these values
  40. * are store in Y.config. See <a href="config.html">Config</a> for the list of supported
  41. * properties.
  42. */
  43. /*global YUI*/
  44. /*global YUI_config*/
  45. var YUI = function() {
  46. var i = 0,
  47. Y = this,
  48. args = arguments,
  49. l = args.length,
  50. instanceOf = function(o, type) {
  51. return (o && o.hasOwnProperty && (o instanceof type));
  52. },
  53. gconf = (typeof YUI_config !== 'undefined') && YUI_config;
  54. if (!(instanceOf(Y, YUI))) {
  55. Y = new YUI();
  56. } else {
  57. // set up the core environment
  58. Y._init();
  59. // YUI.GlobalConfig is a master configuration that might span
  60. // multiple contexts in a non-browser environment. It is applied
  61. // first to all instances in all contexts.
  62. if (YUI.GlobalConfig) {
  63. Y.applyConfig(YUI.GlobalConfig);
  64. }
  65. // YUI_Config is a page-level config. It is applied to all
  66. // instances created on the page. This is applied after
  67. // YUI.GlobalConfig, and before the instance level configuration
  68. // objects.
  69. if (gconf) {
  70. Y.applyConfig(gconf);
  71. }
  72. // bind the specified additional modules for this instance
  73. if (!l) {
  74. Y._setup();
  75. }
  76. }
  77. if (l) {
  78. // Each instance can accept one or more configuration objects.
  79. // These are applied after YUI.GlobalConfig and YUI_Config,
  80. // overriding values set in those config files if there is a '
  81. // matching property.
  82. for (; i < l; i++) {
  83. Y.applyConfig(args[i]);
  84. }
  85. Y._setup();
  86. }
  87. Y.instanceOf = instanceOf;
  88. return Y;
  89. };
  90. (function() {
  91. var proto, prop,
  92. VERSION = '3.4.0',
  93. PERIOD = '.',
  94. BASE = 'http://yui.yahooapis.com/',
  95. DOC_LABEL = 'yui3-js-enabled',
  96. NOOP = function() {},
  97. SLICE = Array.prototype.slice,
  98. APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo
  99. 'io.xdrResponse': 1, // can call. this should
  100. 'SWF.eventHandler': 1 }, // be done at build time
  101. hasWin = (typeof window != 'undefined'),
  102. win = (hasWin) ? window : null,
  103. doc = (hasWin) ? win.document : null,
  104. docEl = doc && doc.documentElement,
  105. docClass = docEl && docEl.className,
  106. instances = {},
  107. time = new Date().getTime(),
  108. add = function(el, type, fn, capture) {
  109. if (el && el.addEventListener) {
  110. el.addEventListener(type, fn, capture);
  111. } else if (el && el.attachEvent) {
  112. el.attachEvent('on' + type, fn);
  113. }
  114. },
  115. remove = function(el, type, fn, capture) {
  116. if (el && el.removeEventListener) {
  117. // this can throw an uncaught exception in FF
  118. try {
  119. el.removeEventListener(type, fn, capture);
  120. } catch (ex) {}
  121. } else if (el && el.detachEvent) {
  122. el.detachEvent('on' + type, fn);
  123. }
  124. },
  125. handleLoad = function() {
  126. YUI.Env.windowLoaded = true;
  127. YUI.Env.DOMReady = true;
  128. if (hasWin) {
  129. remove(window, 'load', handleLoad);
  130. }
  131. },
  132. getLoader = function(Y, o) {
  133. var loader = Y.Env._loader;
  134. if (loader) {
  135. //loader._config(Y.config);
  136. loader.ignoreRegistered = false;
  137. loader.onEnd = null;
  138. loader.data = null;
  139. loader.required = [];
  140. loader.loadType = null;
  141. } else {
  142. loader = new Y.Loader(Y.config);
  143. Y.Env._loader = loader;
  144. }
  145. return loader;
  146. },
  147. clobber = function(r, s) {
  148. for (var i in s) {
  149. if (s.hasOwnProperty(i)) {
  150. r[i] = s[i];
  151. }
  152. }
  153. },
  154. ALREADY_DONE = { success: true };
  155. // Stamp the documentElement (HTML) with a class of "yui-loaded" to
  156. // enable styles that need to key off of JS being enabled.
  157. if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
  158. if (docClass) {
  159. docClass += ' ';
  160. }
  161. docClass += DOC_LABEL;
  162. docEl.className = docClass;
  163. }
  164. if (VERSION.indexOf('@') > -1) {
  165. VERSION = '3.3.0'; // dev time hack for cdn test
  166. }
  167. proto = {
  168. /**
  169. * Applies a new configuration object to the YUI instance config.
  170. * This will merge new group/module definitions, and will also
  171. * update the loader cache if necessary. Updating Y.config directly
  172. * will not update the cache.
  173. * @method applyConfig
  174. * @param {object} the configuration object.
  175. * @since 3.2.0
  176. */
  177. applyConfig: function(o) {
  178. o = o || NOOP;
  179. var attr,
  180. name,
  181. // detail,
  182. config = this.config,
  183. mods = config.modules,
  184. groups = config.groups,
  185. rls = config.rls,
  186. loader = this.Env._loader;
  187. for (name in o) {
  188. if (o.hasOwnProperty(name)) {
  189. attr = o[name];
  190. if (mods && name == 'modules') {
  191. clobber(mods, attr);
  192. } else if (groups && name == 'groups') {
  193. clobber(groups, attr);
  194. } else if (rls && name == 'rls') {
  195. clobber(rls, attr);
  196. } else if (name == 'win') {
  197. config[name] = attr.contentWindow || attr;
  198. config.doc = config[name].document;
  199. } else if (name == '_yuid') {
  200. // preserve the guid
  201. } else {
  202. config[name] = attr;
  203. }
  204. }
  205. }
  206. if (loader) {
  207. loader._config(o);
  208. }
  209. },
  210. /**
  211. * Old way to apply a config to the instance (calls `applyConfig` under the hood)
  212. * @private
  213. * @method _config
  214. * @param {Object} o The config to apply
  215. */
  216. _config: function(o) {
  217. this.applyConfig(o);
  218. },
  219. /**
  220. * Initialize this YUI instance
  221. * @private
  222. * @method _init
  223. */
  224. _init: function() {
  225. var filter,
  226. Y = this,
  227. G_ENV = YUI.Env,
  228. Env = Y.Env,
  229. prop;
  230. /**
  231. * The version number of the YUI instance.
  232. * @property version
  233. * @type string
  234. */
  235. Y.version = VERSION;
  236. if (!Env) {
  237. Y.Env = {
  238. mods: {}, // flat module map
  239. versions: {}, // version module map
  240. base: BASE,
  241. cdn: BASE + VERSION + '/build/',
  242. // bootstrapped: false,
  243. _idx: 0,
  244. _used: {},
  245. _attached: {},
  246. _missed: [],
  247. _yidx: 0,
  248. _uidx: 0,
  249. _guidp: 'y',
  250. _loaded: {},
  251. // serviced: {},
  252. // Regex in English:
  253. // I'll start at the \b(simpleyui).
  254. // 1. Look in the test string for "simpleyui" or "yui" or
  255. // "yui-base" or "yui-rls" or "yui-foobar" that comes after a word break. That is, it
  256. // can't match "foyui" or "i_heart_simpleyui". This can be anywhere in the string.
  257. // 2. After #1 must come a forward slash followed by the string matched in #1, so
  258. // "yui-base/yui-base" or "simpleyui/simpleyui" or "yui-pants/yui-pants".
  259. // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
  260. // so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
  261. // 4. This is followed by ".js", so "yui/yui.js", "simpleyui/simpleyui-min.js"
  262. // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
  263. // then capture the junk between the LAST "&" and the string in 1-4. So
  264. // "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-rls/yui-rls.js"
  265. // will capture "3.3.0/build/"
  266. //
  267. // Regex Exploded:
  268. // (?:\? Find a ?
  269. // (?:[^&]*&) followed by 0..n characters followed by an &
  270. // * in fact, find as many sets of characters followed by a & as you can
  271. // ([^&]*) capture the stuff after the last & in \1
  272. // )? but it's ok if all this ?junk&more_junk stuff isn't even there
  273. // \b(simpleyui| after a word break find either the string "simpleyui" or
  274. // yui(?:-\w+)? the string "yui" optionally followed by a -, then more characters
  275. // ) and store the simpleyui or yui-* string in \2
  276. // \/\2 then comes a / followed by the simpleyui or yui-* string in \2
  277. // (?:-(min|debug))? optionally followed by "-min" or "-debug"
  278. // .js and ending in ".js"
  279. _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
  280. parseBasePath: function(src, pattern) {
  281. var match = src.match(pattern),
  282. path, filter;
  283. if (match) {
  284. path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
  285. // this is to set up the path to the loader. The file
  286. // filter for loader should match the yui include.
  287. filter = match[3];
  288. // extract correct path for mixed combo urls
  289. // http://yuilibrary.com/projects/yui3/ticket/2528423
  290. if (match[1]) {
  291. path += '?' + match[1];
  292. }
  293. path = {
  294. filter: filter,
  295. path: path
  296. }
  297. }
  298. return path;
  299. },
  300. getBase: G_ENV && G_ENV.getBase ||
  301. function(pattern) {
  302. var nodes = (doc && doc.getElementsByTagName('script')) || [],
  303. path = Env.cdn, parsed,
  304. i, len, src;
  305. for (i = 0, len = nodes.length; i < len; ++i) {
  306. src = nodes[i].src;
  307. if (src) {
  308. parsed = Y.Env.parseBasePath(src, pattern);
  309. if (parsed) {
  310. filter = parsed.filter;
  311. path = parsed.path;
  312. break;
  313. }
  314. }
  315. }
  316. // use CDN default
  317. return path;
  318. }
  319. };
  320. Env = Y.Env;
  321. Env._loaded[VERSION] = {};
  322. if (G_ENV && Y !== YUI) {
  323. Env._yidx = ++G_ENV._yidx;
  324. Env._guidp = ('yui_' + VERSION + '_' +
  325. Env._yidx + '_' + time).replace(/\./g, '_');
  326. } else if (YUI._YUI) {
  327. G_ENV = YUI._YUI.Env;
  328. Env._yidx += G_ENV._yidx;
  329. Env._uidx += G_ENV._uidx;
  330. for (prop in G_ENV) {
  331. if (!(prop in Env)) {
  332. Env[prop] = G_ENV[prop];
  333. }
  334. }
  335. delete YUI._YUI;
  336. }
  337. Y.id = Y.stamp(Y);
  338. instances[Y.id] = Y;
  339. }
  340. Y.constructor = YUI;
  341. // configuration defaults
  342. Y.config = Y.config || {
  343. win: win,
  344. doc: doc,
  345. debug: true,
  346. useBrowserConsole: true,
  347. throwFail: true,
  348. bootstrap: true,
  349. cacheUse: true,
  350. fetchCSS: true,
  351. use_rls: false,
  352. rls_timeout: 2000
  353. };
  354. if (YUI.Env.rls_disabled) {
  355. Y.config.use_rls = false;
  356. }
  357. Y.config.lang = Y.config.lang || 'en-US';
  358. Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
  359. if (!filter || (!('mindebug').indexOf(filter))) {
  360. filter = 'min';
  361. }
  362. filter = (filter) ? '-' + filter : filter;
  363. Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
  364. },
  365. /**
  366. * Finishes the instance setup. Attaches whatever modules were defined
  367. * when the yui modules was registered.
  368. * @method _setup
  369. * @private
  370. */
  371. _setup: function(o) {
  372. var i, Y = this,
  373. core = [],
  374. mods = YUI.Env.mods,
  375. extras = Y.config.core || ['get','features','intl-base','yui-log','yui-later'];
  376. for (i = 0; i < extras.length; i++) {
  377. if (mods[extras[i]]) {
  378. core.push(extras[i]);
  379. }
  380. }
  381. Y._attach(['yui-base']);
  382. Y._attach(core);
  383. // Y.log(Y.id + ' initialized', 'info', 'yui');
  384. },
  385. /**
  386. * Executes a method on a YUI instance with
  387. * the specified id if the specified method is whitelisted.
  388. * @method applyTo
  389. * @param id {String} the YUI instance id.
  390. * @param method {String} the name of the method to exectute.
  391. * Ex: 'Object.keys'.
  392. * @param args {Array} the arguments to apply to the method.
  393. * @return {Object} the return value from the applied method or null.
  394. */
  395. applyTo: function(id, method, args) {
  396. if (!(method in APPLY_TO_AUTH)) {
  397. this.log(method + ': applyTo not allowed', 'warn', 'yui');
  398. return null;
  399. }
  400. var instance = instances[id], nest, m, i;
  401. if (instance) {
  402. nest = method.split('.');
  403. m = instance;
  404. for (i = 0; i < nest.length; i = i + 1) {
  405. m = m[nest[i]];
  406. if (!m) {
  407. this.log('applyTo not found: ' + method, 'warn', 'yui');
  408. }
  409. }
  410. return m.apply(instance, args);
  411. }
  412. return null;
  413. },
  414. /**
  415. * Registers a module with the YUI global. The easiest way to create a
  416. * first-class YUI module is to use the YUI component build tool.
  417. *
  418. * http://yuilibrary.com/projects/builder
  419. *
  420. * The build system will produce the `YUI.add` wrapper for you module, along
  421. * with any configuration info required for the module.
  422. * @method add
  423. * @param name {String} module name.
  424. * @param fn {Function} entry point into the module that
  425. * is used to bind module to the YUI instance.
  426. * @param version {String} version string.
  427. * @param details {Object} optional config data:
  428. * @param details.requires {Array} features that must be present before this module can be attached.
  429. * @param details.optional {Array} optional features that should be present if loadOptional
  430. * is defined. Note: modules are not often loaded this way in YUI 3,
  431. * but this field is still useful to inform the user that certain
  432. * features in the component will require additional dependencies.
  433. * @param details.use {Array} features that are included within this module which need to
  434. * be attached automatically when this module is attached. This
  435. * supports the YUI 3 rollup system -- a module with submodules
  436. * defined will need to have the submodules listed in the 'use'
  437. * config. The YUI component build tool does this for you.
  438. * @return {YUI} the YUI instance.
  439. *
  440. */
  441. add: function(name, fn, version, details) {
  442. details = details || {};
  443. var env = YUI.Env,
  444. mod = {
  445. name: name,
  446. fn: fn,
  447. version: version,
  448. details: details
  449. },
  450. loader,
  451. i, versions = env.versions;
  452. env.mods[name] = mod;
  453. versions[version] = versions[version] || {};
  454. versions[version][name] = mod;
  455. for (i in instances) {
  456. if (instances.hasOwnProperty(i)) {
  457. loader = instances[i].Env._loader;
  458. if (loader) {
  459. if (!loader.moduleInfo[name]) {
  460. loader.addModule(details, name);
  461. }
  462. }
  463. }
  464. }
  465. return this;
  466. },
  467. /**
  468. * Executes the function associated with each required
  469. * module, binding the module to the YUI instance.
  470. * @method _attach
  471. * @private
  472. */
  473. _attach: function(r, moot) {
  474. var i, name, mod, details, req, use, after,
  475. mods = YUI.Env.mods,
  476. aliases = YUI.Env.aliases,
  477. Y = this, j,
  478. done = Y.Env._attached,
  479. len = r.length, loader;
  480. //console.info('attaching: ' + r, 'info', 'yui');
  481. for (i = 0; i < len; i++) {
  482. if (!done[r[i]]) {
  483. name = r[i];
  484. mod = mods[name];
  485. if (aliases && aliases[name]) {
  486. Y._attach(aliases[name]);
  487. continue;
  488. }
  489. if (!mod) {
  490. loader = Y.Env._loader;
  491. if (loader && loader.moduleInfo[name]) {
  492. mod = loader.moduleInfo[name];
  493. if (mod.use) {
  494. moot = true;
  495. }
  496. }
  497. // Y.log('no js def for: ' + name, 'info', 'yui');
  498. //if (!loader || !loader.moduleInfo[name]) {
  499. //if ((!loader || !loader.moduleInfo[name]) && !moot) {
  500. if (!moot) {
  501. if (name.indexOf('skin-') === -1) {
  502. Y.Env._missed.push(name);
  503. Y.message('NOT loaded: ' + name, 'warn', 'yui');
  504. }
  505. }
  506. } else {
  507. done[name] = true;
  508. //Don't like this, but in case a mod was asked for once, then we fetch it
  509. //We need to remove it from the missed list
  510. for (j = 0; j < Y.Env._missed.length; j++) {
  511. if (Y.Env._missed[j] === name) {
  512. Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
  513. Y.Env._missed.splice(j, 1);
  514. }
  515. }
  516. details = mod.details;
  517. req = details.requires;
  518. use = details.use;
  519. after = details.after;
  520. if (req) {
  521. for (j = 0; j < req.length; j++) {
  522. if (!done[req[j]]) {
  523. if (!Y._attach(req)) {
  524. return false;
  525. }
  526. break;
  527. }
  528. }
  529. }
  530. if (after) {
  531. for (j = 0; j < after.length; j++) {
  532. if (!done[after[j]]) {
  533. if (!Y._attach(after, true)) {
  534. return false;
  535. }
  536. break;
  537. }
  538. }
  539. }
  540. if (mod.fn) {
  541. try {
  542. mod.fn(Y, name);
  543. } catch (e) {
  544. Y.error('Attach error: ' + name, e, name);
  545. return false;
  546. }
  547. }
  548. if (use) {
  549. for (j = 0; j < use.length; j++) {
  550. if (!done[use[j]]) {
  551. if (!Y._attach(use)) {
  552. return false;
  553. }
  554. break;
  555. }
  556. }
  557. }
  558. }
  559. }
  560. }
  561. return true;
  562. },
  563. /**
  564. * Attaches one or more modules to the YUI instance. When this
  565. * is executed, the requirements are analyzed, and one of
  566. * several things can happen:
  567. *
  568. * * All requirements are available on the page -- The modules
  569. * are attached to the instance. If supplied, the use callback
  570. * is executed synchronously.
  571. *
  572. * * Modules are missing, the Get utility is not available OR
  573. * the 'bootstrap' config is false -- A warning is issued about
  574. * the missing modules and all available modules are attached.
  575. *
  576. * * Modules are missing, the Loader is not available but the Get
  577. * utility is and boostrap is not false -- The loader is bootstrapped
  578. * before doing the following....
  579. *
  580. * * Modules are missing and the Loader is available -- The loader
  581. * expands the dependency tree and fetches missing modules. When
  582. * the loader is finshed the callback supplied to use is executed
  583. * asynchronously.
  584. *
  585. * @method use
  586. * @param modules* {String} 1-n modules to bind (uses arguments array).
  587. * @param *callback {Function} callback function executed when
  588. * the instance has the required functionality. If included, it
  589. * must be the last parameter.
  590. *
  591. * @example
  592. * // loads and attaches dd and its dependencies
  593. * YUI().use('dd', function(Y) {});
  594. *
  595. * // loads and attaches dd and node as well as all of their dependencies (since 3.4.0)
  596. * YUI().use(['dd', 'node'], function(Y) {});
  597. *
  598. * // attaches all modules that are available on the page
  599. * YUI().use('*', function(Y) {});
  600. *
  601. * // intrinsic YUI gallery support (since 3.1.0)
  602. * YUI().use('gallery-yql', function(Y) {});
  603. *
  604. * // intrinsic YUI 2in3 support (since 3.1.0)
  605. * YUI().use('yui2-datatable', function(Y) {});
  606. *
  607. * @return {YUI} the YUI instance.
  608. */
  609. use: function() {
  610. var args = SLICE.call(arguments, 0),
  611. callback = args[args.length - 1],
  612. Y = this,
  613. i = 0,
  614. name,
  615. Env = Y.Env,
  616. provisioned = true;
  617. // The last argument supplied to use can be a load complete callback
  618. if (Y.Lang.isFunction(callback)) {
  619. args.pop();
  620. } else {
  621. callback = null;
  622. }
  623. if (Y.Lang.isArray(args[0])) {
  624. args = args[0];
  625. }
  626. if (Y.config.cacheUse) {
  627. while ((name = args[i++])) {
  628. if (!Env._attached[name]) {
  629. provisioned = false;
  630. break;
  631. }
  632. }
  633. if (provisioned) {
  634. if (args.length) {
  635. Y.log('already provisioned: ' + args, 'info', 'yui');
  636. }
  637. Y._notify(callback, ALREADY_DONE, args);
  638. return Y;
  639. }
  640. }
  641. if (Y.config.cacheUse) {
  642. while ((name = args[i++])) {
  643. if (!Env._attached[name]) {
  644. provisioned = false;
  645. break;
  646. }
  647. }
  648. if (provisioned) {
  649. if (args.length) {
  650. Y.log('already provisioned: ' + args, 'info', 'yui');
  651. }
  652. Y._notify(callback, ALREADY_DONE, args);
  653. return Y;
  654. }
  655. }
  656. if (Y._loading) {
  657. Y._useQueue = Y._useQueue || new Y.Queue();
  658. Y._useQueue.add([args, callback]);
  659. } else {
  660. Y._use(args, function(Y, response) {
  661. Y._notify(callback, response, args);
  662. });
  663. }
  664. return Y;
  665. },
  666. /**
  667. * Notify handler from Loader for attachment/load errors
  668. * @method _notify
  669. * @param callback {Function} The callback to pass to the `Y.config.loadErrorFn`
  670. * @param response {Object} The response returned from Loader
  671. * @param args {Array} The aruments passed from Loader
  672. * @private
  673. */
  674. _notify: function(callback, response, args) {
  675. if (!response.success && this.config.loadErrorFn) {
  676. this.config.loadErrorFn.call(this, this, callback, response, args);
  677. } else if (callback) {
  678. try {
  679. callback(this, response);
  680. } catch (e) {
  681. this.error('use callback error', e, args);
  682. }
  683. }
  684. },
  685. /**
  686. * This private method is called from the `use` method queue. To ensure that only one set of loading
  687. * logic is performed at a time.
  688. * @method _use
  689. * @private
  690. * @param args* {String} 1-n modules to bind (uses arguments array).
  691. * @param *callback {Function} callback function executed when
  692. * the instance has the required functionality. If included, it
  693. * must be the last parameter.
  694. */
  695. _use: function(args, callback) {
  696. if (!this.Array) {
  697. this._attach(['yui-base']);
  698. }
  699. var len, loader, handleBoot, handleRLS,
  700. Y = this,
  701. G_ENV = YUI.Env,
  702. mods = G_ENV.mods,
  703. Env = Y.Env,
  704. used = Env._used,
  705. queue = G_ENV._loaderQueue,
  706. firstArg = args[0],
  707. YArray = Y.Array,
  708. config = Y.config,
  709. boot = config.bootstrap,
  710. missing = [],
  711. r = [],
  712. ret = true,
  713. fetchCSS = config.fetchCSS,
  714. process = function(names, skip) {
  715. if (!names.length) {
  716. return;
  717. }
  718. YArray.each(names, function(name) {
  719. // add this module to full list of things to attach
  720. if (!skip) {
  721. r.push(name);
  722. }
  723. // only attach a module once
  724. if (used[name]) {
  725. return;
  726. }
  727. var m = mods[name], req, use;
  728. if (m) {
  729. used[name] = true;
  730. req = m.details.requires;
  731. use = m.details.use;
  732. } else {
  733. // CSS files don't register themselves, see if it has
  734. // been loaded
  735. if (!G_ENV._loaded[VERSION][name]) {
  736. missing.push(name);
  737. } else {
  738. used[name] = true; // probably css
  739. }
  740. }
  741. // make sure requirements are attached
  742. if (req && req.length) {
  743. process(req);
  744. }
  745. // make sure we grab the submodule dependencies too
  746. if (use && use.length) {
  747. process(use, 1);
  748. }
  749. });
  750. },
  751. handleLoader = function(fromLoader) {
  752. var response = fromLoader || {
  753. success: true,
  754. msg: 'not dynamic'
  755. },
  756. redo, origMissing,
  757. ret = true,
  758. data = response.data;
  759. Y._loading = false;
  760. if (data) {
  761. origMissing = missing;
  762. missing = [];
  763. r = [];
  764. process(data);
  765. redo = missing.length;
  766. if (redo) {
  767. if (missing.sort().join() ==
  768. origMissing.sort().join()) {
  769. redo = false;
  770. }
  771. }
  772. }
  773. if (redo && data) {
  774. Y._loading = false;
  775. Y._use(args, function() {
  776. Y.log('Nested use callback: ' + data, 'info', 'yui');
  777. if (Y._attach(data)) {
  778. Y._notify(callback, response, data);
  779. }
  780. });
  781. } else {
  782. if (data) {
  783. // Y.log('attaching from loader: ' + data, 'info', 'yui');
  784. ret = Y._attach(data);
  785. }
  786. if (ret) {
  787. Y._notify(callback, response, args);
  788. }
  789. }
  790. if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
  791. Y._use.apply(Y, Y._useQueue.next());
  792. }
  793. };
  794. // Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui');
  795. // YUI().use('*'); // bind everything available
  796. if (firstArg === '*') {
  797. ret = Y._attach(Y.Object.keys(mods));
  798. if (ret) {
  799. handleLoader();
  800. }
  801. return Y;
  802. }
  803. // Y.log('before loader requirements: ' + args, 'info', 'yui');
  804. // use loader to expand dependencies and sort the
  805. // requirements if it is available.
  806. if (boot && Y.Loader && args.length) {
  807. loader = getLoader(Y);
  808. loader.require(args);
  809. loader.ignoreRegistered = true;
  810. loader.calculate(null, (fetchCSS) ? null : 'js');
  811. args = loader.sorted;
  812. }
  813. // process each requirement and any additional requirements
  814. // the module metadata specifies
  815. process(args);
  816. len = missing.length;
  817. if (len) {
  818. missing = Y.Object.keys(YArray.hash(missing));
  819. len = missing.length;
  820. Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui');
  821. }
  822. // dynamic load
  823. if (boot && len && Y.Loader) {
  824. // Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui');
  825. Y.log('Using Loader', 'info', 'yui');
  826. Y._loading = true;
  827. loader = getLoader(Y);
  828. loader.onEnd = handleLoader;
  829. loader.context = Y;
  830. loader.data = args;
  831. loader.ignoreRegistered = false;
  832. loader.require(args);
  833. loader.insert(null, (fetchCSS) ? null : 'js');
  834. // loader.partial(missing, (fetchCSS) ? null : 'js');
  835. } else if (len && Y.config.use_rls && !YUI.Env.rls_enabled) {
  836. G_ENV._rls_queue = G_ENV._rls_queue || new Y.Queue();
  837. // server side loader service
  838. handleRLS = function(instance, argz) {
  839. var rls_end = function(o) {
  840. handleLoader(o);
  841. instance.rls_advance();
  842. },
  843. rls_url = instance._rls(argz);
  844. if (rls_url) {
  845. Y.log('Fetching RLS url', 'info', 'rls');
  846. instance.rls_oncomplete(function(o) {
  847. rls_end(o);
  848. });
  849. instance.Get.script(rls_url, {
  850. data: argz,
  851. timeout: instance.config.rls_timeout,
  852. onFailure: instance.rls_handleFailure,
  853. onTimeout: instance.rls_handleTimeout
  854. });
  855. } else {
  856. rls_end({
  857. data: argz
  858. });
  859. }
  860. };
  861. G_ENV._rls_queue.add(function() {
  862. Y.log('executing queued rls request', 'info', 'rls');
  863. G_ENV._rls_in_progress = true;
  864. Y.rls_callback = callback;
  865. Y.rls_locals(Y, args, handleRLS);
  866. });
  867. if (!G_ENV._rls_in_progress && G_ENV._rls_queue.size()) {
  868. G_ENV._rls_queue.next()();
  869. }
  870. } else if (boot && len && Y.Get && !Env.bootstrapped) {
  871. Y._loading = true;
  872. handleBoot = function() {
  873. Y._loading = false;
  874. queue.running = false;
  875. Env.bootstrapped = true;
  876. G_ENV._bootstrapping = false;
  877. if (Y._attach(['loader'])) {
  878. Y._use(args, callback);
  879. }
  880. };
  881. if (G_ENV._bootstrapping) {
  882. Y.log('Waiting for loader', 'info', 'yui');
  883. queue.add(handleBoot);
  884. } else {
  885. G_ENV._bootstrapping = true;
  886. Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui');
  887. Y.Get.script(config.base + config.loaderPath, {
  888. onEnd: handleBoot
  889. });
  890. }
  891. } else {
  892. Y.log('Attaching available dependencies: ' + args, 'info', 'yui');
  893. ret = Y._attach(args);
  894. if (ret) {
  895. handleLoader();
  896. }
  897. }
  898. return Y;
  899. },
  900. /**
  901. * Returns the namespace specified and creates it if it doesn't exist
  902. *
  903. * YUI.namespace("property.package");
  904. * YUI.namespace("YAHOO.property.package");
  905. *
  906. * Either of the above would create `YUI.property`, then
  907. * `YUI.property.package` (`YAHOO` is scrubbed out, this is
  908. * to remain compatible with YUI2)
  909. *
  910. * Be careful when naming packages. Reserved words may work in some browsers
  911. * and not others. For instance, the following will fail in Safari:
  912. *
  913. * YUI.namespace("really.long.nested.namespace");
  914. *
  915. * This fails because "long" is a future reserved word in ECMAScript
  916. *
  917. * @method namespace
  918. * @param {string*} arguments 1-n namespaces to create.
  919. * @return {object} A reference to the last namespace object created.
  920. */
  921. namespace: function() {
  922. var a = arguments, o = this, i = 0, j, d, arg;
  923. for (; i < a.length; i++) {
  924. // d = ('' + a[i]).split('.');
  925. arg = a[i];
  926. if (arg.indexOf(PERIOD)) {
  927. d = arg.split(PERIOD);
  928. for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
  929. o[d[j]] = o[d[j]] || {};
  930. o = o[d[j]];
  931. }
  932. } else {
  933. o[arg] = o[arg] || {};
  934. }
  935. }
  936. return o;
  937. },
  938. // this is replaced if the log module is included
  939. log: NOOP,
  940. message: NOOP,
  941. // this is replaced if the dump module is included
  942. dump: function (o) { return ''+o; },
  943. /**
  944. * Report an error. The reporting mechanism is controled by
  945. * the `throwFail` configuration attribute. If throwFail is
  946. * not specified, the message is written to the Logger, otherwise
  947. * a JS error is thrown
  948. * @method error
  949. * @param msg {String} the error message.
  950. * @param e {Error|String} Optional JS error that was caught, or an error string.
  951. * @param data Optional additional info
  952. * and `throwFail` is specified, this error will be re-thrown.
  953. * @return {YUI} this YUI instance.
  954. */
  955. error: function(msg, e, data) {
  956. var Y = this, ret;
  957. if (Y.config.errorFn) {
  958. ret = Y.config.errorFn.apply(Y, arguments);
  959. }
  960. if (Y.config.throwFail && !ret) {
  961. throw (e || new Error(msg));
  962. } else {
  963. Y.message(msg, 'error'); // don't scrub this one
  964. }
  965. return Y;
  966. },
  967. /**
  968. * Generate an id that is unique among all YUI instances
  969. * @method guid
  970. * @param pre {String} optional guid prefix.
  971. * @return {String} the guid.
  972. */
  973. guid: function(pre) {
  974. var id = this.Env._guidp + '_' + (++this.Env._uidx);
  975. return (pre) ? (pre + id) : id;
  976. },
  977. /**
  978. * Returns a `guid` associated with an object. If the object
  979. * does not have one, a new one is created unless `readOnly`
  980. * is specified.
  981. * @method stamp
  982. * @param o {Object} The object to stamp.
  983. * @param readOnly {Boolean} if `true`, a valid guid will only
  984. * be returned if the object has one assigned to it.
  985. * @return {String} The object's guid or null.
  986. */
  987. stamp: function(o, readOnly) {
  988. var uid;
  989. if (!o) {
  990. return o;
  991. }
  992. // IE generates its own unique ID for dom nodes
  993. // The uniqueID property of a document node returns a new ID
  994. if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
  995. uid = o.uniqueID;
  996. } else {
  997. uid = (typeof o === 'string') ? o : o._yuid;
  998. }
  999. if (!uid) {
  1000. uid = this.guid();
  1001. if (!readOnly) {
  1002. try {
  1003. o._yuid = uid;
  1004. } catch (e) {
  1005. uid = null;
  1006. }
  1007. }
  1008. }
  1009. return uid;
  1010. },
  1011. /**
  1012. * Destroys the YUI instance
  1013. * @method destroy
  1014. * @since 3.3.0
  1015. */
  1016. destroy: function() {
  1017. var Y = this;
  1018. if (Y.Event) {
  1019. Y.Event._unload();
  1020. }
  1021. delete instances[Y.id];
  1022. delete Y.Env;
  1023. delete Y.config;
  1024. }
  1025. /**
  1026. * instanceof check for objects that works around
  1027. * memory leak in IE when the item tested is
  1028. * window/document
  1029. * @method instanceOf
  1030. * @since 3.3.0
  1031. */
  1032. };
  1033. YUI.prototype = proto;
  1034. // inheritance utilities are not available yet
  1035. for (prop in proto) {
  1036. if (proto.hasOwnProperty(prop)) {
  1037. YUI[prop] = proto[prop];
  1038. }
  1039. }
  1040. // set up the environment
  1041. YUI._init();
  1042. if (hasWin) {
  1043. // add a window load event at load time so we can capture
  1044. // the case where it fires before dynamic loading is
  1045. // complete.
  1046. add(window, 'load', handleLoad);
  1047. } else {
  1048. handleLoad();
  1049. }
  1050. YUI.Env.add = add;
  1051. YUI.Env.remove = remove;
  1052. /*global exports*/
  1053. // Support the CommonJS method for exporting our single global
  1054. if (typeof exports == 'object') {
  1055. exports.YUI = YUI;
  1056. }
  1057. }());
  1058. /**
  1059. * The config object contains all of the configuration options for
  1060. * the `YUI` instance. This object is supplied by the implementer
  1061. * when instantiating a `YUI` instance. Some properties have default
  1062. * values if they are not supplied by the implementer. This should
  1063. * not be updated directly because some values are cached. Use
  1064. * `applyConfig()` to update the config object on a YUI instance that
  1065. * has already been configured.
  1066. *
  1067. * @class config
  1068. * @static
  1069. */
  1070. /**
  1071. * Allows the YUI seed file to fetch the loader component and library
  1072. * metadata to dynamically load additional dependencies.
  1073. *
  1074. * @property bootstrap
  1075. * @type boolean
  1076. * @default true
  1077. */
  1078. /**
  1079. * Log to the browser console if debug is on and the browser has a
  1080. * supported console.
  1081. *
  1082. * @property useBrowserConsole
  1083. * @type boolean
  1084. * @default true
  1085. */
  1086. /**
  1087. * A hash of log sources that should be logged. If specified, only
  1088. * log messages from these sources will be logged.
  1089. *
  1090. * @property logInclude
  1091. * @type object
  1092. */
  1093. /**
  1094. * A hash of log sources that should be not be logged. If specified,
  1095. * all sources are logged if not on this list.
  1096. *
  1097. * @property logExclude
  1098. * @type object
  1099. */
  1100. /**
  1101. * Set to true if the yui seed file was dynamically loaded in
  1102. * order to bootstrap components relying on the window load event
  1103. * and the `domready` custom event.
  1104. *
  1105. * @property injected
  1106. * @type boolean
  1107. * @default false
  1108. */
  1109. /**
  1110. * If `throwFail` is set, `Y.error` will generate or re-throw a JS Error.
  1111. * Otherwise the failure is logged.
  1112. *
  1113. * @property throwFail
  1114. * @type boolean
  1115. * @default true
  1116. */
  1117. /**
  1118. * The window/frame that this instance should operate in.
  1119. *
  1120. * @property win
  1121. * @type Window
  1122. * @default the window hosting YUI
  1123. */
  1124. /**
  1125. * The document associated with the 'win' configuration.
  1126. *
  1127. * @property doc
  1128. * @type Document
  1129. * @default the document hosting YUI
  1130. */
  1131. /**
  1132. * A list of modules that defines the YUI core (overrides the default).
  1133. *
  1134. * @property core
  1135. * @type string[]
  1136. */
  1137. /**
  1138. * A list of languages in order of preference. This list is matched against
  1139. * the list of available languages in modules that the YUI instance uses to
  1140. * determine the best possible localization of language sensitive modules.
  1141. * Languages are represented using BCP 47 language tags, such as "en-GB" for
  1142. * English as used in the United Kingdom, or "zh-Hans-CN" for simplified
  1143. * Chinese as used in China. The list can be provided as a comma-separated
  1144. * list or as an array.
  1145. *
  1146. * @property lang
  1147. * @type string|string[]
  1148. */
  1149. /**
  1150. * The default date format
  1151. * @property dateFormat
  1152. * @type string
  1153. * @deprecated use configuration in `DataType.Date.format()` instead.
  1154. */
  1155. /**
  1156. * The default locale
  1157. * @property locale
  1158. * @type string
  1159. * @deprecated use `config.lang` instead.
  1160. */
  1161. /**
  1162. * The default interval when polling in milliseconds.
  1163. * @property pollInterval
  1164. * @type int
  1165. * @default 20
  1166. */
  1167. /**
  1168. * The number of dynamic nodes to insert by default before
  1169. * automatically removing them. This applies to script nodes
  1170. * because removing the node will not make the evaluated script
  1171. * unavailable. Dynamic CSS is not auto purged, because removing
  1172. * a linked style sheet will also remove the style definitions.
  1173. * @property purgethreshold
  1174. * @type int
  1175. * @default 20
  1176. */
  1177. /**
  1178. * The default interval when polling in milliseconds.
  1179. * @property windowResizeDelay
  1180. * @type int
  1181. * @default 40
  1182. */
  1183. /**
  1184. * Base directory for dynamic loading
  1185. * @property base
  1186. * @type string
  1187. */
  1188. /*
  1189. * The secure base dir (not implemented)
  1190. * For dynamic loading.
  1191. * @property secureBase
  1192. * @type string
  1193. */
  1194. /**
  1195. * The YUI combo service base dir. Ex: `http://yui.yahooapis.com/combo?`
  1196. * For dynamic loading.
  1197. * @property comboBase
  1198. * @type string
  1199. */
  1200. /**
  1201. * The root path to prepend to module path for the combo service.
  1202. * Ex: 3.0.0b1/build/
  1203. * For dynamic loading.
  1204. * @property root
  1205. * @type string
  1206. */
  1207. /**
  1208. * A filter to apply to result urls. This filter will modify the default
  1209. * path for all modules. The default path for the YUI library is the
  1210. * minified version of the files (e.g., event-min.js). The filter property
  1211. * can be a predefined filter or a custom filter. The valid predefined
  1212. * filters are:
  1213. * <dl>
  1214. * <dt>DEBUG</dt>
  1215. * <dd>Selects the debug versions of the library (e.g., event-debug.js).
  1216. * This option will automatically include the Logger widget</dd>
  1217. * <dt>RAW</dt>
  1218. * <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
  1219. * </dl>
  1220. * You can also define a custom filter, which must be an object literal
  1221. * containing a search expression and a replace string:
  1222. *
  1223. * myFilter: {
  1224. * 'searchExp': "-min\\.js",
  1225. * 'replaceStr': "-debug.js"
  1226. * }
  1227. *
  1228. * For dynamic loading.
  1229. *
  1230. * @property filter
  1231. * @type string|object
  1232. */
  1233. /**
  1234. * The `skin` config let's you configure application level skin
  1235. * customizations. It contains the following attributes which
  1236. * can be specified to override the defaults:
  1237. *
  1238. * // The default skin, which is automatically applied if not
  1239. * // overriden by a component-specific skin definition.
  1240. * // Change this in to apply a different skin globally
  1241. * defaultSkin: 'sam',
  1242. *
  1243. * // This is combined with the loader base property to get
  1244. * // the default root directory for a skin.
  1245. * base: 'assets/skins/',
  1246. *
  1247. * // Any component-specific overrides can be specified here,
  1248. * // making it possible to load different skins for different
  1249. * // components. It is possible to load more than one skin
  1250. * // for a given component as well.
  1251. * overrides: {
  1252. * slider: ['capsule', 'round']
  1253. * }
  1254. *
  1255. * For dynamic loading.
  1256. *
  1257. * @property skin
  1258. */
  1259. /**
  1260. * Hash of per-component filter specification. If specified for a given
  1261. * component, this overrides the filter config.
  1262. *
  1263. * For dynamic loading.
  1264. *
  1265. * @property filters
  1266. */
  1267. /**
  1268. * Use the YUI combo service to reduce the number of http connections
  1269. * required to load your dependencies. Turning this off will
  1270. * disable combo handling for YUI and all module groups configured
  1271. * with a combo service.
  1272. *
  1273. * For dynamic loading.
  1274. *
  1275. * @property combine
  1276. * @type boolean
  1277. * @default true if 'base' is not supplied, false if it is.
  1278. */
  1279. /**
  1280. * A list of modules that should never be dynamically loaded
  1281. *
  1282. * @property ignore
  1283. * @type string[]
  1284. */
  1285. /**
  1286. * A list of modules that should always be loaded when required, even if already
  1287. * present on the page.
  1288. *
  1289. * @property force
  1290. * @type string[]
  1291. */
  1292. /**
  1293. * Node or id for a node that should be used as the insertion point for new
  1294. * nodes. For dynamic loading.
  1295. *
  1296. * @property insertBefore
  1297. * @type string
  1298. */
  1299. /**
  1300. * Object literal containing attributes to add to dynamically loaded script
  1301. * nodes.
  1302. * @property jsAttributes
  1303. * @type string
  1304. */
  1305. /**
  1306. * Object literal containing attributes to add to dynamically loaded link
  1307. * nodes.
  1308. * @property cssAttributes
  1309. * @type string
  1310. */
  1311. /**
  1312. * Number of milliseconds before a timeout occurs when dynamically
  1313. * loading nodes. If not set, there is no timeout.
  1314. * @property timeout
  1315. * @type int
  1316. */
  1317. /**
  1318. * Callback for the 'CSSComplete' event. When dynamically loading YUI
  1319. * components with CSS, this property fires when the CSS is finished
  1320. * loading but script loading is still ongoing. This provides an
  1321. * opportunity to enhance the presentation of a loading page a little
  1322. * bit before the entire loading process is done.
  1323. *
  1324. * @property onCSS
  1325. * @type function
  1326. */
  1327. /**
  1328. * A hash of module definitions to add to the list of YUI components.
  1329. * These components can then be dynamically loaded side by side with
  1330. * YUI via the `use()` method. This is a hash, the key is the module
  1331. * name, and the value is an object literal specifying the metdata
  1332. * for the module. See `Loader.addModule` for the supported module
  1333. * metadata fields. Also see groups, which provides a way to
  1334. * configure the base and combo spec for a set of modules.
  1335. *
  1336. * modules: {
  1337. * mymod1: {
  1338. * requires: ['node'],
  1339. * fullpath: 'http://myserver.mydomain.com/mymod1/mymod1.js'
  1340. * },
  1341. * mymod2: {
  1342. * requires: ['mymod1'],
  1343. * fullpath: 'http://myserver.mydomain.com/mymod2/mymod2.js'
  1344. * }
  1345. * }
  1346. *
  1347. * @property modules
  1348. * @type object
  1349. */
  1350. /**
  1351. * A hash of module group definitions. It for each group you
  1352. * can specify a list of modules and the base path and
  1353. * combo spec to use when dynamically loading the modules.
  1354. *
  1355. * groups: {
  1356. * yui2: {
  1357. * // specify whether or not this group has a combo service
  1358. * combine: true,
  1359. *
  1360. * // the base path for non-combo paths
  1361. * base: 'http://yui.yahooapis.com/2.8.0r4/build/',
  1362. *
  1363. * // the path to the combo service
  1364. * comboBase: 'http://yui.yahooapis.com/combo?',
  1365. *
  1366. * // a fragment to prepend to the path attribute when
  1367. * // when building combo urls
  1368. * root: '2.8.0r4/build/',
  1369. *
  1370. * // the module definitions
  1371. * modules: {
  1372. * yui2_yde: {
  1373. * path: "yahoo-dom-event/yahoo-dom-event.js"
  1374. * },
  1375. * yui2_anim: {
  1376. * path: "animation/animation.js",
  1377. * requires: ['yui2_yde']
  1378. * }
  1379. * }
  1380. * }
  1381. * }
  1382. *
  1383. * @property groups
  1384. * @type object
  1385. */
  1386. /**
  1387. * The loader 'path' attribute to the loader itself. This is combined
  1388. * with the 'base' attribute to dynamically load the loader component
  1389. * when boostrapping with the get utility alone.
  1390. *
  1391. * @property loaderPath
  1392. * @type string
  1393. * @default loader/loader-min.js
  1394. */
  1395. /**
  1396. * Specifies whether or not YUI().use(...) will attempt to load CSS
  1397. * resources at all. Any truthy value will cause CSS dependencies
  1398. * to load when fetching script. The special value 'force' will
  1399. * cause CSS dependencies to be loaded even if no script is needed.
  1400. *
  1401. * @property fetchCSS
  1402. * @type boolean|string
  1403. * @default true
  1404. */
  1405. /**
  1406. * The default gallery version to build gallery module urls
  1407. * @property gallery
  1408. * @type string
  1409. * @since 3.1.0
  1410. */
  1411. /**
  1412. * The default YUI 2 version to build yui2 module urls. This is for
  1413. * intrinsic YUI 2 support via the 2in3 project. Also see the '2in3'
  1414. * config for pulling different revisions of the wrapped YUI 2
  1415. * modules.
  1416. * @since 3.1.0
  1417. * @property yui2
  1418. * @type string
  1419. * @default 2.8.1
  1420. */
  1421. /**
  1422. * The 2in3 project is a deployment of the various versions of YUI 2
  1423. * deployed as first-class YUI 3 modules. Eventually, the wrapper
  1424. * for the modules will change (but the underlying YUI 2 code will
  1425. * be the same), and you can select a particular version of
  1426. * the wrapper modules via this config.
  1427. * @since 3.1.0
  1428. * @property 2in3
  1429. * @type string
  1430. * @default 1
  1431. */
  1432. /**
  1433. * Alternative console log function for use in environments without
  1434. * a supported native console. The function is executed in the
  1435. * YUI instance context.
  1436. * @since 3.1.0
  1437. * @property logFn
  1438. * @type Function
  1439. */
  1440. /**
  1441. * A callback to execute when Y.error is called. It receives the
  1442. * error message and an javascript error object if Y.error was
  1443. * executed because a javascript error was caught. The function
  1444. * is executed in the YUI instance context.
  1445. *
  1446. * @since 3.2.0
  1447. * @property errorFn
  1448. * @type Function
  1449. */
  1450. /**
  1451. * A callback to execute when the loader fails to load one or
  1452. * more resource. This could be because of a script load
  1453. * failure. It can also fail if a javascript module fails
  1454. * to register itself, but only when the 'requireRegistration'
  1455. * is true. If this function is defined, the use() callback will
  1456. * only be called when the loader succeeds, otherwise it always
  1457. * executes unless there was a javascript error when attaching
  1458. * a module.
  1459. *
  1460. * @since 3.3.0
  1461. * @property loadErrorFn
  1462. * @type Function
  1463. */
  1464. /**
  1465. * When set to true, the YUI loader will expect that all modules
  1466. * it is responsible for loading will be first-class YUI modules
  1467. * that register themselves with the YUI global. If this is
  1468. * set to true, loader will fail if the module registration fails
  1469. * to happen after the script is loaded.
  1470. *
  1471. * @since 3.3.0
  1472. * @property requireRegistration
  1473. * @type boolean
  1474. * @default false
  1475. */
  1476. /**
  1477. * Cache serviced use() requests.
  1478. * @since 3.3.0
  1479. * @property cacheUse
  1480. * @type boolean
  1481. * @default true
  1482. * @deprecated no longer used
  1483. */
  1484. /**
  1485. * The parameter defaults for the remote loader service.
  1486. * Requires the rls submodule. The properties that are
  1487. * supported:
  1488. *
  1489. * * `m`: comma separated list of module requirements. This
  1490. * must be the param name even for custom implemetations.
  1491. * * `v`: the version of YUI to load. Defaults to the version
  1492. * of YUI that is being used.
  1493. * * `gv`: the version of the gallery to load (see the gallery config)
  1494. * * `env`: comma separated list of modules already on the page.
  1495. * this must be the param name even for custom implemetations.
  1496. * * `lang`: the languages supported on the page (see the lang config)
  1497. * * `'2in3v'`: the version of the 2in3 wrapper to use (see the 2in3 config).
  1498. * * `'2v'`: the version of yui2 to use in the yui 2in3 wrappers
  1499. * * `filt`: a filter def to apply to the urls (see the filter config).
  1500. * * `filts`: a list of custom filters to apply per module
  1501. * * `tests`: this is a map of conditional module test function id keys
  1502. * with the values of 1 if the test passes, 0 if not. This must be
  1503. * the name of the querystring param in custom templates.
  1504. *
  1505. * @since 3.2.0
  1506. * @property rls
  1507. */
  1508. /**
  1509. * The base path to the remote loader service
  1510. *
  1511. * @since 3.2.0
  1512. * @property rls_base
  1513. */
  1514. /**
  1515. * The template to use for building the querystring portion
  1516. * of the remote loader service url. The default is determined
  1517. * by the rls config -- each property that has a value will be
  1518. * represented.
  1519. *
  1520. * @since 3.2.0
  1521. * @property rls_tmpl
  1522. * @example
  1523. * m={m}&v={v}&env={env}&lang={lang}&filt={filt}&tests={tests}
  1524. *
  1525. */
  1526. /**
  1527. * Configure the instance to use a remote loader service instead of
  1528. * the client loader.
  1529. *
  1530. * @since 3.2.0
  1531. * @property use_rls
  1532. */
  1533. YUI.add('yui-base', function(Y) {
  1534. /*
  1535. * YUI stub
  1536. * @module yui
  1537. * @submodule yui-base
  1538. */
  1539. /**
  1540. * The YUI module contains the components required for building the YUI
  1541. * seed file. This includes the script loading mechanism, a simple queue,
  1542. * and the core utilities for the library.
  1543. * @module yui
  1544. * @submodule yui-base
  1545. */
  1546. /**
  1547. * Provides core language utilites and extensions used throughout YUI.
  1548. *
  1549. * @class Lang
  1550. * @static
  1551. */
  1552. var L = Y.Lang || (Y.Lang = {}),
  1553. STRING_PROTO = String.prototype,
  1554. TOSTRING = Object.prototype.toString,
  1555. TYPES = {
  1556. 'undefined' : 'undefined',
  1557. 'number' : 'number',
  1558. 'boolean' : 'boolean',
  1559. 'string' : 'string',
  1560. '[object Function]': 'function',
  1561. '[object RegExp]' : 'regexp',
  1562. '[object Array]' : 'array',
  1563. '[object Date]' : 'date',
  1564. '[object Error]' : 'error'
  1565. },
  1566. SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
  1567. TRIMREGEX = /^\s+|\s+$/g,
  1568. // If either MooTools or Prototype is on the page, then there's a chance that we
  1569. // can't trust "native" language features to actually be native. When this is
  1570. // the case, we take the safe route and fall back to our own non-native
  1571. // implementation.
  1572. win = Y.config.win,
  1573. unsafeNatives = win && !!(win.MooTools || win.Prototype);
  1574. /**
  1575. * Determines whether or not the provided item is an array.
  1576. *
  1577. * Returns `false` for array-like collections such as the function `arguments`
  1578. * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
  1579. * test for an array-like collection.
  1580. *
  1581. * @method isArray
  1582. * @param o The object to test.
  1583. * @return {boolean} true if o is an array.
  1584. * @static
  1585. */
  1586. L.isArray = (!unsafeNatives && Array.isArray) || function (o) {
  1587. return L.type(o) === 'array';
  1588. };
  1589. /**
  1590. * Determines whether or not the provided item is a boolean.
  1591. * @method isBoolean
  1592. * @static
  1593. * @param o The object to test.
  1594. * @return {boolean} true if o is a boolean.
  1595. */
  1596. L.isBoolean = function(o) {
  1597. return typeof o === 'boolean';
  1598. };
  1599. /**
  1600. * <p>
  1601. * Determines whether or not the provided item is a function.
  1602. * Note: Internet Explorer thinks certain functions are objects:
  1603. * </p>
  1604. *
  1605. * <pre>
  1606. * var obj = document.createElement("object");
  1607. * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
  1608. * &nbsp;
  1609. * var input = document.createElement("input"); // append to body
  1610. * Y.Lang.isFunction(input.focus) // reports false in IE
  1611. * </pre>
  1612. *
  1613. * <p>
  1614. * You will have to implement additional tests if these functions
  1615. * matter to you.
  1616. * </p>
  1617. *
  1618. * @method isFunction
  1619. * @static
  1620. * @param o The object to test.
  1621. * @return {boolean} true if o is a function.
  1622. */
  1623. L.isFunction = function(o) {
  1624. return L.type(o) === 'function';
  1625. };
  1626. /**
  1627. * Determines whether or not the supplied item is a date instance.
  1628. * @method isDate
  1629. * @static
  1630. * @param o The object to test.
  1631. * @return {boolean} true if o is a date.
  1632. */
  1633. L.isDate = function(o) {
  1634. return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
  1635. };
  1636. /**
  1637. * Determines whether or not the provided item is null.
  1638. * @method isNull
  1639. * @static
  1640. * @param o The object to test.
  1641. * @return {boolean} true if o is null.
  1642. */
  1643. L.isNull = function(o) {
  1644. return o === null;
  1645. };
  1646. /**
  1647. * Determines whether or not the provided item is a legal number.
  1648. * @method isNumber
  1649. * @static
  1650. * @param o The object to test.
  1651. * @return {boolean} true if o is a number.
  1652. */
  1653. L.isNumber = function(o) {
  1654. return typeof o === 'number' && isFinite(o);
  1655. };
  1656. /**
  1657. * Determines whether or not the provided item is of type object
  1658. * or function. Note that arrays are also objects, so
  1659. * <code>Y.Lang.isObject([]) === true</code>.
  1660. * @method isObject
  1661. * @static
  1662. * @param o The object to test.
  1663. * @param failfn {boolean} fail if the input is a function.
  1664. * @return {boolean} true if o is an object.
  1665. * @see isPlainObject
  1666. */
  1667. L.isObject = function(o, failfn) {
  1668. var t = typeof o;
  1669. return (o && (t === 'object' ||
  1670. (!failfn && (t === 'function' || L.isFunction(o))))) || false;
  1671. };
  1672. /**
  1673. * Determines whether or not the provided item is a string.
  1674. * @method isString
  1675. * @static
  1676. * @param o The object to test.
  1677. * @return {boolean} true if o is a string.
  1678. */
  1679. L.isString = function(o) {
  1680. return typeof o === 'string';
  1681. };
  1682. /**
  1683. * Determines whether or not the provided item is undefined.
  1684. * @method isUndefined
  1685. * @static
  1686. * @param o The object to test.
  1687. * @return {boolean} true if o is undefined.
  1688. */
  1689. L.isUndefined = function(o) {
  1690. return typeof o === 'undefined';
  1691. };
  1692. /**
  1693. * Returns a string without any leading or trailing whitespace. If
  1694. * the input is not a string, the input will be returned untouched.
  1695. * @method trim
  1696. * @static
  1697. * @param s {string} the string to trim.
  1698. * @return {string} the trimmed string.
  1699. */
  1700. L.trim = STRING_PROTO.trim ? function(s) {
  1701. return s && s.trim ? s.trim() : s;
  1702. } : function (s) {
  1703. try {
  1704. return s.replace(TRIMREGEX, '');
  1705. } catch (e) {
  1706. return s;
  1707. }
  1708. };
  1709. /**
  1710. * Returns a string without any leading whitespace.
  1711. * @method trimLeft
  1712. * @static
  1713. * @param s {string} the string to trim.
  1714. * @return {string} the trimmed string.
  1715. */
  1716. L.trimLeft = STRING_PROTO.trimLeft ? function (s) {
  1717. return s.trimLeft();
  1718. } : function (s) {
  1719. return s.replace(/^\s+/, '');
  1720. };
  1721. /**
  1722. * Returns a string without any trailing whitespace.
  1723. * @method trimRight
  1724. * @static
  1725. * @param s {string} the string to trim.
  1726. * @return {string} the trimmed string.
  1727. */
  1728. L.trimRight = STRING_PROTO.trimRight ? function (s) {
  1729. return s.trimRight();
  1730. } : function (s) {
  1731. return s.replace(/\s+$/, '');
  1732. };
  1733. /**
  1734. * A convenience method for detecting a legitimate non-null value.
  1735. * Returns false for null/undefined/NaN, true for other values,
  1736. * including 0/false/''
  1737. * @method isValue
  1738. * @static
  1739. * @param o The item to test.
  1740. * @return {boolean} true if it is not null/undefined/NaN || false.
  1741. */
  1742. L.isValue = function(o) {
  1743. var t = L.type(o);
  1744. switch (t) {
  1745. case 'number':
  1746. return isFinite(o);
  1747. case 'null': // fallthru
  1748. case 'undefined':
  1749. return false;
  1750. default:
  1751. return !!t;
  1752. }
  1753. };
  1754. /**
  1755. * <p>
  1756. * Returns a string representing the type of the item passed in.
  1757. * </p>
  1758. *
  1759. * <p>
  1760. * Known issues:
  1761. * </p>
  1762. *
  1763. * <ul>
  1764. * <li>
  1765. * <code>typeof HTMLElementCollection</code> returns function in Safari, but
  1766. * <code>Y.type()</code> reports object, which could be a good thing --
  1767. * but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
  1768. * </li>
  1769. * </ul>
  1770. *
  1771. * @method type
  1772. * @param o the item to test.
  1773. * @return {string} the detected type.
  1774. * @static
  1775. */
  1776. L.type = function(o) {
  1777. return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
  1778. };
  1779. /**
  1780. * Lightweight version of <code>Y.substitute</code>. Uses the same template
  1781. * structure as <code>Y.substitute</code>, but doesn't support recursion,
  1782. * auto-object coersion, or formats.
  1783. * @method sub
  1784. * @param {string} s String to be modified.
  1785. * @param {object} o Object containing replacement values.
  1786. * @return {string} the substitute result.
  1787. * @static
  1788. * @since 3.2.0
  1789. */
  1790. L.sub = function(s, o) {
  1791. return s.replace ? s.replace(SUBREGEX, function (match, key) {
  1792. return L.isUndefined(o[key]) ? match : o[key];
  1793. }) : s;
  1794. };
  1795. /**
  1796. * Returns the current time in milliseconds.
  1797. *
  1798. * @method now
  1799. * @return {Number} Current time in milliseconds.
  1800. * @static
  1801. * @since 3.3.0
  1802. */
  1803. L.now = Date.now || function () {
  1804. return new Date().getTime();
  1805. };
  1806. /**
  1807. * The YUI module contains the components required for building the YUI seed
  1808. * file. This includes the script loading mechanism, a simple queue, and the
  1809. * core utilities for the library.
  1810. *
  1811. * @module yui
  1812. * @submodule yui-base
  1813. */
  1814. var Lang = Y.Lang,
  1815. Native = Array.prototype,
  1816. hasOwn = Object.prototype.hasOwnProperty;
  1817. /**
  1818. Provides utility methods for working with arrays. Additional array helpers can
  1819. be found in the `collection` and `array-extras` modules.
  1820. `Y.Array(thing)` returns a native array created from _thing_. Depending on
  1821. _thing_'s type, one of the following will happen:
  1822. * Arrays are returned unmodified unless a non-zero _startIndex_ is
  1823. specified.
  1824. * Array-like collections (see `Array.test()`) are converted to arrays.
  1825. * For everything else, a new array is created with _thing_ as the sole
  1826. item.
  1827. Note: elements that are also collections, such as `<form>` and `<select>`
  1828. elements, are not automatically converted to arrays. To force a conversion,
  1829. pass `true` as the value of the _force_ parameter.
  1830. @class Array
  1831. @constructor
  1832. @param {Any} thing The thing to arrayify.
  1833. @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
  1834. collection, a subset of items starting at the specified index will be
  1835. returned.
  1836. @param {Boolean} [force=false] If `true`, _thing_ will be treated as an
  1837. array-like collection no matter what.
  1838. @return {Array} A native array created from _thing_, according to the rules
  1839. described above.
  1840. **/
  1841. function YArray(thing, startIndex, force) {
  1842. var len, result;
  1843. startIndex || (startIndex = 0);
  1844. if (force || YArray.test(thing)) {
  1845. // IE throws when trying to slice HTMLElement collections.
  1846. try {
  1847. return Native.slice.call(thing, startIndex);
  1848. } catch (ex) {
  1849. result = [];
  1850. for (len = thing.length; startIndex < len; ++startIndex) {
  1851. result.push(thing[startIndex]);
  1852. }
  1853. return result;
  1854. }
  1855. }
  1856. return [thing];
  1857. }
  1858. Y.Array = YArray;
  1859. /**
  1860. Evaluates _obj_ to determine if it's an array, an array-like collection, or
  1861. something else. This is useful when working with the function `arguments`
  1862. collection and `HTMLElement` collections.
  1863. Note: This implementation doesn't consider elements that are also
  1864. collections, such as `<form>` and `<select>`, to be array-like.
  1865. @method test
  1866. @param {Object} obj Object to test.
  1867. @return {Number} A number indicating the results of the test:
  1868. * 0: Neither an array nor an array-like collection.
  1869. * 1: Real array.
  1870. * 2: Array-like collection.
  1871. @static
  1872. **/
  1873. YArray.test = function (obj) {
  1874. var result = 0;
  1875. if (Lang.isArray(obj)) {
  1876. result = 1;
  1877. } else if (Lang.isObject(obj)) {
  1878. try {
  1879. // indexed, but no tagName (element) or alert (window),
  1880. // or functions without apply/call (Safari
  1881. // HTMLElementCollection bug).
  1882. if ('length' in obj && !obj.tagName && !obj.alert && !obj.apply) {
  1883. result = 2;
  1884. }
  1885. } catch (ex) {}
  1886. }
  1887. return result;
  1888. };
  1889. /**
  1890. Dedupes an array of strings, returning an array that's guaranteed to contain
  1891. only one copy of a given string.
  1892. This method differs from `Array.unique()` in that it's optimized for use only
  1893. with strings, whereas `unique` may be used with other types (but is slower).
  1894. Using `dedupe()` with non-string values may result in unexpected behavior.
  1895. @method dedupe
  1896. @param {String[]} array Array of strings to dedupe.
  1897. @return {Array} Deduped copy of _array_.
  1898. @static
  1899. @since 3.4.0
  1900. **/
  1901. YArray.dedupe = function (array) {
  1902. var hash = {},
  1903. results = [],
  1904. i, item, len;
  1905. for (i = 0, len = array.length; i < len; ++i) {
  1906. item = array[i];
  1907. if (!hasOwn.call(hash, item)) {
  1908. hash[item] = 1;
  1909. results.push(item);
  1910. }
  1911. }
  1912. return results;
  1913. };
  1914. /**
  1915. Executes the supplied function on each item in the array. This method wraps
  1916. the native ES5 `Array.forEach()` method if available.
  1917. @method each
  1918. @param {Array} array Array to iterate.
  1919. @param {Function} fn Function to execute on each item in the array. The function
  1920. will receive the following arguments:
  1921. @param {Any} fn.item Current array item.
  1922. @param {Number} fn.index Current array index.
  1923. @param {Array} fn.array Array being iterated.
  1924. @param {Object} [thisObj] `this` object to use when calling _fn_.
  1925. @return {YUI} The YUI instance.
  1926. @static
  1927. **/
  1928. YArray.each = YArray.forEach = Native.forEach ? function (array, fn, thisObj) {
  1929. Native.forEach.call(array || [], fn, thisObj || Y);
  1930. return Y;
  1931. } : function (array, fn, thisObj) {
  1932. for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
  1933. if (i in array) {
  1934. fn.call(thisObj || Y, array[i], i, array);
  1935. }
  1936. }
  1937. return Y;
  1938. };
  1939. /**
  1940. Alias for `each()`.
  1941. @method forEach
  1942. @static
  1943. **/
  1944. /**
  1945. Returns an object using the first array as keys and the second as values. If
  1946. the second array is not provided, or if it doesn't contain the same number of
  1947. values as the first array, then `true` will be used in place of the missing
  1948. values.
  1949. @example
  1950. Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
  1951. // => {a: 'foo', b: 'bar', c: true}
  1952. @method hash
  1953. @param {String[]} keys Array of strings to use as keys.
  1954. @param {Array} [values] Array to use as values.
  1955. @return {Object} Hash using the first array as keys and the second as values.
  1956. @static
  1957. **/
  1958. YArray.hash = function (keys, values) {
  1959. var hash = {},
  1960. vlen = (values && values.length) || 0,
  1961. i, len;
  1962. for (i = 0, len = keys.length; i < len; ++i) {
  1963. if (i in keys) {
  1964. hash[keys[i]] = vlen > i && i in values ? values[i] : true;
  1965. }
  1966. }
  1967. return hash;
  1968. };
  1969. /**
  1970. Returns the index of the first item in the array that's equal (using a strict
  1971. equality check) to the specified _value_, or `-1` if the value isn't found.
  1972. This method wraps the native ES5 `Array.indexOf()` method if available.
  1973. @method indexOf
  1974. @param {Array} array Array to search.
  1975. @param {Any} value Value to search for.
  1976. @return {Number} Index of the item strictly equal to _value_, or `-1` if not
  1977. found.
  1978. @static
  1979. **/
  1980. YArray.indexOf = Native.indexOf ? function (array, value) {
  1981. // TODO: support fromIndex
  1982. return Native.indexOf.call(array, value);
  1983. } : function (array, value) {
  1984. for (var i = 0, len = array.length; i < len; ++i) {
  1985. if (array[i] === value) {
  1986. return i;
  1987. }
  1988. }
  1989. return -1;
  1990. };
  1991. /**
  1992. Numeric sort convenience function.
  1993. The native `Array.prototype.sort()` function converts values to strings and
  1994. sorts them in lexicographic order, which is unsuitable for sorting numeric
  1995. values. Provide `Array.numericSort` as a custom sort function when you want
  1996. to sort values in numeric order.
  1997. @example
  1998. [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
  1999. // => [4, 8, 15, 16, 23, 42]
  2000. @method numericSort
  2001. @param {Number} a First value to compare.
  2002. @param {Number} b Second value to compare.
  2003. @return {Number} Difference between _a_ and _b_.
  2004. @static
  2005. **/
  2006. YArray.numericSort = function (a, b) {
  2007. return a - b;
  2008. };
  2009. /**
  2010. Executes the supplied function on each item in the array. Returning a truthy
  2011. value from the function will stop the processing of remaining items.
  2012. @method some
  2013. @param {Array} array Array to iterate over.
  2014. @param {Function} fn Function to execute on each item. The function will receive
  2015. the following arguments:
  2016. @param {Any} fn.value Current array item.
  2017. @param {Number} fn.index Current array index.
  2018. @param {Array} fn.array Array being iterated over.
  2019. @param {Object} [thisObj] `this` object to use when calling _fn_.
  2020. @return {Boolean} `true` if the function returns a truthy value on any of the
  2021. items in the array; `false` otherwise.
  2022. @static
  2023. **/
  2024. YArray.some = Native.some ? function (array, fn, thisObj) {
  2025. return Native.some.call(array, fn, thisObj);
  2026. } : function (array, fn, thisObj) {
  2027. for (var i = 0, len = array.length; i < len; ++i) {
  2028. if (i in array && fn.call(thisObj, array[i], i, array)) {
  2029. return true;
  2030. }
  2031. }
  2032. return false;
  2033. };
  2034. /**
  2035. * The YUI module contains the components required for building the YUI
  2036. * seed file. This includes the script loading mechanism, a simple queue,
  2037. * and the core utilities for the library.
  2038. * @module yui
  2039. * @submodule yui-base
  2040. */
  2041. /**
  2042. * A simple FIFO queue. Items are added to the Queue with add(1..n items) and
  2043. * removed using next().
  2044. *
  2045. * @class Queue
  2046. * @constructor
  2047. * @param {MIXED} item* 0..n items to seed the queue.
  2048. */
  2049. function Queue() {
  2050. this._init();
  2051. this.add.apply(this, arguments);
  2052. }
  2053. Queue.prototype = {
  2054. /**
  2055. * Initialize the queue
  2056. *
  2057. * @method _init
  2058. * @protected
  2059. */
  2060. _init: function() {
  2061. /**
  2062. * The collection of enqueued items
  2063. *
  2064. * @property _q
  2065. * @type Array
  2066. * @protected
  2067. */
  2068. this._q = [];
  2069. },
  2070. /**
  2071. * Get the next item in the queue. FIFO support
  2072. *
  2073. * @method next
  2074. * @return {MIXED} the next item in the queue.
  2075. */
  2076. next: function() {
  2077. return this._q.shift();
  2078. },
  2079. /**
  2080. * Get the last in the queue. LIFO support.
  2081. *
  2082. * @method last
  2083. * @return {MIXED} the last item in the queue.
  2084. */
  2085. last: function() {
  2086. return this._q.pop();
  2087. },
  2088. /**
  2089. * Add 0..n items to the end of the queue.
  2090. *
  2091. * @method add
  2092. * @param {MIXED} item* 0..n items.
  2093. * @return {object} this queue.
  2094. */
  2095. add: function() {
  2096. this._q.push.apply(this._q, arguments);
  2097. return this;
  2098. },
  2099. /**
  2100. * Returns the current number of queued items.
  2101. *
  2102. * @method size
  2103. * @return {Number} The size.
  2104. */
  2105. size: function() {
  2106. return this._q.length;
  2107. }
  2108. };
  2109. Y.Queue = Queue;
  2110. YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
  2111. /**
  2112. The YUI module contains the components required for building the YUI seed file.
  2113. This includes the script loading mechanism, a simple queue, and the core
  2114. utilities for the library.
  2115. @module yui
  2116. @submodule yui-base
  2117. **/
  2118. var CACHED_DELIMITER = '__',
  2119. hasOwn = Object.prototype.hasOwnProperty,
  2120. isObject = Y.Lang.isObject;
  2121. /**
  2122. Returns a wrapper for a function which caches the return value of that function,
  2123. keyed off of the combined string representation of the argument values provided
  2124. when the wrapper is called.
  2125. Calling this function again with the same arguments will return the cached value
  2126. rather than executing the wrapped function.
  2127. Note that since the cache is keyed off of the string representation of arguments
  2128. passed to the wrapper function, arguments that aren't strings and don't provide
  2129. a meaningful `toString()` method may result in unexpected caching behavior. For
  2130. example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
  2131. string `[object Object]` when used as a cache key.
  2132. @method cached
  2133. @param {Function} source The function to memoize.
  2134. @param {Object} [cache={}] Object in which to store cached values. You may seed
  2135. this object with pre-existing cached values if desired.
  2136. @param {any} [refetch] If supplied, this value is compared with the cached value
  2137. using a `==` comparison. If the values are equal, the wrapped function is
  2138. executed again even though a cached value exists.
  2139. @return {Function} Wrapped function.
  2140. @for YUI
  2141. **/
  2142. Y.cached = function (source, cache, refetch) {
  2143. cache || (cache = {});
  2144. return function (arg) {
  2145. var key = arguments.length > 1 ?
  2146. Array.prototype.join.call(arguments, CACHED_DELIMITER) :
  2147. arg.toString();
  2148. if (!(key in cache) || (refetch && cache[key] == refetch)) {
  2149. cache[key] = source.apply(source, arguments);
  2150. }
  2151. return cache[key];
  2152. };
  2153. };
  2154. /**
  2155. Returns a new object containing all of the properties of all the supplied
  2156. objects. The properties from later objects will overwrite those in earlier
  2157. objects.
  2158. Passing in a single object will create a shallow copy of it. For a deep copy,
  2159. use `clone()`.
  2160. @method merge
  2161. @param {Object} objects* One or more objects to merge.
  2162. @return {Object} A new merged object.
  2163. **/
  2164. Y.merge = function () {
  2165. var args = arguments,
  2166. i = 0,
  2167. len = args.length,
  2168. result = {};
  2169. for (; i < len; ++i) {
  2170. Y.mix(result, args[i], true);
  2171. }
  2172. return result;
  2173. };
  2174. /**
  2175. Mixes _supplier_'s properties into _receiver_. Properties will not be
  2176. overwritten or merged unless the _overwrite_ or _merge_ parameters are `true`,
  2177. respectively.
  2178. In the default mode (0), only properties the supplier owns are copied (prototype
  2179. properties are not copied). The following copying modes are available:
  2180. * `0`: _Default_. Object to object.
  2181. * `1`: Prototype to prototype.
  2182. * `2`: Prototype to prototype and object to object.
  2183. * `3`: Prototype to object.
  2184. * `4`: Object to prototype.
  2185. @method mix
  2186. @param {Function|Object} receiver The object or function to receive the mixed
  2187. properties.
  2188. @param {Function|Object} supplier The object or function supplying the
  2189. properties to be mixed.
  2190. @param {Boolean} [overwrite=false] If `true`, properties that already exist
  2191. on the receiver will be overwritten with properties from the supplier.
  2192. @param {String[]} [whitelist] An array of property names to copy. If
  2193. specified, only the whitelisted properties will be copied, and all others
  2194. will be ignored.
  2195. @param {Int} [mode=0] Mix mode to use. See above for available modes.
  2196. @param {Boolean} [merge=false] If `true`, objects and arrays that already
  2197. exist on the receiver will have the corresponding object/array from the
  2198. supplier merged into them, rather than being skipped or overwritten. When
  2199. both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
  2200. @return {Function|Object|YUI} The receiver, or the YUI instance if the
  2201. specified receiver is falsy.
  2202. **/
  2203. Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
  2204. var alwaysOverwrite, exists, from, i, key, len, to;
  2205. // If no supplier is given, we return the receiver. If no receiver is given,
  2206. // we return Y. Returning Y doesn't make much sense to me, but it's
  2207. // grandfathered in for backcompat reasons.
  2208. if (!receiver || !supplier) {
  2209. return receiver || Y;
  2210. }
  2211. if (mode) {
  2212. // In mode 2 (prototype to prototype and object to object), we recurse
  2213. // once To Do the proto to proto mix. The object to object mix will be
  2214. // handled later on.
  2215. if (mode === 2) {
  2216. Y.mix(receiver.prototype, supplier.prototype, overwrite,
  2217. whitelist, 0, merge);
  2218. }
  2219. // Depending on which mode is specified, we may be copying from or to
  2220. // the prototypes of the supplier and receiver.
  2221. from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
  2222. to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
  2223. // If either the supplier or receiver doesn't actually have a
  2224. // prototype property, then we could end up with an undefined `from`
  2225. // or `to`. If that happens, we abort and return the receiver.
  2226. if (!from || !to) {
  2227. return receiver;
  2228. }
  2229. } else {
  2230. from = supplier;
  2231. to = receiver;
  2232. }
  2233. // If `overwrite` is truthy and `merge` is falsy, then we can skip a call
  2234. // to `hasOwnProperty` on each iteration and save some time.
  2235. alwaysOverwrite = overwrite && !merge;
  2236. if (whitelist) {
  2237. for (i = 0, len = whitelist.length; i < len; ++i) {
  2238. key = whitelist[i];
  2239. // We call `Object.prototype.hasOwnProperty` instead of calling
  2240. // `hasOwnProperty` on the object itself, since the object's
  2241. // `hasOwnProperty` method may have been overridden or removed.
  2242. // Also, some native objects don't implement a `hasOwnProperty`
  2243. // method.
  2244. if (!hasOwn.call(from, key)) {
  2245. continue;
  2246. }
  2247. exists = alwaysOverwrite ? false : hasOwn.call(to, key);
  2248. if (merge && exists && isObject(to[key], true)
  2249. && isObject(from[key], true)) {
  2250. // If we're in merge mode, and the key is present on both
  2251. // objects, and the value on both objects is either an object or
  2252. // an array (but not a function), then we recurse to merge the
  2253. // `from` value into the `to` value instead of overwriting it.
  2254. //
  2255. // Note: It's intentional that the whitelist isn't passed to the
  2256. // recursive call here. This is legacy behavior that lots of
  2257. // code still depends on.
  2258. Y.mix(to[key], from[key], overwrite, null, 0, merge);
  2259. } else if (overwrite || !exists) {
  2260. // We're not in merge mode, so we'll only copy the `from` value
  2261. // to the `to` value if we're in overwrite mode or if the
  2262. // current key doesn't exist on the `to` object.
  2263. to[key] = from[key];
  2264. }
  2265. }
  2266. } else {
  2267. for (key in from) {
  2268. // The code duplication here is for runtime performance reasons.
  2269. // Combining whitelist and non-whitelist operations into a single
  2270. // loop or breaking the shared logic out into a function both result
  2271. // in worse performance, and Y.mix is critical enough that the byte
  2272. // tradeoff is worth it.
  2273. if (!hasOwn.call(from, key)) {
  2274. continue;
  2275. }
  2276. exists = alwaysOverwrite ? false : hasOwn.call(to, key);
  2277. if (merge && exists && isObject(to[key], true)
  2278. && isObject(from[key], true)) {
  2279. Y.mix(to[key], from[key], overwrite, null, 0, merge);
  2280. } else if (overwrite || !exists) {
  2281. to[key] = from[key];
  2282. }
  2283. }
  2284. // If this is an IE browser with the JScript enumeration bug, force
  2285. // enumeration of the buggy properties by making a recursive call with
  2286. // the buggy properties as the whitelist.
  2287. if (Y.Object._hasEnumBug) {
  2288. Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
  2289. }
  2290. }
  2291. return receiver;
  2292. };
  2293. /**
  2294. * The YUI module contains the components required for building the YUI
  2295. * seed file. This includes the script loading mechanism, a simple queue,
  2296. * and the core utilities for the library.
  2297. * @module yui
  2298. * @submodule yui-base
  2299. */
  2300. /**
  2301. * Adds utilities to the YUI instance for working with objects.
  2302. *
  2303. * @class Object
  2304. */
  2305. var hasOwn = Object.prototype.hasOwnProperty,
  2306. // If either MooTools or Prototype is on the page, then there's a chance that we
  2307. // can't trust "native" language features to actually be native. When this is
  2308. // the case, we take the safe route and fall back to our own non-native
  2309. // implementations.
  2310. win = Y.config.win,
  2311. unsafeNatives = win && !!(win.MooTools || win.Prototype),
  2312. UNDEFINED, // <-- Note the comma. We're still declaring vars.
  2313. /**
  2314. * Returns a new object that uses _obj_ as its prototype. This method wraps the
  2315. * native ES5 `Object.create()` method if available, but doesn't currently
  2316. * pass through `Object.create()`'s second argument (properties) in order to
  2317. * ensure compatibility with older browsers.
  2318. *
  2319. * @method ()
  2320. * @param {Object} obj Prototype object.
  2321. * @return {Object} New object using _obj_ as its prototype.
  2322. * @static
  2323. */
  2324. O = Y.Object = (!unsafeNatives && Object.create) ? function (obj) {
  2325. // We currently wrap the native Object.create instead of simply aliasing it
  2326. // to ensure consistency with our fallback shim, which currently doesn't
  2327. // support Object.create()'s second argument (properties). Once we have a
  2328. // safe fallback for the properties arg, we can stop wrapping
  2329. // Object.create().
  2330. return Object.create(obj);
  2331. } : (function () {
  2332. // Reusable constructor function for the Object.create() shim.
  2333. function F() {}
  2334. // The actual shim.
  2335. return function (obj) {
  2336. F.prototype = obj;
  2337. return new F();
  2338. };
  2339. }()),
  2340. /**
  2341. * Property names that IE doesn't enumerate in for..in loops, even when they
  2342. * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
  2343. * manually enumerate these properties.
  2344. *
  2345. * @property _forceEnum
  2346. * @type String[]
  2347. * @protected
  2348. * @static
  2349. */
  2350. forceEnum = O._forceEnum = [
  2351. 'hasOwnProperty',
  2352. 'isPrototypeOf',
  2353. 'propertyIsEnumerable',
  2354. 'toString',
  2355. 'toLocaleString',
  2356. 'valueOf'
  2357. ],
  2358. /**
  2359. * `true` if this browser has the JScript enumeration bug that prevents
  2360. * enumeration of the properties named in the `_forceEnum` array, `false`
  2361. * otherwise.
  2362. *
  2363. * See:
  2364. * - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
  2365. * - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
  2366. *
  2367. * @property _hasEnumBug
  2368. * @type {Boolean}
  2369. * @protected
  2370. * @static
  2371. */
  2372. hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
  2373. /**
  2374. * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
  2375. * exists only on _obj_'s prototype. This is essentially a safer version of
  2376. * `obj.hasOwnProperty()`.
  2377. *
  2378. * @method owns
  2379. * @param {Object} obj Object to test.
  2380. * @param {String} key Property name to look for.
  2381. * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
  2382. * @static
  2383. */
  2384. owns = O.owns = function (obj, key) {
  2385. return !!obj && hasOwn.call(obj, key);
  2386. }; // <-- End of var declarations.
  2387. /**
  2388. * Alias for `owns()`.
  2389. *
  2390. * @method hasKey
  2391. * @param {Object} obj Object to test.
  2392. * @param {String} key Property name to look for.
  2393. * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
  2394. * @static
  2395. */
  2396. O.hasKey = owns;
  2397. /**
  2398. * Returns an array containing the object's enumerable keys. Does not include
  2399. * prototype keys or non-enumerable keys.
  2400. *
  2401. * Note that keys are returned in enumeration order (that is, in the same order
  2402. * that they would be enumerated by a `for-in` loop), which may not be the same
  2403. * as the order in which they were defined.
  2404. *
  2405. * This method is an alias for the native ES5 `Object.keys()` method if
  2406. * available.
  2407. *
  2408. * @example
  2409. *
  2410. * Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
  2411. * // => ['a', 'b', 'c']
  2412. *
  2413. * @method keys
  2414. * @param {Object} obj An object.
  2415. * @return {String[]} Array of keys.
  2416. * @static
  2417. */
  2418. O.keys = (!unsafeNatives && Object.keys) || function (obj) {
  2419. if (!Y.Lang.isObject(obj)) {
  2420. throw new TypeError('Object.keys called on a non-object');
  2421. }
  2422. var keys = [],
  2423. i, key, len;
  2424. for (key in obj) {
  2425. if (owns(obj, key)) {
  2426. keys.push(key);
  2427. }
  2428. }
  2429. if (hasEnumBug) {
  2430. for (i = 0, len = forceEnum.length; i < len; ++i) {
  2431. key = forceEnum[i];
  2432. if (owns(obj, key)) {
  2433. keys.push(key);
  2434. }
  2435. }
  2436. }
  2437. return keys;
  2438. };
  2439. /**
  2440. * Returns an array containing the values of the object's enumerable keys.
  2441. *
  2442. * Note that values are returned in enumeration order (that is, in the same
  2443. * order that they would be enumerated by a `for-in` loop), which may not be the
  2444. * same as the order in which they were defined.
  2445. *
  2446. * @example
  2447. *
  2448. * Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
  2449. * // => ['foo', 'bar', 'baz']
  2450. *
  2451. * @method values
  2452. * @param {Object} obj An object.
  2453. * @return {Array} Array of values.
  2454. * @static
  2455. */
  2456. O.values = function (obj) {
  2457. var keys = O.keys(obj),
  2458. i = 0,
  2459. len = keys.length,
  2460. values = [];
  2461. for (; i < len; ++i) {
  2462. values.push(obj[keys[i]]);
  2463. }
  2464. return values;
  2465. };
  2466. /**
  2467. * Returns the number of enumerable keys owned by an object.
  2468. *
  2469. * @method size
  2470. * @param {Object} obj An object.
  2471. * @return {Number} The object's size.
  2472. * @static
  2473. */
  2474. O.size = function (obj) {
  2475. return O.keys(obj).length;
  2476. };
  2477. /**
  2478. * Returns `true` if the object owns an enumerable property with the specified
  2479. * value.
  2480. *
  2481. * @method hasValue
  2482. * @param {Object} obj An object.
  2483. * @param {any} value The value to search for.
  2484. * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
  2485. * @static
  2486. */
  2487. O.hasValue = function (obj, value) {
  2488. return Y.Array.indexOf(O.values(obj), value) > -1;
  2489. };
  2490. /**
  2491. * Executes a function on each enumerable property in _obj_. The function
  2492. * receives the value, the key, and the object itself as parameters (in that
  2493. * order).
  2494. *
  2495. * By default, only properties owned by _obj_ are enumerated. To include
  2496. * prototype properties, set the _proto_ parameter to `true`.
  2497. *
  2498. * @method each
  2499. * @param {Object} obj Object to enumerate.
  2500. * @param {Function} fn Function to execute on each enumerable property.
  2501. * @param {mixed} fn.value Value of the current property.
  2502. * @param {String} fn.key Key of the current property.
  2503. * @param {Object} fn.obj Object being enumerated.
  2504. * @param {Object} [thisObj] `this` object to use when calling _fn_.
  2505. * @param {Boolean} [proto=false] Include prototype properties.
  2506. * @return {YUI} the YUI instance.
  2507. * @chainable
  2508. * @static
  2509. */
  2510. O.each = function (obj, fn, thisObj, proto) {
  2511. var key;
  2512. for (key in obj) {
  2513. if (proto || owns(obj, key)) {
  2514. fn.call(thisObj || Y, obj[key], key, obj);
  2515. }
  2516. }
  2517. return Y;
  2518. };
  2519. /**
  2520. * Executes a function on each enumerable property in _obj_, but halts if the
  2521. * function returns a truthy value. The function receives the value, the key,
  2522. * and the object itself as paramters (in that order).
  2523. *
  2524. * By default, only properties owned by _obj_ are enumerated. To include
  2525. * prototype properties, set the _proto_ parameter to `true`.
  2526. *
  2527. * @method some
  2528. * @param {Object} obj Object to enumerate.
  2529. * @param {Function} fn Function to execute on each enumerable property.
  2530. * @param {mixed} fn.value Value of the current property.
  2531. * @param {String} fn.key Key of the current property.
  2532. * @param {Object} fn.obj Object being enumerated.
  2533. * @param {Object} [thisObj] `this` object to use when calling _fn_.
  2534. * @param {Boolean} [proto=false] Include prototype properties.
  2535. * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
  2536. * `false` otherwise.
  2537. * @static
  2538. */
  2539. O.some = function (obj, fn, thisObj, proto) {
  2540. var key;
  2541. for (key in obj) {
  2542. if (proto || owns(obj, key)) {
  2543. if (fn.call(thisObj || Y, obj[key], key, obj)) {
  2544. return true;
  2545. }
  2546. }
  2547. }
  2548. return false;
  2549. };
  2550. /**
  2551. * Retrieves the sub value at the provided path,
  2552. * from the value object provided.
  2553. *
  2554. * @method getValue
  2555. * @static
  2556. * @param o The object from which to extract the property value.
  2557. * @param path {Array} A path array, specifying the object traversal path
  2558. * from which to obtain the sub value.
  2559. * @return {Any} The value stored in the path, undefined if not found,
  2560. * undefined if the source is not an object. Returns the source object
  2561. * if an empty path is provided.
  2562. */
  2563. O.getValue = function(o, path) {
  2564. if (!Y.Lang.isObject(o)) {
  2565. return UNDEFINED;
  2566. }
  2567. var i,
  2568. p = Y.Array(path),
  2569. l = p.length;
  2570. for (i = 0; o !== UNDEFINED && i < l; i++) {
  2571. o = o[p[i]];
  2572. }
  2573. return o;
  2574. };
  2575. /**
  2576. * Sets the sub-attribute value at the provided path on the
  2577. * value object. Returns the modified value object, or
  2578. * undefined if the path is invalid.
  2579. *
  2580. * @method setValue
  2581. * @static
  2582. * @param o The object on which to set the sub value.
  2583. * @param path {Array} A path array, specifying the object traversal path
  2584. * at which to set the sub value.
  2585. * @param val {Any} The new value for the sub-attribute.
  2586. * @return {Object} The modified object, with the new sub value set, or
  2587. * undefined, if the path was invalid.
  2588. */
  2589. O.setValue = function(o, path, val) {
  2590. var i,
  2591. p = Y.Array(path),
  2592. leafIdx = p.length - 1,
  2593. ref = o;
  2594. if (leafIdx >= 0) {
  2595. for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
  2596. ref = ref[p[i]];
  2597. }
  2598. if (ref !== UNDEFINED) {
  2599. ref[p[i]] = val;
  2600. } else {
  2601. return UNDEFINED;
  2602. }
  2603. }
  2604. return o;
  2605. };
  2606. /**
  2607. * Returns `true` if the object has no enumerable properties of its own.
  2608. *
  2609. * @method isEmpty
  2610. * @param {Object} obj An object.
  2611. * @return {Boolean} `true` if the object is empty.
  2612. * @static
  2613. * @since 3.2.0
  2614. */
  2615. O.isEmpty = function (obj) {
  2616. return !O.keys(obj).length;
  2617. };
  2618. /**
  2619. * The YUI module contains the components required for building the YUI seed
  2620. * file. This includes the script loading mechanism, a simple queue, and the
  2621. * core utilities for the library.
  2622. * @module yui
  2623. * @submodule yui-base
  2624. */
  2625. /**
  2626. * YUI user agent detection.
  2627. * Do not fork for a browser if it can be avoided. Use feature detection when
  2628. * you can. Use the user agent as a last resort. For all fields listed
  2629. * as @type float, UA stores a version number for the browser engine,
  2630. * 0 otherwise. This value may or may not map to the version number of
  2631. * the browser using the engine. The value is presented as a float so
  2632. * that it can easily be used for boolean evaluation as well as for
  2633. * looking for a particular range of versions. Because of this,
  2634. * some of the granularity of the version info may be lost. The fields that
  2635. * are @type string default to null. The API docs list the values that
  2636. * these fields can have.
  2637. * @class UA
  2638. * @static
  2639. */
  2640. /**
  2641. * Static method for parsing the UA string. Defaults to assigning it's value to Y.UA
  2642. * @static
  2643. * @method Env.parseUA
  2644. * @param {String} subUA Parse this UA string instead of navigator.userAgent
  2645. * @returns {Object} The Y.UA object
  2646. */
  2647. YUI.Env.parseUA = function(subUA) {
  2648. var numberify = function(s) {
  2649. var c = 0;
  2650. return parseFloat(s.replace(/\./g, function() {
  2651. return (c++ == 1) ? '' : '.';
  2652. }));
  2653. },
  2654. win = Y.config.win,
  2655. nav = win && win.navigator,
  2656. o = {
  2657. /**
  2658. * Internet Explorer version number or 0. Example: 6
  2659. * @property ie
  2660. * @type float
  2661. * @static
  2662. */
  2663. ie: 0,
  2664. /**
  2665. * Opera version number or 0. Example: 9.2
  2666. * @property opera
  2667. * @type float
  2668. * @static
  2669. */
  2670. opera: 0,
  2671. /**
  2672. * Gecko engine revision number. Will evaluate to 1 if Gecko
  2673. * is detected but the revision could not be found. Other browsers
  2674. * will be 0. Example: 1.8
  2675. * <pre>
  2676. * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7
  2677. * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
  2678. * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
  2679. * Firefox 3.0 <-- 1.9
  2680. * Firefox 3.5 <-- 1.91
  2681. * </pre>
  2682. * @property gecko
  2683. * @type float
  2684. * @static
  2685. */
  2686. gecko: 0,
  2687. /**
  2688. * AppleWebKit version. KHTML browsers that are not WebKit browsers
  2689. * will evaluate to 1, other browsers 0. Example: 418.9
  2690. * <pre>
  2691. * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
  2692. * latest available for Mac OSX 10.3.
  2693. * Safari 2.0.2: 416 <-- hasOwnProperty introduced
  2694. * Safari 2.0.4: 418 <-- preventDefault fixed
  2695. * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
  2696. * different versions of webkit
  2697. * Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been
  2698. * updated, but not updated
  2699. * to the latest patch.
  2700. * Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native
  2701. * SVG and many major issues fixed).
  2702. * Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic
  2703. * update from 2.x via the 10.4.11 OS patch.
  2704. * Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event.
  2705. * yahoo.com user agent hack removed.
  2706. * </pre>
  2707. * http://en.wikipedia.org/wiki/Safari_version_history
  2708. * @property webkit
  2709. * @type float
  2710. * @static
  2711. */
  2712. webkit: 0,
  2713. /**
  2714. * Safari will be detected as webkit, but this property will also
  2715. * be populated with the Safari version number
  2716. * @property safari
  2717. * @type float
  2718. * @static
  2719. */
  2720. safari: 0,
  2721. /**
  2722. * Chrome will be detected as webkit, but this property will also
  2723. * be populated with the Chrome version number
  2724. * @property chrome
  2725. * @type float
  2726. * @static
  2727. */
  2728. chrome: 0,
  2729. /**
  2730. * The mobile property will be set to a string containing any relevant
  2731. * user agent information when a modern mobile browser is detected.
  2732. * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
  2733. * devices with the WebKit-based browser, and Opera Mini.
  2734. * @property mobile
  2735. * @type string
  2736. * @default null
  2737. * @static
  2738. */
  2739. mobile: null,
  2740. /**
  2741. * Adobe AIR version number or 0. Only populated if webkit is detected.
  2742. * Example: 1.0
  2743. * @property air
  2744. * @type float
  2745. */
  2746. air: 0,
  2747. /**
  2748. * Detects Apple iPad's OS version
  2749. * @property ipad
  2750. * @type float
  2751. * @static
  2752. */
  2753. ipad: 0,
  2754. /**
  2755. * Detects Apple iPhone's OS version
  2756. * @property iphone
  2757. * @type float
  2758. * @static
  2759. */
  2760. iphone: 0,
  2761. /**
  2762. * Detects Apples iPod's OS version
  2763. * @property ipod
  2764. * @type float
  2765. * @static
  2766. */
  2767. ipod: 0,
  2768. /**
  2769. * General truthy check for iPad, iPhone or iPod
  2770. * @property ios
  2771. * @type float
  2772. * @default null
  2773. * @static
  2774. */
  2775. ios: null,
  2776. /**
  2777. * Detects Googles Android OS version
  2778. * @property android
  2779. * @type float
  2780. * @static
  2781. */
  2782. android: 0,
  2783. /**
  2784. * Detects Palms WebOS version
  2785. * @property webos
  2786. * @type float
  2787. * @static
  2788. */
  2789. webos: 0,
  2790. /**
  2791. * Google Caja version number or 0.
  2792. * @property caja
  2793. * @type float
  2794. */
  2795. caja: nav && nav.cajaVersion,
  2796. /**
  2797. * Set to true if the page appears to be in SSL
  2798. * @property secure
  2799. * @type boolean
  2800. * @static
  2801. */
  2802. secure: false,
  2803. /**
  2804. * The operating system. Currently only detecting windows or macintosh
  2805. * @property os
  2806. * @type string
  2807. * @default null
  2808. * @static
  2809. */
  2810. os: null
  2811. },
  2812. ua = subUA || nav && nav.userAgent,
  2813. loc = win && win.location,
  2814. href = loc && loc.href,
  2815. m;
  2816. o.secure = href && (href.toLowerCase().indexOf('https') === 0);
  2817. if (ua) {
  2818. if ((/windows|win32/i).test(ua)) {
  2819. o.os = 'windows';
  2820. } else if ((/macintosh/i).test(ua)) {
  2821. o.os = 'macintosh';
  2822. } else if ((/rhino/i).test(ua)) {
  2823. o.os = 'rhino';
  2824. }
  2825. // Modern KHTML browsers should qualify as Safari X-Grade
  2826. if ((/KHTML/).test(ua)) {
  2827. o.webkit = 1;
  2828. }
  2829. // Modern WebKit browsers are at least X-Grade
  2830. m = ua.match(/AppleWebKit\/([^\s]*)/);
  2831. if (m && m[1]) {
  2832. o.webkit = numberify(m[1]);
  2833. o.safari = o.webkit;
  2834. // Mobile browser check
  2835. if (/ Mobile\//.test(ua)) {
  2836. o.mobile = 'Apple'; // iPhone or iPod Touch
  2837. m = ua.match(/OS ([^\s]*)/);
  2838. if (m && m[1]) {
  2839. m = numberify(m[1].replace('_', '.'));
  2840. }
  2841. o.ios = m;
  2842. o.ipad = o.ipod = o.iphone = 0;
  2843. m = ua.match(/iPad|iPod|iPhone/);
  2844. if (m && m[0]) {
  2845. o[m[0].toLowerCase()] = o.ios;
  2846. }
  2847. } else {
  2848. m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
  2849. if (m) {
  2850. // Nokia N-series, webOS, ex: NokiaN95
  2851. o.mobile = m[0];
  2852. }
  2853. if (/webOS/.test(ua)) {
  2854. o.mobile = 'WebOS';
  2855. m = ua.match(/webOS\/([^\s]*);/);
  2856. if (m && m[1]) {
  2857. o.webos = numberify(m[1]);
  2858. }
  2859. }
  2860. if (/ Android/.test(ua)) {
  2861. if (/Mobile/.test(ua)) {
  2862. o.mobile = 'Android';
  2863. }
  2864. m = ua.match(/Android ([^\s]*);/);
  2865. if (m && m[1]) {
  2866. o.android = numberify(m[1]);
  2867. }
  2868. }
  2869. }
  2870. m = ua.match(/Chrome\/([^\s]*)/);
  2871. if (m && m[1]) {
  2872. o.chrome = numberify(m[1]); // Chrome
  2873. o.safari = 0; //Reset safari back to 0
  2874. } else {
  2875. m = ua.match(/AdobeAIR\/([^\s]*)/);
  2876. if (m) {
  2877. o.air = m[0]; // Adobe AIR 1.0 or better
  2878. }
  2879. }
  2880. }
  2881. if (!o.webkit) { // not webkit
  2882. // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
  2883. m = ua.match(/Opera[\s\/]([^\s]*)/);
  2884. if (m && m[1]) {
  2885. o.opera = numberify(m[1]);
  2886. m = ua.match(/Version\/([^\s]*)/);
  2887. if (m && m[1]) {
  2888. o.opera = numberify(m[1]); // opera 10+
  2889. }
  2890. m = ua.match(/Opera Mini[^;]*/);
  2891. if (m) {
  2892. o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
  2893. }
  2894. } else { // not opera or webkit
  2895. m = ua.match(/MSIE\s([^;]*)/);
  2896. if (m && m[1]) {
  2897. o.ie = numberify(m[1]);
  2898. } else { // not opera, webkit, or ie
  2899. m = ua.match(/Gecko\/([^\s]*)/);
  2900. if (m) {
  2901. o.gecko = 1; // Gecko detected, look for revision
  2902. m = ua.match(/rv:([^\s\)]*)/);
  2903. if (m && m[1]) {
  2904. o.gecko = numberify(m[1]);
  2905. }
  2906. }
  2907. }
  2908. }
  2909. }
  2910. }
  2911. YUI.Env.UA = o;
  2912. return o;
  2913. };
  2914. Y.UA = YUI.Env.UA || YUI.Env.parseUA();
  2915. YUI.Env.aliases = {
  2916. "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
  2917. "app": ["controller","model","model-list","view"],
  2918. "attribute": ["attribute-base","attribute-complex"],
  2919. "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
  2920. "base": ["base-base","base-pluginhost","base-build"],
  2921. "cache": ["cache-base","cache-offline","cache-plugin"],
  2922. "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
  2923. "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
  2924. "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
  2925. "datatable": ["datatable-base","datatable-datasource","datatable-sort","datatable-scroll"],
  2926. "datatype": ["datatype-number","datatype-date","datatype-xml"],
  2927. "datatype-date": ["datatype-date-parse","datatype-date-format"],
  2928. "datatype-number": ["datatype-number-parse","datatype-number-format"],
  2929. "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
  2930. "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
  2931. "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
  2932. "editor": ["frame","selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
  2933. "event": ["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside"],
  2934. "event-custom": ["event-custom-base","event-custom-complex"],
  2935. "event-gestures": ["event-flick","event-move"],
  2936. "highlight": ["highlight-base","highlight-accentfold"],
  2937. "history": ["history-base","history-hash","history-hash-ie","history-html5"],
  2938. "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
  2939. "json": ["json-parse","json-stringify"],
  2940. "loader": ["loader-base","loader-rollup","loader-yui3"],
  2941. "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
  2942. "pluginhost": ["pluginhost-base","pluginhost-config"],
  2943. "querystring": ["querystring-parse","querystring-stringify"],
  2944. "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
  2945. "resize": ["resize-base","resize-proxy","resize-constrain"],
  2946. "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
  2947. "text": ["text-accentfold","text-wordbreak"],
  2948. "widget": ["widget-base","widget-htmlparser","widget-uievents","widget-skin"]
  2949. };
  2950. }, '3.4.0' );
  2951. YUI.add('get', function(Y) {
  2952. /**
  2953. * Provides a mechanism to fetch remote resources and
  2954. * insert them into a document.
  2955. * @module yui
  2956. * @submodule get
  2957. */
  2958. /**
  2959. * Fetches and inserts one or more script or link nodes into the document
  2960. * @class Get
  2961. * @static
  2962. */
  2963. var ua = Y.UA,
  2964. L = Y.Lang,
  2965. TYPE_JS = 'text/javascript',
  2966. TYPE_CSS = 'text/css',
  2967. STYLESHEET = 'stylesheet',
  2968. SCRIPT = 'script',
  2969. AUTOPURGE = 'autopurge',
  2970. UTF8 = 'utf-8',
  2971. LINK = 'link',
  2972. ASYNC = 'async',
  2973. ALL = true,
  2974. // FireFox does not support the onload event for link nodes, so
  2975. // there is no way to make the css requests synchronous. This means
  2976. // that the css rules in multiple files could be applied out of order
  2977. // in this browser if a later request returns before an earlier one.
  2978. // Safari too.
  2979. ONLOAD_SUPPORTED = {
  2980. script: ALL,
  2981. css: !(ua.webkit || ua.gecko)
  2982. },
  2983. /**
  2984. * hash of queues to manage multiple requests
  2985. * @property queues
  2986. * @private
  2987. */
  2988. queues = {},
  2989. /**
  2990. * queue index used to generate transaction ids
  2991. * @property qidx
  2992. * @type int
  2993. * @private
  2994. */
  2995. qidx = 0,
  2996. /**
  2997. * interal property used to prevent multiple simultaneous purge
  2998. * processes
  2999. * @property purging
  3000. * @type boolean
  3001. * @private
  3002. */
  3003. purging,
  3004. /**
  3005. * Clear timeout state
  3006. *
  3007. * @method _clearTimeout
  3008. * @param {Object} q Queue data
  3009. * @private
  3010. */
  3011. _clearTimeout = function(q) {
  3012. var timer = q.timer;
  3013. if (timer) {
  3014. clearTimeout(timer);
  3015. q.timer = null;
  3016. }
  3017. },
  3018. /**
  3019. * Generates an HTML element, this is not appended to a document
  3020. * @method _node
  3021. * @param {string} type the type of element.
  3022. * @param {Object} attr the fixed set of attribute for the type.
  3023. * @param {Object} custAttrs optional Any custom attributes provided by the user.
  3024. * @param {Window} win optional window to create the element in.
  3025. * @return {HTMLElement} the generated node.
  3026. * @private
  3027. */
  3028. _node = function(type, attr, custAttrs, win) {
  3029. var w = win || Y.config.win,
  3030. d = w.document,
  3031. n = d.createElement(type),
  3032. i;
  3033. if (custAttrs) {
  3034. Y.mix(attr, custAttrs);
  3035. }
  3036. for (i in attr) {
  3037. if (attr[i] && attr.hasOwnProperty(i)) {
  3038. n.setAttribute(i, attr[i]);
  3039. }
  3040. }
  3041. return n;
  3042. },
  3043. /**
  3044. * Generates a link node
  3045. * @method _linkNode
  3046. * @param {string} url the url for the css file.
  3047. * @param {Window} win optional window to create the node in.
  3048. * @param {object} attributes optional attributes collection to apply to the
  3049. * new node.
  3050. * @return {HTMLElement} the generated node.
  3051. * @private
  3052. */
  3053. _linkNode = function(url, win, attributes) {
  3054. return _node(LINK, {
  3055. id: Y.guid(),
  3056. type: TYPE_CSS,
  3057. rel: STYLESHEET,
  3058. href: url
  3059. }, attributes, win);
  3060. },
  3061. /**
  3062. * Generates a script node
  3063. * @method _scriptNode
  3064. * @param {string} url the url for the script file.
  3065. * @param {Window} win optional window to create the node in.
  3066. * @param {object} attributes optional attributes collection to apply to the
  3067. * new node.
  3068. * @return {HTMLElement} the generated node.
  3069. * @private
  3070. */
  3071. _scriptNode = function(url, win, attributes) {
  3072. return _node(SCRIPT, {
  3073. id: Y.guid(),
  3074. type: TYPE_JS,
  3075. src: url
  3076. }, attributes, win);
  3077. },
  3078. /**
  3079. * Returns the data payload for callback functions.
  3080. * @method _returnData
  3081. * @param {object} q the queue.
  3082. * @param {string} msg the result message.
  3083. * @param {string} result the status message from the request.
  3084. * @return {object} the state data from the request.
  3085. * @private
  3086. */
  3087. _returnData = function(q, msg, result) {
  3088. return {
  3089. tId: q.tId,
  3090. win: q.win,
  3091. data: q.data,
  3092. nodes: q.nodes,
  3093. msg: msg,
  3094. statusText: result,
  3095. purge: function() {
  3096. _purge(this.tId);
  3097. }
  3098. };
  3099. },
  3100. /**
  3101. * The transaction is finished
  3102. * @method _end
  3103. * @param {string} id the id of the request.
  3104. * @param {string} msg the result message.
  3105. * @param {string} result the status message from the request.
  3106. * @private
  3107. */
  3108. _end = function(id, msg, result) {
  3109. var q = queues[id],
  3110. onEnd = q && q.onEnd;
  3111. q.finished = true;
  3112. if (onEnd) {
  3113. onEnd.call(q.context, _returnData(q, msg, result));
  3114. }
  3115. },
  3116. /**
  3117. * The request failed, execute fail handler with whatever
  3118. * was accomplished. There isn't a failure case at the
  3119. * moment unless you count aborted transactions
  3120. * @method _fail
  3121. * @param {string} id the id of the request
  3122. * @private
  3123. */
  3124. _fail = function(id, msg) {
  3125. Y.log('get failure: ' + msg, 'warn', 'get');
  3126. var q = queues[id],
  3127. onFailure = q.onFailure;
  3128. _clearTimeout(q);
  3129. if (onFailure) {
  3130. onFailure.call(q.context, _returnData(q, msg));
  3131. }
  3132. _end(id, msg, 'failure');
  3133. },
  3134. /**
  3135. * Abort the transaction
  3136. *
  3137. * @method _abort
  3138. * @param {Object} id
  3139. * @private
  3140. */
  3141. _abort = function(id) {
  3142. _fail(id, 'transaction ' + id + ' was aborted');
  3143. },
  3144. /**
  3145. * The request is complete, so executing the requester's callback
  3146. * @method _complete
  3147. * @param {string} id the id of the request.
  3148. * @private
  3149. */
  3150. _complete = function(id) {
  3151. Y.log("Finishing transaction " + id, "info", "get");
  3152. var q = queues[id],
  3153. onSuccess = q.onSuccess;
  3154. _clearTimeout(q);
  3155. if (q.aborted) {
  3156. _abort(id);
  3157. } else {
  3158. if (onSuccess) {
  3159. onSuccess.call(q.context, _returnData(q));
  3160. }
  3161. // 3.3.0 had undefined msg for this path.
  3162. _end(id, undefined, 'OK');
  3163. }
  3164. },
  3165. /**
  3166. * Get node reference, from string
  3167. *
  3168. * @method _getNodeRef
  3169. * @param {String|HTMLElement} nId The node id to find. If an HTMLElement is passed in, it will be returned.
  3170. * @param {String} tId Queue id, used to determine document for queue
  3171. * @private
  3172. */
  3173. _getNodeRef = function(nId, tId) {
  3174. var q = queues[tId],
  3175. n = (L.isString(nId)) ? q.win.document.getElementById(nId) : nId;
  3176. if (!n) {
  3177. _fail(tId, 'target node not found: ' + nId);
  3178. }
  3179. return n;
  3180. },
  3181. /**
  3182. * Removes the nodes for the specified queue
  3183. * @method _purge
  3184. * @param {string} tId the transaction id.
  3185. * @private
  3186. */
  3187. _purge = function(tId) {
  3188. var nodes, doc, parent, sibling, node, attr, insertBefore,
  3189. i, l,
  3190. q = queues[tId];
  3191. if (q) {
  3192. nodes = q.nodes;
  3193. l = nodes.length;
  3194. // TODO: Why is node.parentNode undefined? Which forces us To Do this...
  3195. /*
  3196. doc = q.win.document;
  3197. parent = doc.getElementsByTagName('head')[0];
  3198. insertBefore = q.insertBefore || doc.getElementsByTagName('base')[0];
  3199. if (insertBefore) {
  3200. sibling = _getNodeRef(insertBefore, tId);
  3201. if (sibling) {
  3202. parent = sibling.parentNode;
  3203. }
  3204. }
  3205. */
  3206. for (i = 0; i < l; i++) {
  3207. node = nodes[i];
  3208. parent = node.parentNode;
  3209. if (node.clearAttributes) {
  3210. node.clearAttributes();
  3211. } else {
  3212. // This destroys parentNode ref, so we hold onto it above first.
  3213. for (attr in node) {
  3214. if (node.hasOwnProperty(attr)) {
  3215. delete node[attr];
  3216. }
  3217. }
  3218. }
  3219. parent.removeChild(node);
  3220. }
  3221. }
  3222. q.nodes = [];
  3223. },
  3224. /**
  3225. * Progress callback
  3226. *
  3227. * @method _progress
  3228. * @param {string} id The id of the request.
  3229. * @param {string} The url which just completed.
  3230. * @private
  3231. */
  3232. _progress = function(id, url) {
  3233. var q = queues[id],
  3234. onProgress = q.onProgress,
  3235. o;
  3236. if (onProgress) {
  3237. o = _returnData(q);
  3238. o.url = url;
  3239. onProgress.call(q.context, o);
  3240. }
  3241. },
  3242. /**
  3243. * Timeout detected
  3244. * @method _timeout
  3245. * @param {string} id the id of the request.
  3246. * @private
  3247. */
  3248. _timeout = function(id) {
  3249. Y.log('Timeout ' + id, 'info', 'get');
  3250. var q = queues[id],
  3251. onTimeout = q.onTimeout;
  3252. if (onTimeout) {
  3253. onTimeout.call(q.context, _returnData(q));
  3254. }
  3255. _end(id, 'timeout', 'timeout');
  3256. },
  3257. /**
  3258. * onload callback
  3259. * @method _loaded
  3260. * @param {string} id the id of the request.
  3261. * @return {string} the result.
  3262. * @private
  3263. */
  3264. _loaded = function(id, url) {
  3265. var q = queues[id],
  3266. sync = (q && !q.async);
  3267. if (!q) {
  3268. return;
  3269. }
  3270. if (sync) {
  3271. _clearTimeout(q);
  3272. }
  3273. _progress(id, url);
  3274. // TODO: Cleaning up flow to have a consistent end point
  3275. // !q.finished check is for the async case,
  3276. // where scripts may still be loading when we've
  3277. // already aborted. Ideally there should be a single path
  3278. // for this.
  3279. if (!q.finished) {
  3280. if (q.aborted) {
  3281. _abort(id);
  3282. } else {
  3283. if ((--q.remaining) === 0) {
  3284. _complete(id);
  3285. } else if (sync) {
  3286. _next(id);
  3287. }
  3288. }
  3289. }
  3290. },
  3291. /**
  3292. * Detects when a node has been loaded. In the case of
  3293. * script nodes, this does not guarantee that contained
  3294. * script is ready to use.
  3295. * @method _trackLoad
  3296. * @param {string} type the type of node to track.
  3297. * @param {HTMLElement} n the node to track.
  3298. * @param {string} id the id of the request.
  3299. * @param {string} url the url that is being loaded.
  3300. * @private
  3301. */
  3302. _trackLoad = function(type, n, id, url) {
  3303. // TODO: Can we massage this to use ONLOAD_SUPPORTED[type]?
  3304. // IE supports the readystatechange event for script and css nodes
  3305. // Opera only for script nodes. Opera support onload for script
  3306. // nodes, but this doesn't fire when there is a load failure.
  3307. // The onreadystatechange appears to be a better way to respond
  3308. // to both success and failure.
  3309. if (ua.ie) {
  3310. n.onreadystatechange = function() {
  3311. var rs = this.readyState;
  3312. if ('loaded' === rs || 'complete' === rs) {
  3313. // Y.log(id + " onreadstatechange " + url, "info", "get");
  3314. n.onreadystatechange = null;
  3315. _loaded(id, url);
  3316. }
  3317. };
  3318. } else if (ua.webkit) {
  3319. // webkit prior to 3.x is no longer supported
  3320. if (type === SCRIPT) {
  3321. // Safari 3.x supports the load event for script nodes (DOM2)
  3322. n.addEventListener('load', function() {
  3323. _loaded(id, url);
  3324. }, false);
  3325. }
  3326. } else {
  3327. // FireFox and Opera support onload (but not DOM2 in FF) handlers for
  3328. // script nodes. Opera, but not FF, supports the onload event for link nodes.
  3329. n.onload = function() {
  3330. // Y.log(id + " onload " + url, "info", "get");
  3331. _loaded(id, url);
  3332. };
  3333. n.onerror = function(e) {
  3334. _fail(id, e + ': ' + url);
  3335. };
  3336. }
  3337. },
  3338. _insertInDoc = function(node, id, win) {
  3339. // Add it to the head or insert it before 'insertBefore'.
  3340. // Work around IE bug if there is a base tag.
  3341. var q = queues[id],
  3342. doc = win.document,
  3343. insertBefore = q.insertBefore || doc.getElementsByTagName('base')[0],
  3344. sibling;
  3345. if (insertBefore) {
  3346. sibling = _getNodeRef(insertBefore, id);
  3347. if (sibling) {
  3348. Y.log('inserting before: ' + insertBefore, 'info', 'get');
  3349. sibling.parentNode.insertBefore(node, sibling);
  3350. }
  3351. } else {
  3352. // 3.3.0 assumed head is always around.
  3353. doc.getElementsByTagName('head')[0].appendChild(node);
  3354. }
  3355. },
  3356. /**
  3357. * Loads the next item for a given request
  3358. * @method _next
  3359. * @param {string} id the id of the request.
  3360. * @return {string} the result.
  3361. * @private
  3362. */
  3363. _next = function(id) {
  3364. // Assigning out here for readability
  3365. var q = queues[id],
  3366. type = q.type,
  3367. attrs = q.attributes,
  3368. win = q.win,
  3369. timeout = q.timeout,
  3370. node,
  3371. url;
  3372. if (q.url.length > 0) {
  3373. url = q.url.shift();
  3374. Y.log('attempting to load ' + url, 'info', 'get');
  3375. // !q.timer ensures that this only happens once for async
  3376. if (timeout && !q.timer) {
  3377. q.timer = setTimeout(function() {
  3378. _timeout(id);
  3379. }, timeout);
  3380. }
  3381. if (type === SCRIPT) {
  3382. node = _scriptNode(url, win, attrs);
  3383. } else {
  3384. node = _linkNode(url, win, attrs);
  3385. }
  3386. // add the node to the queue so we can return it in the callback
  3387. q.nodes.push(node);
  3388. _trackLoad(type, node, id, url);
  3389. _insertInDoc(node, id, win);
  3390. if (!ONLOAD_SUPPORTED[type]) {
  3391. _loaded(id, url);
  3392. }
  3393. if (q.async) {
  3394. // For sync, the _next call is chained in _loaded
  3395. _next(id);
  3396. }
  3397. }
  3398. },
  3399. /**
  3400. * Removes processed queues and corresponding nodes
  3401. * @method _autoPurge
  3402. * @private
  3403. */
  3404. _autoPurge = function() {
  3405. if (purging) {
  3406. return;
  3407. }
  3408. purging = true;
  3409. var i, q;
  3410. for (i in queues) {
  3411. if (queues.hasOwnProperty(i)) {
  3412. q = queues[i];
  3413. if (q.autopurge && q.finished) {
  3414. _purge(q.tId);
  3415. delete queues[i];
  3416. }
  3417. }
  3418. }
  3419. purging = false;
  3420. },
  3421. /**
  3422. * Saves the state for the request and begins loading
  3423. * the requested urls
  3424. * @method queue
  3425. * @param {string} type the type of node to insert.
  3426. * @param {string} url the url to load.
  3427. * @param {object} opts the hash of options for this request.
  3428. * @return {object} transaction object.
  3429. * @private
  3430. */
  3431. _queue = function(type, url, opts) {
  3432. opts = opts || {};
  3433. var id = 'q' + (qidx++),
  3434. thresh = opts.purgethreshold || Y.Get.PURGE_THRESH,
  3435. q;
  3436. if (qidx % thresh === 0) {
  3437. _autoPurge();
  3438. }
  3439. // Merge to protect opts (grandfathered in).
  3440. q = queues[id] = Y.merge(opts);
  3441. // Avoid mix, merge overhead. Known set of props.
  3442. q.tId = id;
  3443. q.type = type;
  3444. q.url = url;
  3445. q.finished = false;
  3446. q.nodes = [];
  3447. q.win = q.win || Y.config.win;
  3448. q.context = q.context || q;
  3449. q.autopurge = (AUTOPURGE in q) ? q.autopurge : (type === SCRIPT) ? true : false;
  3450. q.attributes = q.attributes || {};
  3451. q.attributes.charset = opts.charset || q.attributes.charset || UTF8;
  3452. if (ASYNC in q && type === SCRIPT) {
  3453. q.attributes.async = q.async;
  3454. }
  3455. q.url = (L.isString(q.url)) ? [q.url] : q.url;
  3456. // TODO: Do we really need to account for this developer error?
  3457. // If the url is undefined, this is probably a trailing comma problem in IE.
  3458. if (!q.url[0]) {
  3459. q.url.shift();
  3460. Y.log('skipping empty url');
  3461. }
  3462. q.remaining = q.url.length;
  3463. _next(id);
  3464. return {
  3465. tId: id
  3466. };
  3467. };
  3468. Y.Get = {
  3469. /**
  3470. * The number of request required before an automatic purge.
  3471. * Can be configured via the 'purgethreshold' config
  3472. * @property PURGE_THRESH
  3473. * @static
  3474. * @type int
  3475. * @default 20
  3476. * @private
  3477. */
  3478. PURGE_THRESH: 20,
  3479. /**
  3480. * Abort a transaction
  3481. * @method abort
  3482. * @static
  3483. * @param {string|object} o Either the tId or the object returned from
  3484. * script() or css().
  3485. */
  3486. abort : function(o) {
  3487. var id = (L.isString(o)) ? o : o.tId,
  3488. q = queues[id];
  3489. if (q) {
  3490. Y.log('Aborting ' + id, 'info', 'get');
  3491. q.aborted = true;
  3492. }
  3493. },
  3494. /**
  3495. * Fetches and inserts one or more script nodes into the head
  3496. * of the current document or the document in a specified window.
  3497. *
  3498. * @method script
  3499. * @static
  3500. * @param {string|string[]} url the url or urls to the script(s).
  3501. * @param {object} opts Options:
  3502. * <dl>
  3503. * <dt>onSuccess</dt>
  3504. * <dd>
  3505. * callback to execute when the script(s) are finished loading
  3506. * The callback receives an object back with the following
  3507. * data:
  3508. * <dl>
  3509. * <dt>win</dt>
  3510. * <dd>the window the script(s) were inserted into</dd>
  3511. * <dt>data</dt>
  3512. * <dd>the data object passed in when the request was made</dd>
  3513. * <dt>nodes</dt>
  3514. * <dd>An array containing references to the nodes that were
  3515. * inserted</dd>
  3516. * <dt>purge</dt>
  3517. * <dd>A function that, when executed, will remove the nodes
  3518. * that were inserted</dd>
  3519. * <dt>
  3520. * </dl>
  3521. * </dd>
  3522. * <dt>onTimeout</dt>
  3523. * <dd>
  3524. * callback to execute when a timeout occurs.
  3525. * The callback receives an object back with the following
  3526. * data:
  3527. * <dl>
  3528. * <dt>win</dt>
  3529. * <dd>the window the script(s) were inserted into</dd>
  3530. * <dt>data</dt>
  3531. * <dd>the data object passed in when the request was made</dd>
  3532. * <dt>nodes</dt>
  3533. * <dd>An array containing references to the nodes that were
  3534. * inserted</dd>
  3535. * <dt>purge</dt>
  3536. * <dd>A function that, when executed, will remove the nodes
  3537. * that were inserted</dd>
  3538. * <dt>
  3539. * </dl>
  3540. * </dd>
  3541. * <dt>onEnd</dt>
  3542. * <dd>a function that executes when the transaction finishes,
  3543. * regardless of the exit path</dd>
  3544. * <dt>onFailure</dt>
  3545. * <dd>
  3546. * callback to execute when the script load operation fails
  3547. * The callback receives an object back with the following
  3548. * data:
  3549. * <dl>
  3550. * <dt>win</dt>
  3551. * <dd>the window the script(s) were inserted into</dd>
  3552. * <dt>data</dt>
  3553. * <dd>the data object passed in when the request was made</dd>
  3554. * <dt>nodes</dt>
  3555. * <dd>An array containing references to the nodes that were
  3556. * inserted successfully</dd>
  3557. * <dt>purge</dt>
  3558. * <dd>A function that, when executed, will remove any nodes
  3559. * that were inserted</dd>
  3560. * <dt>
  3561. * </dl>
  3562. * </dd>
  3563. * <dt>onProgress</dt>
  3564. * <dd>callback to execute when each individual file is done loading
  3565. * (useful when passing in an array of js files). Receives the same
  3566. * payload as onSuccess, with the addition of a <code>url</code>
  3567. * property, which identifies the file which was loaded.</dd>
  3568. * <dt>async</dt>
  3569. * <dd>
  3570. * <p>When passing in an array of JS files, setting this flag to true
  3571. * will insert them into the document in parallel, as opposed to the
  3572. * default behavior, which is to chain load them serially. It will also
  3573. * set the async attribute on the script node to true.</p>
  3574. * <p>Setting async:true
  3575. * will lead to optimal file download performance allowing the browser to
  3576. * download multiple scripts in parallel, and execute them as soon as they
  3577. * are available.</p>
  3578. * <p>Note that async:true does not guarantee execution order of the
  3579. * scripts being downloaded. They are executed in whichever order they
  3580. * are received.</p>
  3581. * </dd>
  3582. * <dt>context</dt>
  3583. * <dd>the execution context for the callbacks</dd>
  3584. * <dt>win</dt>
  3585. * <dd>a window other than the one the utility occupies</dd>
  3586. * <dt>autopurge</dt>
  3587. * <dd>
  3588. * setting to true will let the utilities cleanup routine purge
  3589. * the script once loaded
  3590. * </dd>
  3591. * <dt>purgethreshold</dt>
  3592. * <dd>
  3593. * The number of transaction before autopurge should be initiated
  3594. * </dd>
  3595. * <dt>data</dt>
  3596. * <dd>
  3597. * data that is supplied to the callback when the script(s) are
  3598. * loaded.
  3599. * </dd>
  3600. * <dt>insertBefore</dt>
  3601. * <dd>node or node id that will become the new node's nextSibling.
  3602. * If this is not specified, nodes will be inserted before a base
  3603. * tag should it exist. Otherwise, the nodes will be appended to the
  3604. * end of the document head.</dd>
  3605. * </dl>
  3606. * <dt>charset</dt>
  3607. * <dd>Node charset, default utf-8 (deprecated, use the attributes
  3608. * config)</dd>
  3609. * <dt>attributes</dt>
  3610. * <dd>An object literal containing additional attributes to add to
  3611. * the link tags</dd>
  3612. * <dt>timeout</dt>
  3613. * <dd>Number of milliseconds to wait before aborting and firing
  3614. * the timeout event</dd>
  3615. * <pre>
  3616. * &nbsp; Y.Get.script(
  3617. * &nbsp; ["http://yui.yahooapis.com/2.5.2/build/yahoo/yahoo-min.js",
  3618. * &nbsp; "http://yui.yahooapis.com/2.5.2/build/event/event-min.js"],
  3619. * &nbsp; &#123;
  3620. * &nbsp; onSuccess: function(o) &#123;
  3621. * &nbsp; this.log("won't cause error because Y is the context");
  3622. * &nbsp; Y.log(o.data); // foo
  3623. * &nbsp; Y.log(o.nodes.length === 2) // true
  3624. * &nbsp; // o.purge(); // optionally remove the script nodes
  3625. * &nbsp; // immediately
  3626. * &nbsp; &#125;,
  3627. * &nbsp; onFailure: function(o) &#123;
  3628. * &nbsp; Y.log("transaction failed");
  3629. * &nbsp; &#125;,
  3630. * &nbsp; onTimeout: function(o) &#123;
  3631. * &nbsp; Y.log("transaction timed out");
  3632. * &nbsp; &#125;,
  3633. * &nbsp; data: "foo",
  3634. * &nbsp; timeout: 10000, // 10 second timeout
  3635. * &nbsp; context: Y, // make the YUI instance
  3636. * &nbsp; // win: otherframe // target another window/frame
  3637. * &nbsp; autopurge: true // allow the utility to choose when to
  3638. * &nbsp; // remove the nodes
  3639. * &nbsp; purgetheshold: 1 // purge previous transaction before
  3640. * &nbsp; // next transaction
  3641. * &nbsp; &#125;);.
  3642. * </pre>
  3643. * @return {tId: string} an object containing info about the
  3644. * transaction.
  3645. */
  3646. script: function(url, opts) {
  3647. return _queue(SCRIPT, url, opts);
  3648. },
  3649. /**
  3650. * Fetches and inserts one or more css link nodes into the
  3651. * head of the current document or the document in a specified
  3652. * window.
  3653. * @method css
  3654. * @static
  3655. * @param {string} url the url or urls to the css file(s).
  3656. * @param {object} opts Options:
  3657. * <dl>
  3658. * <dt>onSuccess</dt>
  3659. * <dd>
  3660. * callback to execute when the css file(s) are finished loading
  3661. * The callback receives an object back with the following
  3662. * data:
  3663. * <dl>win</dl>
  3664. * <dd>the window the link nodes(s) were inserted into</dd>
  3665. * <dt>data</dt>
  3666. * <dd>the data object passed in when the request was made</dd>
  3667. * <dt>nodes</dt>
  3668. * <dd>An array containing references to the nodes that were
  3669. * inserted</dd>
  3670. * <dt>purge</dt>
  3671. * <dd>A function that, when executed, will remove the nodes
  3672. * that were inserted</dd>
  3673. * <dt>
  3674. * </dl>
  3675. * </dd>
  3676. * <dt>onProgress</dt>
  3677. * <dd>callback to execute when each individual file is done loading (useful when passing in an array of css files). Receives the same
  3678. * payload as onSuccess, with the addition of a <code>url</code> property, which identifies the file which was loaded. Currently only useful for non Webkit/Gecko browsers,
  3679. * where onload for css is detected accurately.</dd>
  3680. * <dt>async</dt>
  3681. * <dd>When passing in an array of css files, setting this flag to true will insert them
  3682. * into the document in parallel, as oppposed to the default behavior, which is to chain load them (where possible).
  3683. * This flag is more useful for scripts currently, since for css Get only chains if not Webkit/Gecko.</dd>
  3684. * <dt>context</dt>
  3685. * <dd>the execution context for the callbacks</dd>
  3686. * <dt>win</dt>
  3687. * <dd>a window other than the one the utility occupies</dd>
  3688. * <dt>data</dt>
  3689. * <dd>
  3690. * data that is supplied to the callbacks when the nodes(s) are
  3691. * loaded.
  3692. * </dd>
  3693. * <dt>insertBefore</dt>
  3694. * <dd>node or node id that will become the new node's nextSibling</dd>
  3695. * <dt>charset</dt>
  3696. * <dd>Node charset, default utf-8 (deprecated, use the attributes
  3697. * config)</dd>
  3698. * <dt>attributes</dt>
  3699. * <dd>An object literal containing additional attributes to add to
  3700. * the link tags</dd>
  3701. * </dl>
  3702. * <pre>
  3703. * Y.Get.css("http://localhost/css/menu.css");
  3704. * </pre>
  3705. * <pre>
  3706. * &nbsp; Y.Get.css(
  3707. * &nbsp; ["http://localhost/css/menu.css",
  3708. * &nbsp; "http://localhost/css/logger.css"], &#123;
  3709. * &nbsp; insertBefore: 'custom-styles' // nodes will be inserted
  3710. * &nbsp; // before the specified node
  3711. * &nbsp; &#125;);.
  3712. * </pre>
  3713. * @return {tId: string} an object containing info about the
  3714. * transaction.
  3715. */
  3716. css: function(url, opts) {
  3717. return _queue('css', url, opts);
  3718. }
  3719. };
  3720. }, '3.4.0' ,{requires:['yui-base']});
  3721. YUI.add('features', function(Y) {
  3722. var feature_tests = {};
  3723. Y.mix(Y.namespace('Features'), {
  3724. tests: feature_tests,
  3725. add: function(cat, name, o) {
  3726. feature_tests[cat] = feature_tests[cat] || {};
  3727. feature_tests[cat][name] = o;
  3728. },
  3729. all: function(cat, args) {
  3730. var cat_o = feature_tests[cat],
  3731. // results = {};
  3732. result = [];
  3733. if (cat_o) {
  3734. Y.Object.each(cat_o, function(v, k) {
  3735. result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
  3736. });
  3737. }
  3738. return (result.length) ? result.join(';') : '';
  3739. },
  3740. test: function(cat, name, args) {
  3741. args = args || [];
  3742. var result, ua, test,
  3743. cat_o = feature_tests[cat],
  3744. feature = cat_o && cat_o[name];
  3745. if (!feature) {
  3746. Y.log('Feature test ' + cat + ', ' + name + ' not found');
  3747. } else {
  3748. result = feature.result;
  3749. if (Y.Lang.isUndefined(result)) {
  3750. ua = feature.ua;
  3751. if (ua) {
  3752. result = (Y.UA[ua]);
  3753. }
  3754. test = feature.test;
  3755. if (test && ((!ua) || result)) {
  3756. result = test.apply(Y, args);
  3757. }
  3758. feature.result = result;
  3759. }
  3760. }
  3761. return result;
  3762. }
  3763. });
  3764. // Y.Features.add("load", "1", {});
  3765. // Y.Features.test("load", "1");
  3766. // caps=1:1;2:0;3:1;
  3767. /* This file is auto-generated by src/loader/scripts/meta_join.py */
  3768. var add = Y.Features.add;
  3769. // graphics-svg.js
  3770. add('load', '0', {
  3771. "name": "graphics-svg",
  3772. "test": function(Y) {
  3773. var DOCUMENT = Y.config.doc;
  3774. return (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
  3775. },
  3776. "trigger": "graphics"
  3777. });
  3778. // ie-base-test.js
  3779. add('load', '1', {
  3780. "name": "event-base-ie",
  3781. "test": function(Y) {
  3782. var imp = Y.config.doc && Y.config.doc.implementation;
  3783. return (imp && (!imp.hasFeature('Events', '2.0')));
  3784. },
  3785. "trigger": "node-base"
  3786. });
  3787. // graphics-vml.js
  3788. add('load', '2', {
  3789. "name": "graphics-vml",
  3790. "test": function(Y) {
  3791. var DOCUMENT = Y.config.doc,
  3792. canvas = DOCUMENT && DOCUMENT.createElement("canvas");
  3793. return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
  3794. },
  3795. "trigger": "graphics"
  3796. });
  3797. // ie-style-test.js
  3798. add('load', '3', {
  3799. "name": "dom-style-ie",
  3800. "test": function (Y) {
  3801. var testFeature = Y.Features.test,
  3802. addFeature = Y.Features.add,
  3803. WINDOW = Y.config.win,
  3804. DOCUMENT = Y.config.doc,
  3805. DOCUMENT_ELEMENT = 'documentElement',
  3806. ret = false;
  3807. addFeature('style', 'computedStyle', {
  3808. test: function() {
  3809. return WINDOW && 'getComputedStyle' in WINDOW;
  3810. }
  3811. });
  3812. addFeature('style', 'opacity', {
  3813. test: function() {
  3814. return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
  3815. }
  3816. });
  3817. ret = (!testFeature('style', 'opacity') &&
  3818. !testFeature('style', 'computedStyle'));
  3819. return ret;
  3820. },
  3821. "trigger": "dom-style"
  3822. });
  3823. // transition-test.js
  3824. add('load', '4', {
  3825. "name": "transition-timer",
  3826. "test": function (Y) {
  3827. var DOCUMENT = Y.config.doc,
  3828. node = (DOCUMENT) ? DOCUMENT.documentElement: null,
  3829. ret = true;
  3830. if (node && node.style) {
  3831. ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style);
  3832. }
  3833. return ret;
  3834. },
  3835. "trigger": "transition"
  3836. });
  3837. // 0
  3838. add('load', '5', {
  3839. "name": "widget-base-ie",
  3840. "trigger": "widget-base",
  3841. "ua": "ie"
  3842. });
  3843. // autocomplete-list-keys-sniff.js
  3844. add('load', '6', {
  3845. "name": "autocomplete-list-keys",
  3846. "test": function (Y) {
  3847. // Only add keyboard support to autocomplete-list if this doesn't appear to
  3848. // be an iOS or Android-based mobile device.
  3849. //
  3850. // There's currently no feasible way to actually detect whether a device has
  3851. // a hardware keyboard, so this sniff will have To Do. It can easily be
  3852. // overridden by manually loading the autocomplete-list-keys module.
  3853. //
  3854. // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
  3855. // doesn't fire the keyboard events used by AutoCompleteList, so there's
  3856. // no point loading the -keys module even when a bluetooth keyboard may be
  3857. // available.
  3858. return !(Y.UA.ios || Y.UA.android);
  3859. },
  3860. "trigger": "autocomplete-list"
  3861. });
  3862. // graphics-canvas.js
  3863. add('load', '7', {
  3864. "name": "graphics-canvas-default",
  3865. "test": function(Y) {
  3866. var DOCUMENT = Y.config.doc,
  3867. canvas = DOCUMENT && DOCUMENT.createElement("canvas");
  3868. return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (canvas && canvas.getContext && canvas.getContext("2d")));
  3869. },
  3870. "trigger": "graphics"
  3871. });
  3872. // dd-gestures-test.js
  3873. add('load', '8', {
  3874. "name": "dd-gestures",
  3875. "test": function(Y) {
  3876. return (Y.config.win && ('ontouchstart' in Y.config.win && !Y.UA.chrome));
  3877. },
  3878. "trigger": "dd-drag"
  3879. });
  3880. // selector-test.js
  3881. add('load', '9', {
  3882. "name": "selector-css2",
  3883. "test": function (Y) {
  3884. var DOCUMENT = Y.config.doc,
  3885. ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
  3886. return ret;
  3887. },
  3888. "trigger": "selector"
  3889. });
  3890. // history-hash-ie-test.js
  3891. add('load', '10', {
  3892. "name": "history-hash-ie",
  3893. "test": function (Y) {
  3894. var docMode = Y.config.doc && Y.config.doc.documentMode;
  3895. return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
  3896. !docMode || docMode < 8);
  3897. },
  3898. "trigger": "history-hash"
  3899. });
  3900. }, '3.4.0' ,{requires:['yui-base']});
  3901. YUI.add('intl-base', function(Y) {
  3902. /**
  3903. * The Intl utility provides a central location for managing sets of
  3904. * localized resources (strings and formatting patterns).
  3905. *
  3906. * @class Intl
  3907. * @uses EventTarget
  3908. * @static
  3909. */
  3910. var SPLIT_REGEX = /[, ]/;
  3911. Y.mix(Y.namespace('Intl'), {
  3912. /**
  3913. * Returns the language among those available that
  3914. * best matches the preferred language list, using the Lookup
  3915. * algorithm of BCP 47.
  3916. * If none of the available languages meets the user's preferences,
  3917. * then "" is returned.
  3918. * Extended language ranges are not supported.
  3919. *
  3920. * @method lookupBestLang
  3921. * @param {String[] | String} preferredLanguages The list of preferred
  3922. * languages in descending preference order, represented as BCP 47
  3923. * language tags. A string array or a comma-separated list.
  3924. * @param {String[]} availableLanguages The list of languages
  3925. * that the application supports, represented as BCP 47 language
  3926. * tags.
  3927. *
  3928. * @return {String} The available language that best matches the
  3929. * preferred language list, or "".
  3930. * @since 3.1.0
  3931. */
  3932. lookupBestLang: function(preferredLanguages, availableLanguages) {
  3933. var i, language, result, index;
  3934. // check whether the list of available languages contains language;
  3935. // if so return it
  3936. function scan(language) {
  3937. var i;
  3938. for (i = 0; i < availableLanguages.length; i += 1) {
  3939. if (language.toLowerCase() ===
  3940. availableLanguages[i].toLowerCase()) {
  3941. return availableLanguages[i];
  3942. }
  3943. }
  3944. }
  3945. if (Y.Lang.isString(preferredLanguages)) {
  3946. preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
  3947. }
  3948. for (i = 0; i < preferredLanguages.length; i += 1) {
  3949. language = preferredLanguages[i];
  3950. if (!language || language === '*') {
  3951. continue;
  3952. }
  3953. // check the fallback sequence for one language
  3954. while (language.length > 0) {
  3955. result = scan(language);
  3956. if (result) {
  3957. return result;
  3958. } else {
  3959. index = language.lastIndexOf('-');
  3960. if (index >= 0) {
  3961. language = language.substring(0, index);
  3962. // one-character subtags get cut along with the
  3963. // following subtag
  3964. if (index >= 2 && language.charAt(index - 2) === '-') {
  3965. language = language.substring(0, index - 2);
  3966. }
  3967. } else {
  3968. // nothing available for this language
  3969. break;
  3970. }
  3971. }
  3972. }
  3973. }
  3974. return '';
  3975. }
  3976. });
  3977. }, '3.4.0' ,{requires:['yui-base']});
  3978. YUI.add('yui-log', function(Y) {
  3979. /**
  3980. * Provides console log capability and exposes a custom event for
  3981. * console implementations. This module is a `core` YUI module, <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
  3982. *
  3983. * @module yui
  3984. * @submodule yui-log
  3985. */
  3986. var INSTANCE = Y,
  3987. LOGEVENT = 'yui:log',
  3988. UNDEFINED = 'undefined',
  3989. LEVELS = { debug: 1,
  3990. info: 1,
  3991. warn: 1,
  3992. error: 1 };
  3993. /**
  3994. * If the 'debug' config is true, a 'yui:log' event will be
  3995. * dispatched, which the Console widget and anything else
  3996. * can consume. If the 'useBrowserConsole' config is true, it will
  3997. * write to the browser console if available. YUI-specific log
  3998. * messages will only be present in the -debug versions of the
  3999. * JS files. The build system is supposed to remove log statements
  4000. * from the raw and minified versions of the files.
  4001. *
  4002. * @method log
  4003. * @for YUI
  4004. * @param {String} msg The message to log.
  4005. * @param {String} cat The log category for the message. Default
  4006. * categories are "info", "warn", "error", time".
  4007. * Custom categories can be used as well. (opt).
  4008. * @param {String} src The source of the the message (opt).
  4009. * @param {boolean} silent If true, the log event won't fire.
  4010. * @return {YUI} YUI instance.
  4011. */
  4012. INSTANCE.log = function(msg, cat, src, silent) {
  4013. var bail, excl, incl, m, f,
  4014. Y = INSTANCE,
  4015. c = Y.config,
  4016. publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
  4017. // suppress log message if the config is off or the event stack
  4018. // or the event call stack contains a consumer of the yui:log event
  4019. if (c.debug) {
  4020. // apply source filters
  4021. if (src) {
  4022. excl = c.logExclude;
  4023. incl = c.logInclude;
  4024. if (incl && !(src in incl)) {
  4025. bail = 1;
  4026. } else if (incl && (src in incl)) {
  4027. bail = !incl[src];
  4028. } else if (excl && (src in excl)) {
  4029. bail = excl[src];
  4030. }
  4031. }
  4032. if (!bail) {
  4033. if (c.useBrowserConsole) {
  4034. m = (src) ? src + ': ' + msg : msg;
  4035. if (Y.Lang.isFunction(c.logFn)) {
  4036. c.logFn.call(Y, msg, cat, src);
  4037. } else if (typeof console != UNDEFINED && console.log) {
  4038. f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
  4039. console[f](m);
  4040. } else if (typeof opera != UNDEFINED) {
  4041. opera.postError(m);
  4042. }
  4043. }
  4044. if (publisher && !silent) {
  4045. if (publisher == Y && (!publisher.getEvent(LOGEVENT))) {
  4046. publisher.publish(LOGEVENT, {
  4047. broadcast: 2
  4048. });
  4049. }
  4050. publisher.fire(LOGEVENT, {
  4051. msg: msg,
  4052. cat: cat,
  4053. src: src
  4054. });
  4055. }
  4056. }
  4057. }
  4058. return Y;
  4059. };
  4060. /**
  4061. * Write a system message. This message will be preserved in the
  4062. * minified and raw versions of the YUI files, unlike log statements.
  4063. * @method message
  4064. * @for YUI
  4065. * @param {String} msg The message to log.
  4066. * @param {String} cat The log category for the message. Default
  4067. * categories are "info", "warn", "error", time".
  4068. * Custom categories can be used as well. (opt).
  4069. * @param {String} src The source of the the message (opt).
  4070. * @param {boolean} silent If true, the log event won't fire.
  4071. * @return {YUI} YUI instance.
  4072. */
  4073. INSTANCE.message = function() {
  4074. return INSTANCE.log.apply(INSTANCE, arguments);
  4075. };
  4076. }, '3.4.0' ,{requires:['yui-base']});
  4077. YUI.add('yui-later', function(Y) {
  4078. /**
  4079. * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module, <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
  4080. *
  4081. * @module yui
  4082. * @submodule yui-later
  4083. */
  4084. var NO_ARGS = [];
  4085. /**
  4086. * Executes the supplied function in the context of the supplied
  4087. * object 'when' milliseconds later. Executes the function a
  4088. * single time unless periodic is set to true.
  4089. * @for YUI
  4090. * @method later
  4091. * @param when {int} the number of milliseconds to wait until the fn
  4092. * is executed.
  4093. * @param o the context object.
  4094. * @param fn {Function|String} the function to execute or the name of
  4095. * the method in the 'o' object to execute.
  4096. * @param data [Array] data that is provided to the function. This
  4097. * accepts either a single item or an array. If an array is provided,
  4098. * the function is executed with one parameter for each array item.
  4099. * If you need to pass a single array parameter, it needs to be wrapped
  4100. * in an array [myarray].
  4101. *
  4102. * Note: native methods in IE may not have the call and apply methods.
  4103. * In this case, it will work, but you are limited to four arguments.
  4104. *
  4105. * @param periodic {boolean} if true, executes continuously at supplied
  4106. * interval until canceled.
  4107. * @return {object} a timer object. Call the cancel() method on this
  4108. * object to stop the timer.
  4109. */
  4110. Y.later = function(when, o, fn, data, periodic) {
  4111. when = when || 0;
  4112. data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : data;
  4113. var cancelled = false,
  4114. method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
  4115. wrapper = function() {
  4116. // IE 8- may execute a setInterval callback one last time
  4117. // after clearInterval was called, so in order to preserve
  4118. // the cancel() === no more runny-run, we have to jump through
  4119. // an extra hoop.
  4120. if (!cancelled) {
  4121. if (!method.apply) {
  4122. method(data[0], data[1], data[2], data[3]);
  4123. } else {
  4124. method.apply(o, data || NO_ARGS);
  4125. }
  4126. }
  4127. },
  4128. id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
  4129. return {
  4130. id: id,
  4131. interval: periodic,
  4132. cancel: function() {
  4133. cancelled = true;
  4134. if (this.interval) {
  4135. clearInterval(id);
  4136. } else {
  4137. clearTimeout(id);
  4138. }
  4139. }
  4140. };
  4141. };
  4142. Y.Lang.later = Y.later;
  4143. }, '3.4.0' ,{requires:['yui-base']});
  4144. YUI.add('yui', function(Y){}, '3.4.0' ,{use:['yui-base','get','features','intl-base','yui-log','yui-later']});
  4145. YUI.add('oop', function(Y) {
  4146. /**
  4147. Adds object inheritance and manipulation utilities to the YUI instance. This
  4148. module is required by most YUI components.
  4149. @module oop
  4150. **/
  4151. var L = Y.Lang,
  4152. A = Y.Array,
  4153. OP = Object.prototype,
  4154. CLONE_MARKER = '_~yuim~_',
  4155. hasOwn = OP.hasOwnProperty,
  4156. toString = OP.toString;
  4157. function dispatch(o, f, c, proto, action) {
  4158. if (o && o[action] && o !== Y) {
  4159. return o[action].call(o, f, c);
  4160. } else {
  4161. switch (A.test(o)) {
  4162. case 1:
  4163. return A[action](o, f, c);
  4164. case 2:
  4165. return A[action](Y.Array(o, 0, true), f, c);
  4166. default:
  4167. return Y.Object[action](o, f, c, proto);
  4168. }
  4169. }
  4170. }
  4171. /**
  4172. Augments the _receiver_ with prototype properties from the _supplier_. The
  4173. receiver may be a constructor function or an object. The supplier must be a
  4174. constructor function.
  4175. If the _receiver_ is an object, then the _supplier_ constructor will be called
  4176. immediately after _receiver_ is augmented, with _receiver_ as the `this` object.
  4177. If the _receiver_ is a constructor function, then all prototype methods of
  4178. _supplier_ that are copied to _receiver_ will be sequestered, and the
  4179. _supplier_ constructor will not be called immediately. The first time any
  4180. sequestered method is called on the _receiver_'s prototype, all sequestered
  4181. methods will be immediately copied to the _receiver_'s prototype, the
  4182. _supplier_'s constructor will be executed, and finally the newly unsequestered
  4183. method that was called will be executed.
  4184. This sequestering logic sounds like a bunch of complicated voodoo, but it makes
  4185. it cheap to perform frequent augmentation by ensuring that suppliers'
  4186. constructors are only called if a supplied method is actually used. If none of
  4187. the supplied methods is ever used, then there's no need to take the performance
  4188. hit of calling the _supplier_'s constructor.
  4189. @method augment
  4190. @param {Function|Object} receiver Object or function to be augmented.
  4191. @param {Function} supplier Function that supplies the prototype properties with
  4192. which to augment the _receiver_.
  4193. @param {Boolean} [overwrite=false] If `true`, properties already on the receiver
  4194. will be overwritten if found on the supplier's prototype.
  4195. @param {String[]} [whitelist] An array of property names. If specified,
  4196. only the whitelisted prototype properties will be applied to the receiver, and
  4197. all others will be ignored.
  4198. @param {Array|any} [args] Argument or array of arguments to pass to the
  4199. supplier's constructor when initializing.
  4200. @return {Function} Augmented object.
  4201. @for YUI
  4202. **/
  4203. Y.augment = function (receiver, supplier, overwrite, whitelist, args) {
  4204. var rProto = receiver.prototype,
  4205. sequester = rProto && supplier,
  4206. sProto = supplier.prototype,
  4207. to = rProto || receiver,
  4208. copy,
  4209. newPrototype,
  4210. replacements,
  4211. sequestered,
  4212. unsequester;
  4213. args = args ? Y.Array(args) : [];
  4214. if (sequester) {
  4215. newPrototype = {};
  4216. replacements = {};
  4217. sequestered = {};
  4218. copy = function (value, key) {
  4219. if (overwrite || !(key in rProto)) {
  4220. if (toString.call(value) === '[object Function]') {
  4221. sequestered[key] = value;
  4222. newPrototype[key] = replacements[key] = function () {
  4223. return unsequester(this, value, arguments);
  4224. };
  4225. } else {
  4226. newPrototype[key] = value;
  4227. }
  4228. }
  4229. };
  4230. unsequester = function (instance, fn, fnArgs) {
  4231. // Unsequester all sequestered functions.
  4232. for (var key in sequestered) {
  4233. if (hasOwn.call(sequestered, key)
  4234. && instance[key] === replacements[key]) {
  4235. instance[key] = sequestered[key];
  4236. }
  4237. }
  4238. // Execute the supplier constructor.
  4239. supplier.apply(instance, args);
  4240. // Finally, execute the original sequestered function.
  4241. return fn.apply(instance, fnArgs);
  4242. };
  4243. if (whitelist) {
  4244. Y.Array.each(whitelist, function (name) {
  4245. if (name in sProto) {
  4246. copy(sProto[name], name);
  4247. }
  4248. });
  4249. } else {
  4250. Y.Object.each(sProto, copy, null, true);
  4251. }
  4252. }
  4253. Y.mix(to, newPrototype || sProto, overwrite, whitelist);
  4254. if (!sequester) {
  4255. supplier.apply(to, args);
  4256. }
  4257. return receiver;
  4258. };
  4259. /**
  4260. * Applies object properties from the supplier to the receiver. If
  4261. * the target has the property, and the property is an object, the target
  4262. * object will be augmented with the supplier's value. If the property
  4263. * is an array, the suppliers value will be appended to the target.
  4264. * @method aggregate
  4265. * @param {function} r the object to receive the augmentation.
  4266. * @param {function} s the object that supplies the properties to augment.
  4267. * @param {boolean} ov if true, properties already on the receiver
  4268. * will be overwritten if found on the supplier.
  4269. * @param {string[]} wl a whitelist. If supplied, only properties in
  4270. * this list will be applied to the receiver.
  4271. * @return {object} the extended object.
  4272. */
  4273. Y.aggregate = function(r, s, ov, wl) {
  4274. return Y.mix(r, s, ov, wl, 0, true);
  4275. };
  4276. /**
  4277. * Utility to set up the prototype, constructor and superclass properties to
  4278. * support an inheritance strategy that can chain constructors and methods.
  4279. * Static members will not be inherited.
  4280. *
  4281. * @method extend
  4282. * @param {function} r the object to modify.
  4283. * @param {function} s the object to inherit.
  4284. * @param {object} px prototype properties to add/override.
  4285. * @param {object} sx static properties to add/override.
  4286. * @return {object} the extended object.
  4287. */
  4288. Y.extend = function(r, s, px, sx) {
  4289. if (!s || !r) {
  4290. Y.error('extend failed, verify dependencies');
  4291. }
  4292. var sp = s.prototype, rp = Y.Object(sp);
  4293. r.prototype = rp;
  4294. rp.constructor = r;
  4295. r.superclass = sp;
  4296. // assign constructor property
  4297. if (s != Object && sp.constructor == OP.constructor) {
  4298. sp.constructor = s;
  4299. }
  4300. // add prototype overrides
  4301. if (px) {
  4302. Y.mix(rp, px, true);
  4303. }
  4304. // add object overrides
  4305. if (sx) {
  4306. Y.mix(r, sx, true);
  4307. }
  4308. return r;
  4309. };
  4310. /**
  4311. * Executes the supplied function for each item in
  4312. * a collection. Supports arrays, objects, and
  4313. * NodeLists
  4314. * @method each
  4315. * @param {object} o the object to iterate.
  4316. * @param {function} f the function to execute. This function
  4317. * receives the value, key, and object as parameters.
  4318. * @param {object} c the execution context for the function.
  4319. * @param {boolean} proto if true, prototype properties are
  4320. * iterated on objects.
  4321. * @return {YUI} the YUI instance.
  4322. */
  4323. Y.each = function(o, f, c, proto) {
  4324. return dispatch(o, f, c, proto, 'each');
  4325. };
  4326. /**
  4327. * Executes the supplied function for each item in
  4328. * a collection. The operation stops if the function
  4329. * returns true. Supports arrays, objects, and
  4330. * NodeLists.
  4331. * @method some
  4332. * @param {object} o the object to iterate.
  4333. * @param {function} f the function to execute. This function
  4334. * receives the value, key, and object as parameters.
  4335. * @param {object} c the execution context for the function.
  4336. * @param {boolean} proto if true, prototype properties are
  4337. * iterated on objects.
  4338. * @return {boolean} true if the function ever returns true,
  4339. * false otherwise.
  4340. */
  4341. Y.some = function(o, f, c, proto) {
  4342. return dispatch(o, f, c, proto, 'some');
  4343. };
  4344. /**
  4345. * Deep object/array copy. Function clones are actually
  4346. * wrappers around the original function.
  4347. * Array-like objects are treated as arrays.
  4348. * Primitives are returned untouched. Optionally, a
  4349. * function can be provided to handle other data types,
  4350. * filter keys, validate values, etc.
  4351. *
  4352. * @method clone
  4353. * @param {object} o what to clone.
  4354. * @param {boolean} safe if true, objects will not have prototype
  4355. * items from the source. If false, they will. In this case, the
  4356. * original is initially protected, but the clone is not completely
  4357. * immune from changes to the source object prototype. Also, cloned
  4358. * prototype items that are deleted from the clone will result
  4359. * in the value of the source prototype being exposed. If operating
  4360. * on a non-safe clone, items should be nulled out rather than deleted.
  4361. * @param {function} f optional function to apply to each item in a
  4362. * collection; it will be executed prior to applying the value to
  4363. * the new object. Return false to prevent the copy.
  4364. * @param {object} c optional execution context for f.
  4365. * @param {object} owner Owner object passed when clone is iterating
  4366. * an object. Used to set up context for cloned functions.
  4367. * @param {object} cloned hash of previously cloned objects to avoid
  4368. * multiple clones.
  4369. * @return {Array|Object} the cloned object.
  4370. */
  4371. Y.clone = function(o, safe, f, c, owner, cloned) {
  4372. if (!L.isObject(o)) {
  4373. return o;
  4374. }
  4375. // @todo cloning YUI instances doesn't currently work
  4376. if (Y.instanceOf(o, YUI)) {
  4377. return o;
  4378. }
  4379. var o2, marked = cloned || {}, stamp,
  4380. yeach = Y.each;
  4381. switch (L.type(o)) {
  4382. case 'date':
  4383. return new Date(o);
  4384. case 'regexp':
  4385. // if we do this we need to set the flags too
  4386. // return new RegExp(o.source);
  4387. return o;
  4388. case 'function':
  4389. // o2 = Y.bind(o, owner);
  4390. // break;
  4391. return o;
  4392. case 'array':
  4393. o2 = [];
  4394. break;
  4395. default:
  4396. // #2528250 only one clone of a given object should be created.
  4397. if (o[CLONE_MARKER]) {
  4398. return marked[o[CLONE_MARKER]];
  4399. }
  4400. stamp = Y.guid();
  4401. o2 = (safe) ? {} : Y.Object(o);
  4402. o[CLONE_MARKER] = stamp;
  4403. marked[stamp] = o;
  4404. }
  4405. // #2528250 don't try to clone element properties
  4406. if (!o.addEventListener && !o.attachEvent) {
  4407. yeach(o, function(v, k) {
  4408. if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
  4409. if (k !== CLONE_MARKER) {
  4410. if (k == 'prototype') {
  4411. // skip the prototype
  4412. // } else if (o[k] === o) {
  4413. // this[k] = this;
  4414. } else {
  4415. this[k] =
  4416. Y.clone(v, safe, f, c, owner || o, marked);
  4417. }
  4418. }
  4419. }
  4420. }, o2);
  4421. }
  4422. if (!cloned) {
  4423. Y.Object.each(marked, function(v, k) {
  4424. if (v[CLONE_MARKER]) {
  4425. try {
  4426. delete v[CLONE_MARKER];
  4427. } catch (e) {
  4428. v[CLONE_MARKER] = null;
  4429. }
  4430. }
  4431. }, this);
  4432. marked = null;
  4433. }
  4434. return o2;
  4435. };
  4436. /**
  4437. * Returns a function that will execute the supplied function in the
  4438. * supplied object's context, optionally adding any additional
  4439. * supplied parameters to the beginning of the arguments collection the
  4440. * supplied to the function.
  4441. *
  4442. * @method bind
  4443. * @param {Function|String} f the function to bind, or a function name
  4444. * to execute on the context object.
  4445. * @param {object} c the execution context.
  4446. * @param {any} args* 0..n arguments to include before the arguments the
  4447. * function is executed with.
  4448. * @return {function} the wrapped function.
  4449. */
  4450. Y.bind = function(f, c) {
  4451. var xargs = arguments.length > 2 ?
  4452. Y.Array(arguments, 2, true) : null;
  4453. return function() {
  4454. var fn = L.isString(f) ? c[f] : f,
  4455. args = (xargs) ?
  4456. xargs.concat(Y.Array(arguments, 0, true)) : arguments;
  4457. return fn.apply(c || fn, args);
  4458. };
  4459. };
  4460. /**
  4461. * Returns a function that will execute the supplied function in the
  4462. * supplied object's context, optionally adding any additional
  4463. * supplied parameters to the end of the arguments the function
  4464. * is executed with.
  4465. *
  4466. * @method rbind
  4467. * @param {Function|String} f the function to bind, or a function name
  4468. * to execute on the context object.
  4469. * @param {object} c the execution context.
  4470. * @param {any} args* 0..n arguments to append to the end of
  4471. * arguments collection supplied to the function.
  4472. * @return {function} the wrapped function.
  4473. */
  4474. Y.rbind = function(f, c) {
  4475. var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
  4476. return function() {
  4477. var fn = L.isString(f) ? c[f] : f,
  4478. args = (xargs) ?
  4479. Y.Array(arguments, 0, true).concat(xargs) : arguments;
  4480. return fn.apply(c || fn, args);
  4481. };
  4482. };
  4483. }, '3.4.0' ,{requires:['yui-base']});
  4484. YUI.add('features', function(Y) {
  4485. var feature_tests = {};
  4486. Y.mix(Y.namespace('Features'), {
  4487. tests: feature_tests,
  4488. add: function(cat, name, o) {
  4489. feature_tests[cat] = feature_tests[cat] || {};
  4490. feature_tests[cat][name] = o;
  4491. },
  4492. all: function(cat, args) {
  4493. var cat_o = feature_tests[cat],
  4494. // results = {};
  4495. result = [];
  4496. if (cat_o) {
  4497. Y.Object.each(cat_o, function(v, k) {
  4498. result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
  4499. });
  4500. }
  4501. return (result.length) ? result.join(';') : '';
  4502. },
  4503. test: function(cat, name, args) {
  4504. args = args || [];
  4505. var result, ua, test,
  4506. cat_o = feature_tests[cat],
  4507. feature = cat_o && cat_o[name];
  4508. if (!feature) {
  4509. Y.log('Feature test ' + cat + ', ' + name + ' not found');
  4510. } else {
  4511. result = feature.result;
  4512. if (Y.Lang.isUndefined(result)) {
  4513. ua = feature.ua;
  4514. if (ua) {
  4515. result = (Y.UA[ua]);
  4516. }
  4517. test = feature.test;
  4518. if (test && ((!ua) || result)) {
  4519. result = test.apply(Y, args);
  4520. }
  4521. feature.result = result;
  4522. }
  4523. }
  4524. return result;
  4525. }
  4526. });
  4527. // Y.Features.add("load", "1", {});
  4528. // Y.Features.test("load", "1");
  4529. // caps=1:1;2:0;3:1;
  4530. /* This file is auto-generated by src/loader/scripts/meta_join.py */
  4531. var add = Y.Features.add;
  4532. // graphics-svg.js
  4533. add('load', '0', {
  4534. "name": "graphics-svg",
  4535. "test": function(Y) {
  4536. var DOCUMENT = Y.config.doc;
  4537. return (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
  4538. },
  4539. "trigger": "graphics"
  4540. });
  4541. // ie-base-test.js
  4542. add('load', '1', {
  4543. "name": "event-base-ie",
  4544. "test": function(Y) {
  4545. var imp = Y.config.doc && Y.config.doc.implementation;
  4546. return (imp && (!imp.hasFeature('Events', '2.0')));
  4547. },
  4548. "trigger": "node-base"
  4549. });
  4550. // graphics-vml.js
  4551. add('load', '2', {
  4552. "name": "graphics-vml",
  4553. "test": function(Y) {
  4554. var DOCUMENT = Y.config.doc,
  4555. canvas = DOCUMENT && DOCUMENT.createElement("canvas");
  4556. return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
  4557. },
  4558. "trigger": "graphics"
  4559. });
  4560. // ie-style-test.js
  4561. add('load', '3', {
  4562. "name": "dom-style-ie",
  4563. "test": function (Y) {
  4564. var testFeature = Y.Features.test,
  4565. addFeature = Y.Features.add,
  4566. WINDOW = Y.config.win,
  4567. DOCUMENT = Y.config.doc,
  4568. DOCUMENT_ELEMENT = 'documentElement',
  4569. ret = false;
  4570. addFeature('style', 'computedStyle', {
  4571. test: function() {
  4572. return WINDOW && 'getComputedStyle' in WINDOW;
  4573. }
  4574. });
  4575. addFeature('style', 'opacity', {
  4576. test: function() {
  4577. return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
  4578. }
  4579. });
  4580. ret = (!testFeature('style', 'opacity') &&
  4581. !testFeature('style', 'computedStyle'));
  4582. return ret;
  4583. },
  4584. "trigger": "dom-style"
  4585. });
  4586. // transition-test.js
  4587. add('load', '4', {
  4588. "name": "transition-timer",
  4589. "test": function (Y) {
  4590. var DOCUMENT = Y.config.doc,
  4591. node = (DOCUMENT) ? DOCUMENT.documentElement: null,
  4592. ret = true;
  4593. if (node && node.style) {
  4594. ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style);
  4595. }
  4596. return ret;
  4597. },
  4598. "trigger": "transition"
  4599. });
  4600. // 0
  4601. add('load', '5', {
  4602. "name": "widget-base-ie",
  4603. "trigger": "widget-base",
  4604. "ua": "ie"
  4605. });
  4606. // autocomplete-list-keys-sniff.js
  4607. add('load', '6', {
  4608. "name": "autocomplete-list-keys",
  4609. "test": function (Y) {
  4610. // Only add keyboard support to autocomplete-list if this doesn't appear to
  4611. // be an iOS or Android-based mobile device.
  4612. //
  4613. // There's currently no feasible way to actually detect whether a device has
  4614. // a hardware keyboard, so this sniff will have To Do. It can easily be
  4615. // overridden by manually loading the autocomplete-list-keys module.
  4616. //
  4617. // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
  4618. // doesn't fire the keyboard events used by AutoCompleteList, so there's
  4619. // no point loading the -keys module even when a bluetooth keyboard may be
  4620. // available.
  4621. return !(Y.UA.ios || Y.UA.android);
  4622. },
  4623. "trigger": "autocomplete-list"
  4624. });
  4625. // graphics-canvas.js
  4626. add('load', '7', {
  4627. "name": "graphics-canvas-default",
  4628. "test": function(Y) {
  4629. var DOCUMENT = Y.config.doc,
  4630. canvas = DOCUMENT && DOCUMENT.createElement("canvas");
  4631. return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (canvas && canvas.getContext && canvas.getContext("2d")));
  4632. },
  4633. "trigger": "graphics"
  4634. });
  4635. // dd-gestures-test.js
  4636. add('load', '8', {
  4637. "name": "dd-gestures",
  4638. "test": function(Y) {
  4639. return (Y.config.win && ('ontouchstart' in Y.config.win && !Y.UA.chrome));
  4640. },
  4641. "trigger": "dd-drag"
  4642. });
  4643. // selector-test.js
  4644. add('load', '9', {
  4645. "name": "selector-css2",
  4646. "test": function (Y) {
  4647. var DOCUMENT = Y.config.doc,
  4648. ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
  4649. return ret;
  4650. },
  4651. "trigger": "selector"
  4652. });
  4653. // history-hash-ie-test.js
  4654. add('load', '10', {
  4655. "name": "history-hash-ie",
  4656. "test": function (Y) {
  4657. var docMode = Y.config.doc && Y.config.doc.documentMode;
  4658. return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
  4659. !docMode || docMode < 8);
  4660. },
  4661. "trigger": "history-hash"
  4662. });
  4663. }, '3.4.0' ,{requires:['yui-base']});
  4664. YUI.add('dom-core', function(Y) {
  4665. var NODE_TYPE = 'nodeType',
  4666. OWNER_DOCUMENT = 'ownerDocument',
  4667. DOCUMENT_ELEMENT = 'documentElement',
  4668. DEFAULT_VIEW = 'defaultView',
  4669. PARENT_WINDOW = 'parentWindow',
  4670. TAG_NAME = 'tagName',
  4671. PARENT_NODE = 'parentNode',
  4672. PREVIOUS_SIBLING = 'previousSibling',
  4673. NEXT_SIBLING = 'nextSibling',
  4674. CONTAINS = 'contains',
  4675. COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
  4676. EMPTY_ARRAY = [],
  4677. /**
  4678. * The DOM utility provides a cross-browser abtraction layer
  4679. * normalizing DOM tasks, and adds extra helper functionality
  4680. * for other common tasks.
  4681. * @module dom
  4682. * @submodule dom-base
  4683. * @for DOM
  4684. *
  4685. */
  4686. /**
  4687. * Provides DOM helper methods.
  4688. * @class DOM
  4689. *
  4690. */
  4691. Y_DOM = {
  4692. /**
  4693. * Returns the HTMLElement with the given ID (Wrapper for document.getElementById).
  4694. * @method byId
  4695. * @param {String} id the id attribute
  4696. * @param {Object} doc optional The document to search. Defaults to current document
  4697. * @return {HTMLElement | null} The HTMLElement with the id, or null if none found.
  4698. */
  4699. byId: function(id, doc) {
  4700. // handle dupe IDs and IE name collision
  4701. return Y_DOM.allById(id, doc)[0] || null;
  4702. },
  4703. /*
  4704. * Finds the ancestor of the element.
  4705. * @method ancestor
  4706. * @param {HTMLElement} element The html element.
  4707. * @param {Function} fn optional An optional boolean test to apply.
  4708. * The optional function is passed the current DOM node being tested as its only argument.
  4709. * If no function is given, the parentNode is returned.
  4710. * @param {Boolean} testSelf optional Whether or not to include the element in the scan
  4711. * @return {HTMLElement | null} The matching DOM node or null if none found.
  4712. */
  4713. ancestor: function(element, fn, testSelf) {
  4714. var ret = null;
  4715. if (testSelf) {
  4716. ret = (!fn || fn(element)) ? element : null;
  4717. }
  4718. return ret || Y_DOM.elementByAxis(element, PARENT_NODE, fn, null);
  4719. },
  4720. /*
  4721. * Finds the ancestors of the element.
  4722. * @method ancestors
  4723. * @param {HTMLElement} element The html element.
  4724. * @param {Function} fn optional An optional boolean test to apply.
  4725. * The optional function is passed the current DOM node being tested as its only argument.
  4726. * If no function is given, all ancestors are returned.
  4727. * @param {Boolean} testSelf optional Whether or not to include the element in the scan
  4728. * @return {Array} An array containing all matching DOM nodes.
  4729. */
  4730. ancestors: function(element, fn, testSelf) {
  4731. var ancestor = Y_DOM.ancestor.apply(Y_DOM, arguments),
  4732. ret = (ancestor) ? [ancestor] : [];
  4733. while ((ancestor = Y_DOM.ancestor(ancestor, fn))) {
  4734. if (ancestor) {
  4735. ret.unshift(ancestor);
  4736. }
  4737. }
  4738. return ret;
  4739. },
  4740. /**
  4741. * Searches the element by the given axis for the first matching element.
  4742. * @method elementByAxis
  4743. * @param {HTMLElement} element The html element.
  4744. * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling).
  4745. * @param {Function} fn optional An optional boolean test to apply.
  4746. * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
  4747. * The optional function is passed the current HTMLElement being tested as its only argument.
  4748. * If no function is given, the first element is returned.
  4749. * @return {HTMLElement | null} The matching element or null if none found.
  4750. */
  4751. elementByAxis: function(element, axis, fn, all) {
  4752. while (element && (element = element[axis])) { // NOTE: assignment
  4753. if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
  4754. return element;
  4755. }
  4756. }
  4757. return null;
  4758. },
  4759. /**
  4760. * Determines whether or not one HTMLElement is or contains another HTMLElement.
  4761. * @method contains
  4762. * @param {HTMLElement} element The containing html element.
  4763. * @param {HTMLElement} needle The html element that may be contained.
  4764. * @return {Boolean} Whether or not the element is or contains the needle.
  4765. */
  4766. contains: function(element, needle) {
  4767. var ret = false;
  4768. if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
  4769. ret = false;
  4770. } else if (element[CONTAINS]) {
  4771. if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE
  4772. ret = element[CONTAINS](needle);
  4773. } else {
  4774. ret = Y_DOM._bruteContains(element, needle);
  4775. }
  4776. } else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko
  4777. if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) {
  4778. ret = true;
  4779. }
  4780. }
  4781. return ret;
  4782. },
  4783. /**
  4784. * Determines whether or not the HTMLElement is part of the document.
  4785. * @method inDoc
  4786. * @param {HTMLElement} element The containing html element.
  4787. * @param {HTMLElement} doc optional The document to check.
  4788. * @return {Boolean} Whether or not the element is attached to the document.
  4789. */
  4790. inDoc: function(element, doc) {
  4791. var ret = false,
  4792. rootNode;
  4793. if (element && element.nodeType) {
  4794. (doc) || (doc = element[OWNER_DOCUMENT]);
  4795. rootNode = doc[DOCUMENT_ELEMENT];
  4796. // contains only works with HTML_ELEMENT
  4797. if (rootNode && rootNode.contains && element.tagName) {
  4798. ret = rootNode.contains(element);
  4799. } else {
  4800. ret = Y_DOM.contains(rootNode, element);
  4801. }
  4802. }
  4803. return ret;
  4804. },
  4805. allById: function(id, root) {
  4806. root = root || Y.config.doc;
  4807. var nodes = [],
  4808. ret = [],
  4809. i,
  4810. node;
  4811. if (root.querySelectorAll) {
  4812. ret = root.querySelectorAll('[id="' + id + '"]');
  4813. } else if (root.all) {
  4814. nodes = root.all(id);
  4815. if (nodes) {
  4816. // root.all may return HTMLElement or HTMLCollection.
  4817. // some elements are also HTMLCollection (FORM, SELECT).
  4818. if (nodes.nodeName) {
  4819. if (nodes.id === id) { // avoid false positive on name
  4820. ret.push(nodes);
  4821. nodes = EMPTY_ARRAY; // done, no need to filter
  4822. } else { // prep for filtering
  4823. nodes = [nodes];
  4824. }
  4825. }
  4826. if (nodes.length) {
  4827. // filter out matches on node.name
  4828. // and element.id as reference to element with id === 'id'
  4829. for (i = 0; node = nodes[i++];) {
  4830. if (node.id === id ||
  4831. (node.attributes && node.attributes.id &&
  4832. node.attributes.id.value === id)) {
  4833. ret.push(node);
  4834. }
  4835. }
  4836. }
  4837. }
  4838. } else {
  4839. ret = [Y_DOM._getDoc(root).getElementById(id)];
  4840. }
  4841. return ret;
  4842. },
  4843. isWindow: function(obj) {
  4844. return !!(obj && obj.alert && obj.document);
  4845. },
  4846. _removeChildNodes: function(node) {
  4847. while (node.firstChild) {
  4848. node.removeChild(node.firstChild);
  4849. }
  4850. },
  4851. siblings: function(node, fn) {
  4852. var nodes = [],
  4853. sibling = node;
  4854. while ((sibling = sibling[PREVIOUS_SIBLING])) {
  4855. if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
  4856. nodes.unshift(sibling);
  4857. }
  4858. }
  4859. sibling = node;
  4860. while ((sibling = sibling[NEXT_SIBLING])) {
  4861. if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
  4862. nodes.push(sibling);
  4863. }
  4864. }
  4865. return nodes;
  4866. },
  4867. /**
  4868. * Brute force version of contains.
  4869. * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc).
  4870. * @method _bruteContains
  4871. * @private
  4872. * @param {HTMLElement} element The containing html element.
  4873. * @param {HTMLElement} needle The html element that may be contained.
  4874. * @return {Boolean} Whether or not the element is or contains the needle.
  4875. */
  4876. _bruteContains: function(element, needle) {
  4877. while (needle) {
  4878. if (element === needle) {
  4879. return true;
  4880. }
  4881. needle = needle.parentNode;
  4882. }
  4883. return false;
  4884. },
  4885. // TODO: move to Lang?
  4886. /**
  4887. * Memoizes dynamic regular expressions to boost runtime performance.
  4888. * @method _getRegExp
  4889. * @private
  4890. * @param {String} str The string to convert to a regular expression.
  4891. * @param {String} flags optional An optinal string of flags.
  4892. * @return {RegExp} An instance of RegExp
  4893. */
  4894. _getRegExp: function(str, flags) {
  4895. flags = flags || '';
  4896. Y_DOM._regexCache = Y_DOM._regexCache || {};
  4897. if (!Y_DOM._regexCache[str + flags]) {
  4898. Y_DOM._regexCache[str + flags] = new RegExp(str, flags);
  4899. }
  4900. return Y_DOM._regexCache[str + flags];
  4901. },
  4902. // TODO: make getDoc/Win true privates?
  4903. /**
  4904. * returns the appropriate document.
  4905. * @method _getDoc
  4906. * @private
  4907. * @param {HTMLElement} element optional Target element.
  4908. * @return {Object} The document for the given element or the default document.
  4909. */
  4910. _getDoc: function(element) {
  4911. var doc = Y.config.doc;
  4912. if (element) {
  4913. doc = (element[NODE_TYPE] === 9) ? element : // element === document
  4914. element[OWNER_DOCUMENT] || // element === DOM node
  4915. element.document || // element === window
  4916. Y.config.doc; // default
  4917. }
  4918. return doc;
  4919. },
  4920. /**
  4921. * returns the appropriate window.
  4922. * @method _getWin
  4923. * @private
  4924. * @param {HTMLElement} element optional Target element.
  4925. * @return {Object} The window for the given element or the default window.
  4926. */
  4927. _getWin: function(element) {
  4928. var doc = Y_DOM._getDoc(element);
  4929. return doc[DEFAULT_VIEW] || doc[PARENT_WINDOW] || Y.config.win;
  4930. },
  4931. _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
  4932. fn = (typeof fn === 'string') ? Y_DOM[fn] : fn;
  4933. var result,
  4934. i = 0,
  4935. node,
  4936. ret;
  4937. if (fn && nodes) {
  4938. while ((node = nodes[i++])) {
  4939. result = result = fn.call(Y_DOM, node, arg1, arg2, arg3, etc);
  4940. if (typeof result !== 'undefined') {
  4941. (ret) || (ret = []);
  4942. ret.push(result);
  4943. }
  4944. }
  4945. }
  4946. return (typeof ret !== 'undefined') ? ret : nodes;
  4947. },
  4948. wrap: function(node, html) {
  4949. var parent = Y.DOM.create(html),
  4950. nodes = parent.getElementsByTagName('*');
  4951. if (nodes.length) {
  4952. parent = nodes[nodes.length - 1];
  4953. }
  4954. if (node.parentNode) {
  4955. node.parentNode.replaceChild(parent, node);
  4956. }
  4957. parent.appendChild(node);
  4958. },
  4959. unwrap: function(node) {
  4960. var parent = node.parentNode,
  4961. lastChild = parent.lastChild,
  4962. next = node,
  4963. grandparent;
  4964. if (parent) {
  4965. grandparent = parent.parentNode;
  4966. if (grandparent) {
  4967. node = parent.firstChild;
  4968. while (node !== lastChild) {
  4969. next = node.nextSibling;
  4970. grandparent.insertBefore(node, parent);
  4971. node = next;
  4972. }
  4973. grandparent.replaceChild(lastChild, parent);
  4974. } else {
  4975. parent.removeChild(node);
  4976. }
  4977. }
  4978. },
  4979. generateID: function(el) {
  4980. var id = el.id;
  4981. if (!id) {
  4982. id = Y.stamp(el);
  4983. el.id = id;
  4984. }
  4985. return id;
  4986. }
  4987. };
  4988. Y.DOM = Y_DOM;
  4989. }, '3.4.0' ,{requires:['oop','features']});
  4990. YUI.add('dom-base', function(Y) {
  4991. var documentElement = Y.config.doc.documentElement,
  4992. Y_DOM = Y.DOM,
  4993. TAG_NAME = 'tagName',
  4994. OWNER_DOCUMENT = 'ownerDocument',
  4995. EMPTY_STRING = '',
  4996. addFeature = Y.Features.add,
  4997. testFeature = Y.Features.test;
  4998. Y.mix(Y_DOM, {
  4999. /**
  5000. * Returns the text content of the HTMLElement.
  5001. * @method getText
  5002. * @param {HTMLElement} element The html element.
  5003. * @return {String} The text content of the element (includes text of any descending elements).
  5004. */
  5005. getText: (documentElement.textContent !== undefined) ?
  5006. function(element) {
  5007. var ret = '';
  5008. if (element) {
  5009. ret = element.textContent;
  5010. }
  5011. return ret || '';
  5012. } : function(element) {
  5013. var ret = '';
  5014. if (element) {
  5015. ret = element.innerText || element.nodeValue; // might be a textNode
  5016. }
  5017. return ret || '';
  5018. },
  5019. /**
  5020. * Sets the text content of the HTMLElement.
  5021. * @method setText
  5022. * @param {HTMLElement} element The html element.
  5023. * @param {String} content The content to add.
  5024. */
  5025. setText: (documentElement.textContent !== undefined) ?
  5026. function(element, content) {
  5027. if (element) {
  5028. element.textContent = content;
  5029. }
  5030. } : function(element, content) {
  5031. if ('innerText' in element) {
  5032. element.innerText = content;
  5033. } else if ('nodeValue' in element) {
  5034. element.nodeValue = content;
  5035. }
  5036. },
  5037. CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
  5038. 'for': 'htmlFor',
  5039. 'class': 'className'
  5040. } : { // w3c
  5041. 'htmlFor': 'for',
  5042. 'className': 'class'
  5043. },
  5044. /**
  5045. * Provides a normalized attribute interface.
  5046. * @method setAttribute
  5047. * @param {HTMLElement} el The target element for the attribute.
  5048. * @param {String} attr The attribute to set.
  5049. * @param {String} val The value of the attribute.
  5050. */
  5051. setAttribute: function(el, attr, val, ieAttr) {
  5052. if (el && attr && el.setAttribute) {
  5053. attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
  5054. el.setAttribute(attr, val, ieAttr);
  5055. }
  5056. else { Y.log('bad input to setAttribute', 'warn', 'dom'); }
  5057. },
  5058. /**
  5059. * Provides a normalized attribute interface.
  5060. * @method getAttibute
  5061. * @param {HTMLElement} el The target element for the attribute.
  5062. * @param {String} attr The attribute to get.
  5063. * @return {String} The current value of the attribute.
  5064. */
  5065. getAttribute: function(el, attr, ieAttr) {
  5066. ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
  5067. var ret = '';
  5068. if (el && attr && el.getAttribute) {
  5069. attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
  5070. ret = el.getAttribute(attr, ieAttr);
  5071. if (ret === null) {
  5072. ret = ''; // per DOM spec
  5073. }
  5074. }
  5075. else { Y.log('bad input to getAttribute', 'warn', 'dom'); }
  5076. return ret;
  5077. },
  5078. VALUE_SETTERS: {},
  5079. VALUE_GETTERS: {},
  5080. getValue: function(node) {
  5081. var ret = '', // TODO: return null?
  5082. getter;
  5083. if (node && node[TAG_NAME]) {
  5084. getter = Y_DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()];
  5085. if (getter) {
  5086. ret = getter(node);
  5087. } else {
  5088. ret = node.value;
  5089. }
  5090. }
  5091. // workaround for IE8 JSON stringify bug
  5092. // which converts empty string values to null
  5093. if (ret === EMPTY_STRING) {
  5094. ret = EMPTY_STRING; // for real
  5095. }
  5096. return (typeof ret === 'string') ? ret : '';
  5097. },
  5098. setValue: function(node, val) {
  5099. var setter;
  5100. if (node && node[TAG_NAME]) {
  5101. setter = Y_DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()];
  5102. if (setter) {
  5103. setter(node, val);
  5104. } else {
  5105. node.value = val;
  5106. }
  5107. }
  5108. },
  5109. creators: {}
  5110. });
  5111. addFeature('value-set', 'select', {
  5112. test: function() {
  5113. var node = Y.config.doc.createElement('select');
  5114. node.innerHTML = '<option>1</option><option>2</option>';
  5115. node.value = '2';
  5116. return (node.value && node.value === '2');
  5117. }
  5118. });
  5119. if (!testFeature('value-set', 'select')) {
  5120. Y_DOM.VALUE_SETTERS.select = function(node, val) {
  5121. for (var i = 0, options = node.getElementsByTagName('option'), option;
  5122. option = options[i++];) {
  5123. if (Y_DOM.getValue(option) === val) {
  5124. option.selected = true;
  5125. //Y_DOM.setAttribute(option, 'selected', 'selected');
  5126. break;
  5127. }
  5128. }
  5129. }
  5130. }
  5131. Y.mix(Y_DOM.VALUE_GETTERS, {
  5132. button: function(node) {
  5133. return (node.attributes && node.attributes.value) ? node.attributes.value.value : '';
  5134. }
  5135. });
  5136. Y.mix(Y_DOM.VALUE_SETTERS, {
  5137. // IE: node.value changes the button text, which should be handled via innerHTML
  5138. button: function(node, val) {
  5139. var attr = node.attributes.value;
  5140. if (!attr) {
  5141. attr = node[OWNER_DOCUMENT].createAttribute('value');
  5142. node.setAttributeNode(attr);
  5143. }
  5144. attr.value = val;
  5145. }
  5146. });
  5147. Y.mix(Y_DOM.VALUE_GETTERS, {
  5148. option: function(node) {
  5149. var attrs = node.attributes;
  5150. return (attrs.value && attrs.value.specified) ? node.value : node.text;
  5151. },
  5152. select: function(node) {
  5153. var val = node.value,
  5154. options = node.options;
  5155. if (options && options.length) {
  5156. // TODO: implement multipe select
  5157. if (node.multiple) {
  5158. Y.log('multiple select normalization not implemented', 'warn', 'DOM');
  5159. } else {
  5160. val = Y_DOM.getValue(options[node.selectedIndex]);
  5161. }
  5162. }
  5163. return val;
  5164. }
  5165. });
  5166. var addClass, hasClass, removeClass;
  5167. Y.mix(Y.DOM, {
  5168. /**
  5169. * Determines whether a DOM element has the given className.
  5170. * @method hasClass
  5171. * @for DOM
  5172. * @param {HTMLElement} element The DOM element.
  5173. * @param {String} className the class name to search for
  5174. * @return {Boolean} Whether or not the element has the given class.
  5175. */
  5176. hasClass: function(node, className) {
  5177. var re = Y.DOM._getRegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
  5178. return re.test(node.className);
  5179. },
  5180. /**
  5181. * Adds a class name to a given DOM element.
  5182. * @method addClass
  5183. * @for DOM
  5184. * @param {HTMLElement} element The DOM element.
  5185. * @param {String} className the class name to add to the class attribute
  5186. */
  5187. addClass: function(node, className) {
  5188. if (!Y.DOM.hasClass(node, className)) { // skip if already present
  5189. node.className = Y.Lang.trim([node.className, className].join(' '));
  5190. }
  5191. },
  5192. /**
  5193. * Removes a class name from a given element.
  5194. * @method removeClass
  5195. * @for DOM
  5196. * @param {HTMLElement} element The DOM element.
  5197. * @param {String} className the class name to remove from the class attribute
  5198. */
  5199. removeClass: function(node, className) {
  5200. if (className && hasClass(node, className)) {
  5201. node.className = Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
  5202. className + '(?:\\s+|$)'), ' '));
  5203. if ( hasClass(node, className) ) { // in case of multiple adjacent
  5204. removeClass(node, className);
  5205. }
  5206. }
  5207. },
  5208. /**
  5209. * Replace a class with another class for a given element.
  5210. * If no oldClassName is present, the newClassName is simply added.
  5211. * @method replaceClass
  5212. * @for DOM
  5213. * @param {HTMLElement} element The DOM element
  5214. * @param {String} oldClassName the class name to be replaced
  5215. * @param {String} newClassName the class name that will be replacing the old class name
  5216. */
  5217. replaceClass: function(node, oldC, newC) {
  5218. //Y.log('replaceClass replacing ' + oldC + ' with ' + newC, 'info', 'Node');
  5219. removeClass(node, oldC); // remove first in case oldC === newC
  5220. addClass(node, newC);
  5221. },
  5222. /**
  5223. * If the className exists on the node it is removed, if it doesn't exist it is added.
  5224. * @method toggleClass
  5225. * @for DOM
  5226. * @param {HTMLElement} element The DOM element
  5227. * @param {String} className the class name to be toggled
  5228. * @param {Boolean} addClass optional boolean to indicate whether class
  5229. * should be added or removed regardless of current state
  5230. */
  5231. toggleClass: function(node, className, force) {
  5232. var add = (force !== undefined) ? force :
  5233. !(hasClass(node, className));
  5234. if (add) {
  5235. addClass(node, className);
  5236. } else {
  5237. removeClass(node, className);
  5238. }
  5239. }
  5240. });
  5241. hasClass = Y.DOM.hasClass;
  5242. removeClass = Y.DOM.removeClass;
  5243. addClass = Y.DOM.addClass;
  5244. var re_tag = /<([a-z]+)/i,
  5245. Y_DOM = Y.DOM,
  5246. addFeature = Y.Features.add,
  5247. testFeature = Y.Features.test,
  5248. creators = {},
  5249. createFromDIV = function(html, tag) {
  5250. var div = Y.config.doc.createElement('div'),
  5251. ret = true;
  5252. div.innerHTML = html;
  5253. if (!div.firstChild || div.firstChild.tagName !== tag.toUpperCase()) {
  5254. ret = false;
  5255. }
  5256. return ret;
  5257. },
  5258. re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,
  5259. TABLE_OPEN = '<table>',
  5260. TABLE_CLOSE = '</table>';
  5261. Y.mix(Y.DOM, {
  5262. _fragClones: {},
  5263. _create: function(html, doc, tag) {
  5264. tag = tag || 'div';
  5265. var frag = Y_DOM._fragClones[tag];
  5266. if (frag) {
  5267. frag = frag.cloneNode(false);
  5268. } else {
  5269. frag = Y_DOM._fragClones[tag] = doc.createElement(tag);
  5270. }
  5271. frag.innerHTML = html;
  5272. return frag;
  5273. },
  5274. /**
  5275. * Creates a new dom node using the provided markup string.
  5276. * @method create
  5277. * @param {String} html The markup used to create the element
  5278. * @param {HTMLDocument} doc An optional document context
  5279. * @return {HTMLElement|DocumentFragment} returns a single HTMLElement
  5280. * when creating one node, and a documentFragment when creating
  5281. * multiple nodes.
  5282. */
  5283. create: function(html, doc) {
  5284. if (typeof html === 'string') {
  5285. html = Y.Lang.trim(html); // match IE which trims whitespace from innerHTML
  5286. }
  5287. doc = doc || Y.config.doc;
  5288. var m = re_tag.exec(html),
  5289. create = Y_DOM._create,
  5290. custom = creators,
  5291. ret = null,
  5292. creator,
  5293. tag, nodes;
  5294. if (html != undefined) { // not undefined or null
  5295. if (m && m[1]) {
  5296. creator = custom[m[1].toLowerCase()];
  5297. if (typeof creator === 'function') {
  5298. create = creator;
  5299. } else {
  5300. tag = creator;
  5301. }
  5302. }
  5303. nodes = create(html, doc, tag).childNodes;
  5304. if (nodes.length === 1) { // return single node, breaking parentNode ref from "fragment"
  5305. ret = nodes[0].parentNode.removeChild(nodes[0]);
  5306. } else if (nodes[0] && nodes[0].className === 'yui3-big-dummy') { // using dummy node to preserve some attributes (e.g. OPTION not selected)
  5307. if (nodes.length === 2) {
  5308. ret = nodes[0].nextSibling;
  5309. } else {
  5310. nodes[0].parentNode.removeChild(nodes[0]);
  5311. ret = Y_DOM._nl2frag(nodes, doc);
  5312. }
  5313. } else { // return multiple nodes as a fragment
  5314. ret = Y_DOM._nl2frag(nodes, doc);
  5315. }
  5316. }
  5317. return ret;
  5318. },
  5319. _nl2frag: function(nodes, doc) {
  5320. var ret = null,
  5321. i, len;
  5322. if (nodes && (nodes.push || nodes.item) && nodes[0]) {
  5323. doc = doc || nodes[0].ownerDocument;
  5324. ret = doc.createDocumentFragment();
  5325. if (nodes.item) { // convert live list to static array
  5326. nodes = Y.Array(nodes, 0, true);
  5327. }
  5328. for (i = 0, len = nodes.length; i < len; i++) {
  5329. ret.appendChild(nodes[i]);
  5330. }
  5331. } // else inline with log for minification
  5332. else { Y.log('unable to convert ' + nodes + ' to fragment', 'warn', 'dom'); }
  5333. return ret;
  5334. },
  5335. /**
  5336. * Inserts content in a node at the given location
  5337. * @method addHTML
  5338. * @param {HTMLElement} node The node to insert into
  5339. * @param {HTMLElement | Array | HTMLCollection} content The content to be inserted
  5340. * @param {HTMLElement} where Where to insert the content
  5341. * If no "where" is given, content is appended to the node
  5342. * Possible values for "where"
  5343. * <dl>
  5344. * <dt>HTMLElement</dt>
  5345. * <dd>The element to insert before</dd>
  5346. * <dt>"replace"</dt>
  5347. * <dd>Replaces the existing HTML</dd>
  5348. * <dt>"before"</dt>
  5349. * <dd>Inserts before the existing HTML</dd>
  5350. * <dt>"before"</dt>
  5351. * <dd>Inserts content before the node</dd>
  5352. * <dt>"after"</dt>
  5353. * <dd>Inserts content after the node</dd>
  5354. * </dl>
  5355. */
  5356. addHTML: function(node, content, where) {
  5357. var nodeParent = node.parentNode,
  5358. i = 0,
  5359. item,
  5360. ret = content,
  5361. newNode;
  5362. if (content != undefined) { // not null or undefined (maybe 0)
  5363. if (content.nodeType) { // DOM node, just add it
  5364. newNode = content;
  5365. } else if (typeof content == 'string' || typeof content == 'number') {
  5366. ret = newNode = Y_DOM.create(content);
  5367. } else if (content[0] && content[0].nodeType) { // array or collection
  5368. newNode = Y.config.doc.createDocumentFragment();
  5369. while ((item = content[i++])) {
  5370. newNode.appendChild(item); // append to fragment for insertion
  5371. }
  5372. }
  5373. }
  5374. if (where) {
  5375. if (where.nodeType) { // insert regardless of relationship to node
  5376. where.parentNode.insertBefore(newNode, where);
  5377. } else {
  5378. switch (where) {
  5379. case 'replace':
  5380. while (node.firstChild) {
  5381. node.removeChild(node.firstChild);
  5382. }
  5383. if (newNode) { // allow empty content to clear node
  5384. node.appendChild(newNode);
  5385. }
  5386. break;
  5387. case 'before':
  5388. nodeParent.insertBefore(newNode, node);
  5389. break;
  5390. case 'after':
  5391. if (node.nextSibling) { // IE errors if refNode is null
  5392. nodeParent.insertBefore(newNode, node.nextSibling);
  5393. } else {
  5394. nodeParent.appendChild(newNode);
  5395. }
  5396. break;
  5397. default:
  5398. node.appendChild(newNode);
  5399. }
  5400. }
  5401. } else if (newNode) {
  5402. node.appendChild(newNode);
  5403. }
  5404. return ret;
  5405. }
  5406. });
  5407. addFeature('innerhtml', 'table', {
  5408. test: function() {
  5409. var node = Y.config.doc.createElement('table');
  5410. try {
  5411. node.innerHTML = '<tbody></tbody>';
  5412. } catch(e) {
  5413. return false;
  5414. }
  5415. return (node.firstChild && node.firstChild.nodeName === 'TBODY');
  5416. }
  5417. });
  5418. addFeature('innerhtml-div', 'tr', {
  5419. test: function() {
  5420. return createFromDIV('<tr></tr>', 'tr');
  5421. }
  5422. });
  5423. addFeature('innerhtml-div', 'script', {
  5424. test: function() {
  5425. return createFromDIV('<script></script>', 'script');
  5426. }
  5427. });
  5428. if (!testFeature('innerhtml', 'table')) {
  5429. // TODO: thead/tfoot with nested tbody
  5430. // IE adds TBODY when creating TABLE elements (which may share this impl)
  5431. creators.tbody = function(html, doc) {
  5432. var frag = Y_DOM.create(TABLE_OPEN + html + TABLE_CLOSE, doc),
  5433. tb = frag.children.tags('tbody')[0];
  5434. if (frag.children.length > 1 && tb && !re_tbody.test(html)) {
  5435. tb.parentNode.removeChild(tb); // strip extraneous tbody
  5436. }
  5437. return frag;
  5438. };
  5439. }
  5440. if (!testFeature('innerhtml-div', 'script')) {
  5441. creators.script = function(html, doc) {
  5442. var frag = doc.createElement('div');
  5443. frag.innerHTML = '-' + html;
  5444. frag.removeChild(frag.firstChild);
  5445. return frag;
  5446. }
  5447. creators.link = creators.style = creators.script;
  5448. }
  5449. if (!testFeature('innerhtml-div', 'tr')) {
  5450. Y.mix(creators, {
  5451. option: function(html, doc) {
  5452. return Y_DOM.create('<select><option class="yui3-big-dummy" selected></option>' + html + '</select>', doc);
  5453. },
  5454. tr: function(html, doc) {
  5455. return Y_DOM.create('<tbody>' + html + '</tbody>', doc);
  5456. },
  5457. td: function(html, doc) {
  5458. return Y_DOM.create('<tr>' + html + '</tr>', doc);
  5459. },
  5460. col: function(html, doc) {
  5461. return Y_DOM.create('<colgroup>' + html + '</colgroup>', doc);
  5462. },
  5463. tbody: 'table'
  5464. });
  5465. Y.mix(creators, {
  5466. legend: 'fieldset',
  5467. th: creators.td,
  5468. thead: creators.tbody,
  5469. tfoot: creators.tbody,
  5470. caption: creators.tbody,
  5471. colgroup: creators.tbody,
  5472. optgroup: creators.option
  5473. });
  5474. }
  5475. Y_DOM.creators = creators;
  5476. Y.mix(Y.DOM, {
  5477. /**
  5478. * Sets the width of the element to the given size, regardless
  5479. * of box model, border, padding, etc.
  5480. * @method setWidth
  5481. * @param {HTMLElement} element The DOM element.
  5482. * @param {String|Int} size The pixel height to size to
  5483. */
  5484. setWidth: function(node, size) {
  5485. Y.DOM._setSize(node, 'width', size);
  5486. },
  5487. /**
  5488. * Sets the height of the element to the given size, regardless
  5489. * of box model, border, padding, etc.
  5490. * @method setHeight
  5491. * @param {HTMLElement} element The DOM element.
  5492. * @param {String|Int} size The pixel height to size to
  5493. */
  5494. setHeight: function(node, size) {
  5495. Y.DOM._setSize(node, 'height', size);
  5496. },
  5497. _setSize: function(node, prop, val) {
  5498. val = (val > 0) ? val : 0;
  5499. var size = 0;
  5500. node.style[prop] = val + 'px';
  5501. size = (prop === 'height') ? node.offsetHeight : node.offsetWidth;
  5502. if (size > val) {
  5503. val = val - (size - val);
  5504. if (val < 0) {
  5505. val = 0;
  5506. }
  5507. node.style[prop] = val + 'px';
  5508. }
  5509. }
  5510. });
  5511. }, '3.4.0' ,{requires:['dom-core']});
  5512. YUI.add('dom-style', function(Y) {
  5513. (function(Y) {
  5514. /**
  5515. * Add style management functionality To DoM.
  5516. * @module dom
  5517. * @submodule dom-style
  5518. * @for DOM
  5519. */
  5520. var DOCUMENT_ELEMENT = 'documentElement',
  5521. DEFAULT_VIEW = 'defaultView',
  5522. OWNER_DOCUMENT = 'ownerDocument',
  5523. STYLE = 'style',
  5524. FLOAT = 'float',
  5525. CSS_FLOAT = 'cssFloat',
  5526. STYLE_FLOAT = 'styleFloat',
  5527. TRANSPARENT = 'transparent',
  5528. GET_COMPUTED_STYLE = 'getComputedStyle',
  5529. GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
  5530. WINDOW = Y.config.win,
  5531. DOCUMENT = Y.config.doc,
  5532. UNDEFINED = undefined,
  5533. Y_DOM = Y.DOM,
  5534. TRANSFORM = 'transform',
  5535. VENDOR_TRANSFORM = [
  5536. 'WebkitTransform',
  5537. 'MozTransform',
  5538. 'OTransform'
  5539. ],
  5540. re_color = /color$/i,
  5541. re_unit = /width|height|top|left|right|bottom|margin|padding/i;
  5542. Y.Array.each(VENDOR_TRANSFORM, function(val) {
  5543. if (val in DOCUMENT[DOCUMENT_ELEMENT].style) {
  5544. TRANSFORM = val;
  5545. }
  5546. });
  5547. Y.mix(Y_DOM, {
  5548. DEFAULT_UNIT: 'px',
  5549. CUSTOM_STYLES: {
  5550. },
  5551. /**
  5552. * Sets a style property for a given element.
  5553. * @method setStyle
  5554. * @param {HTMLElement} An HTMLElement to apply the style to.
  5555. * @param {String} att The style property to set.
  5556. * @param {String|Number} val The value.
  5557. */
  5558. setStyle: function(node, att, val, style) {
  5559. style = style || node.style;
  5560. var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES;
  5561. if (style) {
  5562. if (val === null || val === '') { // normalize unsetting
  5563. val = '';
  5564. } else if (!isNaN(new Number(val)) && re_unit.test(att)) { // number values may need a unit
  5565. val += Y_DOM.DEFAULT_UNIT;
  5566. }
  5567. if (att in CUSTOM_STYLES) {
  5568. if (CUSTOM_STYLES[att].set) {
  5569. CUSTOM_STYLES[att].set(node, val, style);
  5570. return; // NOTE: return
  5571. } else if (typeof CUSTOM_STYLES[att] === 'string') {
  5572. att = CUSTOM_STYLES[att];
  5573. }
  5574. } else if (att === '') { // unset inline styles
  5575. att = 'cssText';
  5576. val = '';
  5577. }
  5578. style[att] = val;
  5579. }
  5580. },
  5581. /**
  5582. * Returns the current style value for the given property.
  5583. * @method getStyle
  5584. * @param {HTMLElement} An HTMLElement to get the style from.
  5585. * @param {String} att The style property to get.
  5586. */
  5587. getStyle: function(node, att, style) {
  5588. style = style || node.style;
  5589. var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES,
  5590. val = '';
  5591. if (style) {
  5592. if (att in CUSTOM_STYLES) {
  5593. if (CUSTOM_STYLES[att].get) {
  5594. return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return
  5595. } else if (typeof CUSTOM_STYLES[att] === 'string') {
  5596. att = CUSTOM_STYLES[att];
  5597. }
  5598. }
  5599. val = style[att];
  5600. if (val === '') { // TODO: is empty string sufficient?
  5601. val = Y_DOM[GET_COMPUTED_STYLE](node, att);
  5602. }
  5603. }
  5604. return val;
  5605. },
  5606. /**
  5607. * Sets multiple style properties.
  5608. * @method setStyles
  5609. * @param {HTMLElement} node An HTMLElement to apply the styles to.
  5610. * @param {Object} hash An object literal of property:value pairs.
  5611. */
  5612. setStyles: function(node, hash) {
  5613. var style = node.style;
  5614. Y.each(hash, function(v, n) {
  5615. Y_DOM.setStyle(node, n, v, style);
  5616. }, Y_DOM);
  5617. },
  5618. /**
  5619. * Returns the computed style for the given node.
  5620. * @method getComputedStyle
  5621. * @param {HTMLElement} An HTMLElement to get the style from.
  5622. * @param {String} att The style property to get.
  5623. * @return {String} The computed value of the style property.
  5624. */
  5625. getComputedStyle: function(node, att) {
  5626. var val = '',
  5627. doc = node[OWNER_DOCUMENT];
  5628. if (node[STYLE] && doc[DEFAULT_VIEW] && doc[DEFAULT_VIEW][GET_COMPUTED_STYLE]) {
  5629. val = doc[DEFAULT_VIEW][GET_COMPUTED_STYLE](node, null)[att];
  5630. }
  5631. return val;
  5632. }
  5633. });
  5634. // normalize reserved word float alternatives ("cssFloat" or "styleFloat")
  5635. if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== UNDEFINED) {
  5636. Y_DOM.CUSTOM_STYLES[FLOAT] = CSS_FLOAT;
  5637. } else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== UNDEFINED) {
  5638. Y_DOM.CUSTOM_STYLES[FLOAT] = STYLE_FLOAT;
  5639. }
  5640. // fix opera computedStyle default color unit (convert to rgb)
  5641. if (Y.UA.opera) {
  5642. Y_DOM[GET_COMPUTED_STYLE] = function(node, att) {
  5643. var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
  5644. val = view[GET_COMPUTED_STYLE](node, '')[att];
  5645. if (re_color.test(att)) {
  5646. val = Y.Color.toRGB(val);
  5647. }
  5648. return val;
  5649. };
  5650. }
  5651. // safari converts transparent to rgba(), others use "transparent"
  5652. if (Y.UA.webkit) {
  5653. Y_DOM[GET_COMPUTED_STYLE] = function(node, att) {
  5654. var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
  5655. val = view[GET_COMPUTED_STYLE](node, '')[att];
  5656. if (val === 'rgba(0, 0, 0, 0)') {
  5657. val = TRANSPARENT;
  5658. }
  5659. return val;
  5660. };
  5661. }
  5662. Y.DOM._getAttrOffset = function(node, attr) {
  5663. var val = Y.DOM[GET_COMPUTED_STYLE](node, attr),
  5664. offsetParent = node.offsetParent,
  5665. position,
  5666. parentOffset,
  5667. offset;
  5668. if (val === 'auto') {
  5669. position = Y.DOM.getStyle(node, 'position');
  5670. if (position === 'static' || position === 'relative') {
  5671. val = 0;
  5672. } else if (offsetParent && offsetParent[GET_BOUNDING_CLIENT_RECT]) {
  5673. parentOffset = offsetParent[GET_BOUNDING_CLIENT_RECT]()[attr];
  5674. offset = node[GET_BOUNDING_CLIENT_RECT]()[attr];
  5675. if (attr === 'left' || attr === 'top') {
  5676. val = offset - parentOffset;
  5677. } else {
  5678. val = parentOffset - node[GET_BOUNDING_CLIENT_RECT]()[attr];
  5679. }
  5680. }
  5681. }
  5682. return val;
  5683. };
  5684. Y.DOM._getOffset = function(node) {
  5685. var pos,
  5686. xy = null;
  5687. if (node) {
  5688. pos = Y_DOM.getStyle(node, 'position');
  5689. xy = [
  5690. parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'left'), 10),
  5691. parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'top'), 10)
  5692. ];
  5693. if ( isNaN(xy[0]) ) { // in case of 'auto'
  5694. xy[0] = parseInt(Y_DOM.getStyle(node, 'left'), 10); // try inline
  5695. if ( isNaN(xy[0]) ) { // default to offset value
  5696. xy[0] = (pos === 'relative') ? 0 : node.offsetLeft || 0;
  5697. }
  5698. }
  5699. if ( isNaN(xy[1]) ) { // in case of 'auto'
  5700. xy[1] = parseInt(Y_DOM.getStyle(node, 'top'), 10); // try inline
  5701. if ( isNaN(xy[1]) ) { // default to offset value
  5702. xy[1] = (pos === 'relative') ? 0 : node.offsetTop || 0;
  5703. }
  5704. }
  5705. }
  5706. return xy;
  5707. };
  5708. Y_DOM.CUSTOM_STYLES.transform = {
  5709. set: function(node, val, style) {
  5710. style[TRANSFORM] = val;
  5711. },
  5712. get: function(node, style) {
  5713. return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORM);
  5714. }
  5715. };
  5716. })(Y);
  5717. (function(Y) {
  5718. var PARSE_INT = parseInt,
  5719. RE = RegExp;
  5720. Y.Color = {
  5721. KEYWORDS: {
  5722. black: '000',
  5723. silver: 'c0c0c0',
  5724. gray: '808080',
  5725. white: 'fff',
  5726. maroon: '800000',
  5727. red: 'f00',
  5728. purple: '800080',
  5729. fuchsia: 'f0f',
  5730. green: '008000',
  5731. lime: '0f0',
  5732. olive: '808000',
  5733. yellow: 'ff0',
  5734. navy: '000080',
  5735. blue: '00f',
  5736. teal: '008080',
  5737. aqua: '0ff'
  5738. },
  5739. re_RGB: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
  5740. re_hex: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
  5741. re_hex3: /([0-9A-F])/gi,
  5742. toRGB: function(val) {
  5743. if (!Y.Color.re_RGB.test(val)) {
  5744. val = Y.Color.toHex(val);
  5745. }
  5746. if(Y.Color.re_hex.exec(val)) {
  5747. val = 'rgb(' + [
  5748. PARSE_INT(RE.$1, 16),
  5749. PARSE_INT(RE.$2, 16),
  5750. PARSE_INT(RE.$3, 16)
  5751. ].join(', ') + ')';
  5752. }
  5753. return val;
  5754. },
  5755. toHex: function(val) {
  5756. val = Y.Color.KEYWORDS[val] || val;
  5757. if (Y.Color.re_RGB.exec(val)) {
  5758. val = [
  5759. Number(RE.$1).toString(16),
  5760. Number(RE.$2).toString(16),
  5761. Number(RE.$3).toString(16)
  5762. ];
  5763. for (var i = 0; i < val.length; i++) {
  5764. if (val[i].length < 2) {
  5765. val[i] = '0' + val[i];
  5766. }
  5767. }
  5768. val = val.join('');
  5769. }
  5770. if (val.length < 6) {
  5771. val = val.replace(Y.Color.re_hex3, '$1$1');
  5772. }
  5773. if (val !== 'transparent' && val.indexOf('#') < 0) {
  5774. val = '#' + val;
  5775. }
  5776. return val.toUpperCase();
  5777. }
  5778. };
  5779. })(Y);
  5780. }, '3.4.0' ,{requires:['dom-base']});
  5781. YUI.add('dom-style-ie', function(Y) {
  5782. (function(Y) {
  5783. var HAS_LAYOUT = 'hasLayout',
  5784. PX = 'px',
  5785. FILTER = 'filter',
  5786. FILTERS = 'filters',
  5787. OPACITY = 'opacity',
  5788. AUTO = 'auto',
  5789. BORDER_WIDTH = 'borderWidth',
  5790. BORDER_TOP_WIDTH = 'borderTopWidth',
  5791. BORDER_RIGHT_WIDTH = 'borderRightWidth',
  5792. BORDER_BOTTOM_WIDTH = 'borderBottomWidth',
  5793. BORDER_LEFT_WIDTH = 'borderLeftWidth',
  5794. WIDTH = 'width',
  5795. HEIGHT = 'height',
  5796. TRANSPARENT = 'transparent',
  5797. VISIBLE = 'visible',
  5798. GET_COMPUTED_STYLE = 'getComputedStyle',
  5799. UNDEFINED = undefined,
  5800. documentElement = Y.config.doc.documentElement,
  5801. testFeature = Y.Features.test,
  5802. addFeature = Y.Features.add,
  5803. // TODO: unit-less lineHeight (e.g. 1.22)
  5804. re_unit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,
  5805. isIE8 = (Y.UA.ie >= 8),
  5806. _getStyleObj = function(node) {
  5807. return node.currentStyle || node.style;
  5808. },
  5809. ComputedStyle = {
  5810. CUSTOM_STYLES: {},
  5811. get: function(el, property) {
  5812. var value = '',
  5813. current;
  5814. if (el) {
  5815. current = _getStyleObj(el)[property];
  5816. if (property === OPACITY && Y.DOM.CUSTOM_STYLES[OPACITY]) {
  5817. value = Y.DOM.CUSTOM_STYLES[OPACITY].get(el);
  5818. } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert
  5819. value = current;
  5820. } else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
  5821. value = Y.DOM.IE.COMPUTED[property](el, property);
  5822. } else if (re_unit.test(current)) { // convert to pixel
  5823. value = ComputedStyle.getPixel(el, property) + PX;
  5824. } else {
  5825. value = current;
  5826. }
  5827. }
  5828. return value;
  5829. },
  5830. sizeOffsets: {
  5831. width: ['Left', 'Right'],
  5832. height: ['Top', 'Bottom'],
  5833. top: ['Top'],
  5834. bottom: ['Bottom']
  5835. },
  5836. getOffset: function(el, prop) {
  5837. var current = _getStyleObj(el)[prop], // value of "width", "top", etc.
  5838. capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc.
  5839. offset = 'offset' + capped, // "offsetWidth", "offsetTop", etc.
  5840. pixel = 'pixel' + capped, // "pixelWidth", "pixelTop", etc.
  5841. sizeOffsets = ComputedStyle.sizeOffsets[prop],
  5842. mode = el.ownerDocument.compatMode,
  5843. value = '';
  5844. // IE pixelWidth incorrect for percent
  5845. // manually compute by subtracting padding and border from offset size
  5846. // NOTE: clientWidth/Height (size minus border) is 0 when current === AUTO so offsetHeight is used
  5847. // reverting to auto from auto causes position stacking issues (old impl)
  5848. if (current === AUTO || current.indexOf('%') > -1) {
  5849. value = el['offset' + capped];
  5850. if (mode !== 'BackCompat') {
  5851. if (sizeOffsets[0]) {
  5852. value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[0]);
  5853. value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[0] + 'Width', 1);
  5854. }
  5855. if (sizeOffsets[1]) {
  5856. value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[1]);
  5857. value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[1] + 'Width', 1);
  5858. }
  5859. }
  5860. } else { // use style.pixelWidth, etc. to convert to pixels
  5861. // need to map style.width to currentStyle (no currentStyle.pixelWidth)
  5862. if (!el.style[pixel] && !el.style[prop]) {
  5863. el.style[prop] = current;
  5864. }
  5865. value = el.style[pixel];
  5866. }
  5867. return value + PX;
  5868. },
  5869. borderMap: {
  5870. thin: (isIE8) ? '1px' : '2px',
  5871. medium: (isIE8) ? '3px': '4px',
  5872. thick: (isIE8) ? '5px' : '6px'
  5873. },
  5874. getBorderWidth: function(el, property, omitUnit) {
  5875. var unit = omitUnit ? '' : PX,
  5876. current = el.currentStyle[property];
  5877. if (current.indexOf(PX) < 0) { // look up keywords if a border exists
  5878. if (ComputedStyle.borderMap[current] &&
  5879. el.currentStyle.borderStyle !== 'none') {
  5880. current = ComputedStyle.borderMap[current];
  5881. } else { // otherwise no border (default is "medium")
  5882. current = 0;
  5883. }
  5884. }
  5885. return (omitUnit) ? parseFloat(current) : current;
  5886. },
  5887. getPixel: function(node, att) {
  5888. // use pixelRight to convert to px
  5889. var val = null,
  5890. style = _getStyleObj(node),
  5891. styleRight = style.right,
  5892. current = style[att];
  5893. node.style.right = current;
  5894. val = node.style.pixelRight;
  5895. node.style.right = styleRight; // revert
  5896. return val;
  5897. },
  5898. getMargin: function(node, att) {
  5899. var val,
  5900. style = _getStyleObj(node);
  5901. if (style[att] == AUTO) {
  5902. val = 0;
  5903. } else {
  5904. val = ComputedStyle.getPixel(node, att);
  5905. }
  5906. return val + PX;
  5907. },
  5908. getVisibility: function(node, att) {
  5909. var current;
  5910. while ( (current = node.currentStyle) && current[att] == 'inherit') { // NOTE: assignment in test
  5911. node = node.parentNode;
  5912. }
  5913. return (current) ? current[att] : VISIBLE;
  5914. },
  5915. getColor: function(node, att) {
  5916. var current = _getStyleObj(node)[att];
  5917. if (!current || current === TRANSPARENT) {
  5918. Y.DOM.elementByAxis(node, 'parentNode', null, function(parent) {
  5919. current = _getStyleObj(parent)[att];
  5920. if (current && current !== TRANSPARENT) {
  5921. node = parent;
  5922. return true;
  5923. }
  5924. });
  5925. }
  5926. return Y.Color.toRGB(current);
  5927. },
  5928. getBorderColor: function(node, att) {
  5929. var current = _getStyleObj(node),
  5930. val = current[att] || current.color;
  5931. return Y.Color.toRGB(Y.Color.toHex(val));
  5932. }
  5933. },
  5934. //fontSize: getPixelFont,
  5935. IEComputed = {};
  5936. addFeature('style', 'computedStyle', {
  5937. test: function() {
  5938. return 'getComputedStyle' in Y.config.win;
  5939. }
  5940. });
  5941. addFeature('style', 'opacity', {
  5942. test: function() {
  5943. return 'opacity' in documentElement.style;
  5944. }
  5945. });
  5946. addFeature('style', 'filter', {
  5947. test: function() {
  5948. return 'filters' in documentElement;
  5949. }
  5950. });
  5951. // use alpha filter for IE opacity
  5952. if (!testFeature('style', 'opacity') && testFeature('style', 'filter')) {
  5953. Y.DOM.CUSTOM_STYLES[OPACITY] = {
  5954. get: function(node) {
  5955. var val = 100;
  5956. try { // will error if no DXImageTransform
  5957. val = node[FILTERS]['DXImageTransform.Microsoft.Alpha'][OPACITY];
  5958. } catch(e) {
  5959. try { // make sure its in the document
  5960. val = node[FILTERS]('alpha')[OPACITY];
  5961. } catch(err) {
  5962. Y.log('getStyle: IE opacity filter not found; returning 1', 'warn', 'dom-style');
  5963. }
  5964. }
  5965. return val / 100;
  5966. },
  5967. set: function(node, val, style) {
  5968. var current,
  5969. styleObj = _getStyleObj(node),
  5970. currentFilter = styleObj[FILTER];
  5971. style = style || node.style;
  5972. if (val === '') { // normalize inline style behavior
  5973. current = (OPACITY in styleObj) ? styleObj[OPACITY] : 1; // revert to original opacity
  5974. val = current;
  5975. }
  5976. if (typeof currentFilter == 'string') { // in case not appended
  5977. style[FILTER] = currentFilter.replace(/alpha([^)]*\))/gi, '') +
  5978. ((val < 1) ? 'alpha(' + OPACITY + '=' + val * 100 + ')' : '');
  5979. if (!style[FILTER]) {
  5980. style.removeAttribute(FILTER);
  5981. }
  5982. if (!styleObj[HAS_LAYOUT]) {
  5983. style.zoom = 1; // needs layout
  5984. }
  5985. }
  5986. }
  5987. };
  5988. }
  5989. try {
  5990. Y.config.doc.createElement('div').style.height = '-1px';
  5991. } catch(e) { // IE throws error on invalid style set; trap common cases
  5992. Y.DOM.CUSTOM_STYLES.height = {
  5993. set: function(node, val, style) {
  5994. var floatVal = parseFloat(val);
  5995. if (floatVal >= 0 || val === 'auto' || val === '') {
  5996. style.height = val;
  5997. } else {
  5998. Y.log('invalid style value for height: ' + val, 'warn', 'dom-style');
  5999. }
  6000. }
  6001. };
  6002. Y.DOM.CUSTOM_STYLES.width = {
  6003. set: function(node, val, style) {
  6004. var floatVal = parseFloat(val);
  6005. if (floatVal >= 0 || val === 'auto' || val === '') {
  6006. style.width = val;
  6007. } else {
  6008. Y.log('invalid style value for width: ' + val, 'warn', 'dom-style');
  6009. }
  6010. }
  6011. };
  6012. }
  6013. if (!testFeature('style', 'computedStyle')) {
  6014. // TODO: top, right, bottom, left
  6015. IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset;
  6016. IEComputed.color = IEComputed.backgroundColor = ComputedStyle.getColor;
  6017. IEComputed[BORDER_WIDTH] = IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] =
  6018. IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] =
  6019. ComputedStyle.getBorderWidth;
  6020. IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom =
  6021. IEComputed.marginLeft = ComputedStyle.getMargin;
  6022. IEComputed.visibility = ComputedStyle.getVisibility;
  6023. IEComputed.borderColor = IEComputed.borderTopColor =
  6024. IEComputed.borderRightColor = IEComputed.borderBottomColor =
  6025. IEComputed.borderLeftColor = ComputedStyle.getBorderColor;
  6026. Y.DOM[GET_COMPUTED_STYLE] = ComputedStyle.get;
  6027. Y.namespace('DOM.IE');
  6028. Y.DOM.IE.COMPUTED = IEComputed;
  6029. Y.DOM.IE.ComputedStyle = ComputedStyle;
  6030. }
  6031. })(Y);
  6032. }, '3.4.0' ,{requires:['dom-style']});
  6033. YUI.add('dom-screen', function(Y) {
  6034. (function(Y) {
  6035. /**
  6036. * Adds position and region management functionality To DoM.
  6037. * @module dom
  6038. * @submodule dom-screen
  6039. * @for DOM
  6040. */
  6041. var DOCUMENT_ELEMENT = 'documentElement',
  6042. COMPAT_MODE = 'compatMode',
  6043. POSITION = 'position',
  6044. FIXED = 'fixed',
  6045. RELATIVE = 'relative',
  6046. LEFT = 'left',
  6047. TOP = 'top',
  6048. _BACK_COMPAT = 'BackCompat',
  6049. MEDIUM = 'medium',
  6050. BORDER_LEFT_WIDTH = 'borderLeftWidth',
  6051. BORDER_TOP_WIDTH = 'borderTopWidth',
  6052. GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
  6053. GET_COMPUTED_STYLE = 'getComputedStyle',
  6054. Y_DOM = Y.DOM,
  6055. // TODO: how about thead/tbody/tfoot/tr?
  6056. // TODO: does caption matter?
  6057. RE_TABLE = /^t(?:able|d|h)$/i,
  6058. SCROLL_NODE;
  6059. if (Y.UA.ie) {
  6060. if (Y.config.doc[COMPAT_MODE] !== 'BackCompat') {
  6061. SCROLL_NODE = DOCUMENT_ELEMENT;
  6062. } else {
  6063. SCROLL_NODE = 'body';
  6064. }
  6065. }
  6066. Y.mix(Y_DOM, {
  6067. /**
  6068. * Returns the inner height of the viewport (exludes scrollbar).
  6069. * @method winHeight
  6070. * @return {Number} The current height of the viewport.
  6071. */
  6072. winHeight: function(node) {
  6073. var h = Y_DOM._getWinSize(node).height;
  6074. Y.log('winHeight returning ' + h, 'info', 'dom-screen');
  6075. return h;
  6076. },
  6077. /**
  6078. * Returns the inner width of the viewport (exludes scrollbar).
  6079. * @method winWidth
  6080. * @return {Number} The current width of the viewport.
  6081. */
  6082. winWidth: function(node) {
  6083. var w = Y_DOM._getWinSize(node).width;
  6084. Y.log('winWidth returning ' + w, 'info', 'dom-screen');
  6085. return w;
  6086. },
  6087. /**
  6088. * Document height
  6089. * @method docHeight
  6090. * @return {Number} The current height of the document.
  6091. */
  6092. docHeight: function(node) {
  6093. var h = Y_DOM._getDocSize(node).height;
  6094. Y.log('docHeight returning ' + h, 'info', 'dom-screen');
  6095. return Math.max(h, Y_DOM._getWinSize(node).height);
  6096. },
  6097. /**
  6098. * Document width
  6099. * @method docWidth
  6100. * @return {Number} The current width of the document.
  6101. */
  6102. docWidth: function(node) {
  6103. var w = Y_DOM._getDocSize(node).width;
  6104. Y.log('docWidth returning ' + w, 'info', 'dom-screen');
  6105. return Math.max(w, Y_DOM._getWinSize(node).width);
  6106. },
  6107. /**
  6108. * Amount page has been scroll horizontally
  6109. * @method docScrollX
  6110. * @return {Number} The current amount the screen is scrolled horizontally.
  6111. */
  6112. docScrollX: function(node, doc) {
  6113. doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
  6114. var dv = doc.defaultView,
  6115. pageOffset = (dv) ? dv.pageXOffset : 0;
  6116. return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft, pageOffset);
  6117. },
  6118. /**
  6119. * Amount page has been scroll vertically
  6120. * @method docScrollY
  6121. * @return {Number} The current amount the screen is scrolled vertically.
  6122. */
  6123. docScrollY: function(node, doc) {
  6124. doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
  6125. var dv = doc.defaultView,
  6126. pageOffset = (dv) ? dv.pageYOffset : 0;
  6127. return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop, pageOffset);
  6128. },
  6129. /**
  6130. * Gets the current position of an element based on page coordinates.
  6131. * Element must be part of the DOM tree to have page coordinates
  6132. * (display:none or elements not appended return false).
  6133. * @method getXY
  6134. * @param element The target element
  6135. * @return {Array} The XY position of the element
  6136. TODO: test inDocument/display?
  6137. */
  6138. getXY: function() {
  6139. if (Y.config.doc[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
  6140. return function(node) {
  6141. var xy = null,
  6142. scrollLeft,
  6143. scrollTop,
  6144. box,
  6145. off1, off2,
  6146. bLeft, bTop,
  6147. mode,
  6148. doc,
  6149. inDoc,
  6150. rootNode;
  6151. if (node && node.tagName) {
  6152. doc = node.ownerDocument;
  6153. rootNode = doc[DOCUMENT_ELEMENT];
  6154. // inline inDoc check for perf
  6155. if (rootNode.contains) {
  6156. inDoc = rootNode.contains(node);
  6157. } else {
  6158. inDoc = Y.DOM.contains(rootNode, node);
  6159. }
  6160. if (inDoc) {
  6161. scrollLeft = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollLeft : Y_DOM.docScrollX(node, doc);
  6162. scrollTop = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollTop : Y_DOM.docScrollY(node, doc);
  6163. box = node[GET_BOUNDING_CLIENT_RECT]();
  6164. xy = [box.left, box.top];
  6165. if (Y.UA.ie) {
  6166. off1 = 2;
  6167. off2 = 2;
  6168. mode = doc[COMPAT_MODE];
  6169. bLeft = Y_DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_LEFT_WIDTH);
  6170. bTop = Y_DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_TOP_WIDTH);
  6171. if (Y.UA.ie === 6) {
  6172. if (mode !== _BACK_COMPAT) {
  6173. off1 = 0;
  6174. off2 = 0;
  6175. }
  6176. }
  6177. if ((mode == _BACK_COMPAT)) {
  6178. if (bLeft !== MEDIUM) {
  6179. off1 = parseInt(bLeft, 10);
  6180. }
  6181. if (bTop !== MEDIUM) {
  6182. off2 = parseInt(bTop, 10);
  6183. }
  6184. }
  6185. xy[0] -= off1;
  6186. xy[1] -= off2;
  6187. }
  6188. if ((scrollTop || scrollLeft)) {
  6189. if (!Y.UA.ios || (Y.UA.ios >= 4.2)) {
  6190. xy[0] += scrollLeft;
  6191. xy[1] += scrollTop;
  6192. }
  6193. }
  6194. } else {
  6195. xy = Y_DOM._getOffset(node);
  6196. }
  6197. }
  6198. return xy;
  6199. }
  6200. } else {
  6201. return function(node) { // manually calculate by crawling up offsetParents
  6202. //Calculate the Top and Left border sizes (assumes pixels)
  6203. var xy = null,
  6204. doc,
  6205. parentNode,
  6206. bCheck,
  6207. scrollTop,
  6208. scrollLeft;
  6209. if (node) {
  6210. if (Y_DOM.inDoc(node)) {
  6211. xy = [node.offsetLeft, node.offsetTop];
  6212. doc = node.ownerDocument;
  6213. parentNode = node;
  6214. // TODO: refactor with !! or just falsey
  6215. bCheck = ((Y.UA.gecko || Y.UA.webkit > 519) ? true : false);
  6216. // TODO: worth refactoring for TOP/LEFT only?
  6217. while ((parentNode = parentNode.offsetParent)) {
  6218. xy[0] += parentNode.offsetLeft;
  6219. xy[1] += parentNode.offsetTop;
  6220. if (bCheck) {
  6221. xy = Y_DOM._calcBorders(parentNode, xy);
  6222. }
  6223. }
  6224. // account for any scrolled ancestors
  6225. if (Y_DOM.getStyle(node, POSITION) != FIXED) {
  6226. parentNode = node;
  6227. while ((parentNode = parentNode.parentNode)) {
  6228. scrollTop = parentNode.scrollTop;
  6229. scrollLeft = parentNode.scrollLeft;
  6230. //Firefox does something funky with borders when overflow is not visible.
  6231. if (Y.UA.gecko && (Y_DOM.getStyle(parentNode, 'overflow') !== 'visible')) {
  6232. xy = Y_DOM._calcBorders(parentNode, xy);
  6233. }
  6234. if (scrollTop || scrollLeft) {
  6235. xy[0] -= scrollLeft;
  6236. xy[1] -= scrollTop;
  6237. }
  6238. }
  6239. xy[0] += Y_DOM.docScrollX(node, doc);
  6240. xy[1] += Y_DOM.docScrollY(node, doc);
  6241. } else {
  6242. //Fix FIXED position -- add scrollbars
  6243. xy[0] += Y_DOM.docScrollX(node, doc);
  6244. xy[1] += Y_DOM.docScrollY(node, doc);
  6245. }
  6246. } else {
  6247. xy = Y_DOM._getOffset(node);
  6248. }
  6249. }
  6250. return xy;
  6251. };
  6252. }
  6253. }(),// NOTE: Executing for loadtime branching
  6254. /**
  6255. * Gets the current X position of an element based on page coordinates.
  6256. * Element must be part of the DOM tree to have page coordinates
  6257. * (display:none or elements not appended return false).
  6258. * @method getX
  6259. * @param element The target element
  6260. * @return {Int} The X position of the element
  6261. */
  6262. getX: function(node) {
  6263. return Y_DOM.getXY(node)[0];
  6264. },
  6265. /**
  6266. * Gets the current Y position of an element based on page coordinates.
  6267. * Element must be part of the DOM tree to have page coordinates
  6268. * (display:none or elements not appended return false).
  6269. * @method getY
  6270. * @param element The target element
  6271. * @return {Int} The Y position of the element
  6272. */
  6273. getY: function(node) {
  6274. return Y_DOM.getXY(node)[1];
  6275. },
  6276. /**
  6277. * Set the position of an html element in page coordinates.
  6278. * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
  6279. * @method setXY
  6280. * @param element The target element
  6281. * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
  6282. * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
  6283. */
  6284. setXY: function(node, xy, noRetry) {
  6285. var setStyle = Y_DOM.setStyle,
  6286. pos,
  6287. delta,
  6288. newXY,
  6289. currentXY;
  6290. if (node && xy) {
  6291. pos = Y_DOM.getStyle(node, POSITION);
  6292. delta = Y_DOM._getOffset(node);
  6293. if (pos == 'static') { // default to relative
  6294. pos = RELATIVE;
  6295. setStyle(node, POSITION, pos);
  6296. }
  6297. currentXY = Y_DOM.getXY(node);
  6298. if (xy[0] !== null) {
  6299. setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px');
  6300. }
  6301. if (xy[1] !== null) {
  6302. setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px');
  6303. }
  6304. if (!noRetry) {
  6305. newXY = Y_DOM.getXY(node);
  6306. if (newXY[0] !== xy[0] || newXY[1] !== xy[1]) {
  6307. Y_DOM.setXY(node, xy, true);
  6308. }
  6309. }
  6310. Y.log('setXY setting position to ' + xy, 'info', 'dom-screen');
  6311. } else {
  6312. Y.log('setXY failed to set ' + node + ' to ' + xy, 'info', 'dom-screen');
  6313. }
  6314. },
  6315. /**
  6316. * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
  6317. * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
  6318. * @method setX
  6319. * @param element The target element
  6320. * @param {Int} x The X values for new position (coordinates are page-based)
  6321. */
  6322. setX: function(node, x) {
  6323. return Y_DOM.setXY(node, [x, null]);
  6324. },
  6325. /**
  6326. * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
  6327. * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
  6328. * @method setY
  6329. * @param element The target element
  6330. * @param {Int} y The Y values for new position (coordinates are page-based)
  6331. */
  6332. setY: function(node, y) {
  6333. return Y_DOM.setXY(node, [null, y]);
  6334. },
  6335. /**
  6336. * @method swapXY
  6337. * @description Swap the xy position with another node
  6338. * @param {Node} node The node to swap with
  6339. * @param {Node} otherNode The other node to swap with
  6340. * @return {Node}
  6341. */
  6342. swapXY: function(node, otherNode) {
  6343. var xy = Y_DOM.getXY(node);
  6344. Y_DOM.setXY(node, Y_DOM.getXY(otherNode));
  6345. Y_DOM.setXY(otherNode, xy);
  6346. },
  6347. _calcBorders: function(node, xy2) {
  6348. var t = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0,
  6349. l = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0;
  6350. if (Y.UA.gecko) {
  6351. if (RE_TABLE.test(node.tagName)) {
  6352. t = 0;
  6353. l = 0;
  6354. }
  6355. }
  6356. xy2[0] += l;
  6357. xy2[1] += t;
  6358. return xy2;
  6359. },
  6360. _getWinSize: function(node, doc) {
  6361. doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc;
  6362. var win = doc.defaultView || doc.parentWindow,
  6363. mode = doc[COMPAT_MODE],
  6364. h = win.innerHeight,
  6365. w = win.innerWidth,
  6366. root = doc[DOCUMENT_ELEMENT];
  6367. if ( mode && !Y.UA.opera ) { // IE, Gecko
  6368. if (mode != 'CSS1Compat') { // Quirks
  6369. root = doc.body;
  6370. }
  6371. h = root.clientHeight;
  6372. w = root.clientWidth;
  6373. }
  6374. return { height: h, width: w };
  6375. },
  6376. _getDocSize: function(node) {
  6377. var doc = (node) ? Y_DOM._getDoc(node) : Y.config.doc,
  6378. root = doc[DOCUMENT_ELEMENT];
  6379. if (doc[COMPAT_MODE] != 'CSS1Compat') {
  6380. root = doc.body;
  6381. }
  6382. return { height: root.scrollHeight, width: root.scrollWidth };
  6383. }
  6384. });
  6385. })(Y);
  6386. (function(Y) {
  6387. var TOP = 'top',
  6388. RIGHT = 'right',
  6389. BOTTOM = 'bottom',
  6390. LEFT = 'left',
  6391. getOffsets = function(r1, r2) {
  6392. var t = Math.max(r1[TOP], r2[TOP]),
  6393. r = Math.min(r1[RIGHT], r2[RIGHT]),
  6394. b = Math.min(r1[BOTTOM], r2[BOTTOM]),
  6395. l = Math.max(r1[LEFT], r2[LEFT]),
  6396. ret = {};
  6397. ret[TOP] = t;
  6398. ret[RIGHT] = r;
  6399. ret[BOTTOM] = b;
  6400. ret[LEFT] = l;
  6401. return ret;
  6402. },
  6403. DOM = Y.DOM;
  6404. Y.mix(DOM, {
  6405. /**
  6406. * Returns an Object literal containing the following about this element: (top, right, bottom, left)
  6407. * @for DOM
  6408. * @method region
  6409. * @param {HTMLElement} element The DOM element.
  6410. * @return {Object} Object literal containing the following about this element: (top, right, bottom, left)
  6411. */
  6412. region: function(node) {
  6413. var xy = DOM.getXY(node),
  6414. ret = false;
  6415. if (node && xy) {
  6416. ret = DOM._getRegion(
  6417. xy[1], // top
  6418. xy[0] + node.offsetWidth, // right
  6419. xy[1] + node.offsetHeight, // bottom
  6420. xy[0] // left
  6421. );
  6422. }
  6423. return ret;
  6424. },
  6425. /**
  6426. * Find the intersect information for the passes nodes.
  6427. * @method intersect
  6428. * @for DOM
  6429. * @param {HTMLElement} element The first element
  6430. * @param {HTMLElement | Object} element2 The element or region to check the interect with
  6431. * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance i.e. DragDrop)
  6432. * @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
  6433. */
  6434. intersect: function(node, node2, altRegion) {
  6435. var r = altRegion || DOM.region(node), region = {},
  6436. n = node2,
  6437. off;
  6438. if (n.tagName) {
  6439. region = DOM.region(n);
  6440. } else if (Y.Lang.isObject(node2)) {
  6441. region = node2;
  6442. } else {
  6443. return false;
  6444. }
  6445. off = getOffsets(region, r);
  6446. return {
  6447. top: off[TOP],
  6448. right: off[RIGHT],
  6449. bottom: off[BOTTOM],
  6450. left: off[LEFT],
  6451. area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
  6452. yoff: ((off[BOTTOM] - off[TOP])),
  6453. xoff: (off[RIGHT] - off[LEFT]),
  6454. inRegion: DOM.inRegion(node, node2, false, altRegion)
  6455. };
  6456. },
  6457. /**
  6458. * Check if any part of this node is in the passed region
  6459. * @method inRegion
  6460. * @for DOM
  6461. * @param {Object} node2 The node to get the region from or an Object literal of the region
  6462. * $param {Boolean} all Should all of the node be inside the region
  6463. * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
  6464. * @return {Boolean} True if in region, false if not.
  6465. */
  6466. inRegion: function(node, node2, all, altRegion) {
  6467. var region = {},
  6468. r = altRegion || DOM.region(node),
  6469. n = node2,
  6470. off;
  6471. if (n.tagName) {
  6472. region = DOM.region(n);
  6473. } else if (Y.Lang.isObject(node2)) {
  6474. region = node2;
  6475. } else {
  6476. return false;
  6477. }
  6478. if (all) {
  6479. return (
  6480. r[LEFT] >= region[LEFT] &&
  6481. r[RIGHT] <= region[RIGHT] &&
  6482. r[TOP] >= region[TOP] &&
  6483. r[BOTTOM] <= region[BOTTOM] );
  6484. } else {
  6485. off = getOffsets(region, r);
  6486. if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
  6487. return true;
  6488. } else {
  6489. return false;
  6490. }
  6491. }
  6492. },
  6493. /**
  6494. * Check if any part of this element is in the viewport
  6495. * @method inViewportRegion
  6496. * @for DOM
  6497. * @param {HTMLElement} element The DOM element.
  6498. * @param {Boolean} all Should all of the node be inside the region
  6499. * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
  6500. * @return {Boolean} True if in region, false if not.
  6501. */
  6502. inViewportRegion: function(node, all, altRegion) {
  6503. return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
  6504. },
  6505. _getRegion: function(t, r, b, l) {
  6506. var region = {};
  6507. region[TOP] = region[1] = t;
  6508. region[LEFT] = region[0] = l;
  6509. region[BOTTOM] = b;
  6510. region[RIGHT] = r;
  6511. region.width = region[RIGHT] - region[LEFT];
  6512. region.height = region[BOTTOM] - region[TOP];
  6513. return region;
  6514. },
  6515. /**
  6516. * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left)
  6517. * @method viewportRegion
  6518. * @for DOM
  6519. * @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left)
  6520. */
  6521. viewportRegion: function(node) {
  6522. node = node || Y.config.doc.documentElement;
  6523. var ret = false,
  6524. scrollX,
  6525. scrollY;
  6526. if (node) {
  6527. scrollX = DOM.docScrollX(node);
  6528. scrollY = DOM.docScrollY(node);
  6529. ret = DOM._getRegion(scrollY, // top
  6530. DOM.winWidth(node) + scrollX, // right
  6531. scrollY + DOM.winHeight(node), // bottom
  6532. scrollX); // left
  6533. }
  6534. return ret;
  6535. }
  6536. });
  6537. })(Y);
  6538. }, '3.4.0' ,{requires:['dom-base', 'dom-style']});
  6539. YUI.add('selector-native', function(Y) {
  6540. (function(Y) {
  6541. /**
  6542. * The selector-native module provides support for native querySelector
  6543. * @module dom
  6544. * @submodule selector-native
  6545. * @for Selector
  6546. */
  6547. /**
  6548. * Provides support for using CSS selectors to query the DOM
  6549. * @class Selector
  6550. * @static
  6551. * @for Selector
  6552. */
  6553. Y.namespace('Selector'); // allow native module to standalone
  6554. var COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
  6555. OWNER_DOCUMENT = 'ownerDocument';
  6556. var Selector = {
  6557. _foundCache: [],
  6558. useNative: true,
  6559. _compare: ('sourceIndex' in Y.config.doc.documentElement) ?
  6560. function(nodeA, nodeB) {
  6561. var a = nodeA.sourceIndex,
  6562. b = nodeB.sourceIndex;
  6563. if (a === b) {
  6564. return 0;
  6565. } else if (a > b) {
  6566. return 1;
  6567. }
  6568. return -1;
  6569. } : (Y.config.doc.documentElement[COMPARE_DOCUMENT_POSITION] ?
  6570. function(nodeA, nodeB) {
  6571. if (nodeA[COMPARE_DOCUMENT_POSITION](nodeB) & 4) {
  6572. return -1;
  6573. } else {
  6574. return 1;
  6575. }
  6576. } :
  6577. function(nodeA, nodeB) {
  6578. var rangeA, rangeB, compare;
  6579. if (nodeA && nodeB) {
  6580. rangeA = nodeA[OWNER_DOCUMENT].createRange();
  6581. rangeA.setStart(nodeA, 0);
  6582. rangeB = nodeB[OWNER_DOCUMENT].createRange();
  6583. rangeB.setStart(nodeB, 0);
  6584. compare = rangeA.compareBoundaryPoints(1, rangeB); // 1 === Range.START_TO_END
  6585. }
  6586. return compare;
  6587. }),
  6588. _sort: function(nodes) {
  6589. if (nodes) {
  6590. nodes = Y.Array(nodes, 0, true);
  6591. if (nodes.sort) {
  6592. nodes.sort(Selector._compare);
  6593. }
  6594. }
  6595. return nodes;
  6596. },
  6597. _deDupe: function(nodes) {
  6598. var ret = [],
  6599. i, node;
  6600. for (i = 0; (node = nodes[i++]);) {
  6601. if (!node._found) {
  6602. ret[ret.length] = node;
  6603. node._found = true;
  6604. }
  6605. }
  6606. for (i = 0; (node = ret[i++]);) {
  6607. node._found = null;
  6608. node.removeAttribute('_found');
  6609. }
  6610. return ret;
  6611. },
  6612. /**
  6613. * Retrieves a set of nodes based on a given CSS selector.
  6614. * @method query
  6615. *
  6616. * @param {string} selector The CSS Selector to test the node against.
  6617. * @param {HTMLElement} root optional An HTMLElement to start the query from. Defaults to Y.config.doc
  6618. * @param {Boolean} firstOnly optional Whether or not to return only the first match.
  6619. * @return {Array} An array of nodes that match the given selector.
  6620. * @static
  6621. */
  6622. query: function(selector, root, firstOnly, skipNative) {
  6623. root = root || Y.config.doc;
  6624. var ret = [],
  6625. useNative = (Y.Selector.useNative && Y.config.doc.querySelector && !skipNative),
  6626. queries = [[selector, root]],
  6627. query,
  6628. result,
  6629. i,
  6630. fn = (useNative) ? Y.Selector._nativeQuery : Y.Selector._bruteQuery;
  6631. if (selector && fn) {
  6632. // split group into seperate queries
  6633. if (!skipNative && // already done if skipping
  6634. (!useNative || root.tagName)) { // split native when element scoping is needed
  6635. queries = Selector._splitQueries(selector, root);
  6636. }
  6637. for (i = 0; (query = queries[i++]);) {
  6638. result = fn(query[0], query[1], firstOnly);
  6639. if (!firstOnly) { // coerce DOM Collection to Array
  6640. result = Y.Array(result, 0, true);
  6641. }
  6642. if (result) {
  6643. ret = ret.concat(result);
  6644. }
  6645. }
  6646. if (queries.length > 1) { // remove dupes and sort by doc order
  6647. ret = Selector._sort(Selector._deDupe(ret));
  6648. }
  6649. }
  6650. Y.log('query: ' + selector + ' returning: ' + ret.length, 'info', 'Selector');
  6651. return (firstOnly) ? (ret[0] || null) : ret;
  6652. },
  6653. // allows element scoped queries to begin with combinator
  6654. // e.g. query('> p', document.body) === query('body > p')
  6655. _splitQueries: function(selector, node) {
  6656. var groups = selector.split(','),
  6657. queries = [],
  6658. prefix = '',
  6659. i, len;
  6660. if (node) {
  6661. // enforce for element scoping
  6662. if (node.tagName) {
  6663. node.id = node.id || Y.guid();
  6664. prefix = '[id="' + node.id + '"] ';
  6665. }
  6666. for (i = 0, len = groups.length; i < len; ++i) {
  6667. selector = prefix + groups[i];
  6668. queries.push([selector, node]);
  6669. }
  6670. }
  6671. return queries;
  6672. },
  6673. _nativeQuery: function(selector, root, one) {
  6674. if (Y.UA.webkit && selector.indexOf(':checked') > -1 &&
  6675. (Y.Selector.pseudos && Y.Selector.pseudos.checked)) { // webkit (chrome, safari) fails to pick up "selected" with "checked"
  6676. return Y.Selector.query(selector, root, one, true); // redo with skipNative true to try brute query
  6677. }
  6678. try {
  6679. //Y.log('trying native query with: ' + selector, 'info', 'selector-native');
  6680. return root['querySelector' + (one ? '' : 'All')](selector);
  6681. } catch(e) { // fallback to brute if available
  6682. //Y.log('native query error; reverting to brute query with: ' + selector, 'info', 'selector-native');
  6683. return Y.Selector.query(selector, root, one, true); // redo with skipNative true
  6684. }
  6685. },
  6686. filter: function(nodes, selector) {
  6687. var ret = [],
  6688. i, node;
  6689. if (nodes && selector) {
  6690. for (i = 0; (node = nodes[i++]);) {
  6691. if (Y.Selector.test(node, selector)) {
  6692. ret[ret.length] = node;
  6693. }
  6694. }
  6695. } else {
  6696. Y.log('invalid filter input (nodes: ' + nodes +
  6697. ', selector: ' + selector + ')', 'warn', 'Selector');
  6698. }
  6699. return ret;
  6700. },
  6701. test: function(node, selector, root) {
  6702. var ret = false,
  6703. useFrag = false,
  6704. groups,
  6705. parent,
  6706. item,
  6707. items,
  6708. frag,
  6709. i, j, group;
  6710. if (node && node.tagName) { // only test HTMLElements
  6711. if (typeof selector == 'function') { // test with function
  6712. ret = selector.call(node, node);
  6713. } else { // test with query
  6714. // we need a root if off-doc
  6715. groups = selector.split(',');
  6716. if (!root && !Y.DOM.inDoc(node)) {
  6717. parent = node.parentNode;
  6718. if (parent) {
  6719. root = parent;
  6720. } else { // only use frag when no parent to query
  6721. frag = node[OWNER_DOCUMENT].createDocumentFragment();
  6722. frag.appendChild(node);
  6723. root = frag;
  6724. useFrag = true;
  6725. }
  6726. }
  6727. root = root || node[OWNER_DOCUMENT];
  6728. if (!node.id) {
  6729. node.id = Y.guid();
  6730. }
  6731. for (i = 0; (group = groups[i++]);) { // TODO: off-dom test
  6732. group += '[id="' + node.id + '"]';
  6733. items = Y.Selector.query(group, root);
  6734. for (j = 0; item = items[j++];) {
  6735. if (item === node) {
  6736. ret = true;
  6737. break;
  6738. }
  6739. }
  6740. if (ret) {
  6741. break;
  6742. }
  6743. }
  6744. if (useFrag) { // cleanup
  6745. frag.removeChild(node);
  6746. }
  6747. };
  6748. }
  6749. return ret;
  6750. },
  6751. /**
  6752. * A convenience function to emulate Y.Node's aNode.ancestor(selector).
  6753. * @param {HTMLElement} element An HTMLElement to start the query from.
  6754. * @param {String} selector The CSS selector to test the node against.
  6755. * @return {HTMLElement} The ancestor node matching the selector, or null.
  6756. * @param {Boolean} testSelf optional Whether or not to include the element in the scan
  6757. * @static
  6758. * @method ancestor
  6759. */
  6760. ancestor: function (element, selector, testSelf) {
  6761. return Y.DOM.ancestor(element, function(n) {
  6762. return Y.Selector.test(n, selector);
  6763. }, testSelf);
  6764. }
  6765. };
  6766. Y.mix(Y.Selector, Selector, true);
  6767. })(Y);
  6768. }, '3.4.0' ,{requires:['dom-base']});
  6769. YUI.add('selector', function(Y) {
  6770. }, '3.4.0' ,{requires:['selector-native']});
  6771. YUI.add('event-custom-base', function(Y) {
  6772. /**
  6773. * Custom event engine, DOM event listener abstraction layer, synthetic DOM
  6774. * events.
  6775. * @module event-custom
  6776. */
  6777. Y.Env.evt = {
  6778. handles: {},
  6779. plugins: {}
  6780. };
  6781. /**
  6782. * Custom event engine, DOM event listener abstraction layer, synthetic DOM
  6783. * events.
  6784. * @module event-custom
  6785. * @submodule event-custom-base
  6786. */
  6787. /**
  6788. * Allows for the insertion of methods that are executed before or after
  6789. * a specified method
  6790. * @class Do
  6791. * @static
  6792. */
  6793. var DO_BEFORE = 0,
  6794. DO_AFTER = 1,
  6795. DO = {
  6796. /**
  6797. * Cache of objects touched by the utility
  6798. * @property objs
  6799. * @static
  6800. */
  6801. objs: {},
  6802. /**
  6803. * <p>Execute the supplied method before the specified function. Wrapping
  6804. * function may optionally return an instance of the following classes to
  6805. * further alter runtime behavior:</p>
  6806. * <dl>
  6807. * <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
  6808. * <dd>Immediatly stop execution and return
  6809. * <code>returnValue</code>. No other wrapping functions will be
  6810. * executed.</dd>
  6811. * <dt></code>Y.Do.AlterArgs(message, newArgArray)</code></dt>
  6812. * <dd>Replace the arguments that the original function will be
  6813. * called with.</dd>
  6814. * <dt></code>Y.Do.Prevent(message)</code></dt>
  6815. * <dd>Don't execute the wrapped function. Other before phase
  6816. * wrappers will be executed.</dd>
  6817. * </dl>
  6818. *
  6819. * @method before
  6820. * @param fn {Function} the function to execute
  6821. * @param obj the object hosting the method to displace
  6822. * @param sFn {string} the name of the method to displace
  6823. * @param c The execution context for fn
  6824. * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
  6825. * when the event fires.
  6826. * @return {string} handle for the subscription
  6827. * @static
  6828. */
  6829. before: function(fn, obj, sFn, c) {
  6830. // Y.log('Do before: ' + sFn, 'info', 'event');
  6831. var f = fn, a;
  6832. if (c) {
  6833. a = [fn, c].concat(Y.Array(arguments, 4, true));
  6834. f = Y.rbind.apply(Y, a);
  6835. }
  6836. return this._inject(DO_BEFORE, f, obj, sFn);
  6837. },
  6838. /**
  6839. * <p>Execute the supplied method after the specified function. Wrapping
  6840. * function may optionally return an instance of the following classes to
  6841. * further alter runtime behavior:</p>
  6842. * <dl>
  6843. * <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
  6844. * <dd>Immediatly stop execution and return
  6845. * <code>returnValue</code>. No other wrapping functions will be
  6846. * executed.</dd>
  6847. * <dt></code>Y.Do.AlterReturn(message, returnValue)</code></dt>
  6848. * <dd>Return <code>returnValue</code> instead of the wrapped
  6849. * method's original return value. This can be further altered by
  6850. * other after phase wrappers.</dd>
  6851. * </dl>
  6852. *
  6853. * <p>The static properties <code>Y.Do.originalRetVal</code> and
  6854. * <code>Y.Do.currentRetVal</code> will be populated for reference.</p>
  6855. *
  6856. * @method after
  6857. * @param fn {Function} the function to execute
  6858. * @param obj the object hosting the method to displace
  6859. * @param sFn {string} the name of the method to displace
  6860. * @param c The execution context for fn
  6861. * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
  6862. * @return {string} handle for the subscription
  6863. * @static
  6864. */
  6865. after: function(fn, obj, sFn, c) {
  6866. var f = fn, a;
  6867. if (c) {
  6868. a = [fn, c].concat(Y.Array(arguments, 4, true));
  6869. f = Y.rbind.apply(Y, a);
  6870. }
  6871. return this._inject(DO_AFTER, f, obj, sFn);
  6872. },
  6873. /**
  6874. * Execute the supplied method before or after the specified function.
  6875. * Used by <code>before</code> and <code>after</code>.
  6876. *
  6877. * @method _inject
  6878. * @param when {string} before or after
  6879. * @param fn {Function} the function to execute
  6880. * @param obj the object hosting the method to displace
  6881. * @param sFn {string} the name of the method to displace
  6882. * @param c The execution context for fn
  6883. * @return {string} handle for the subscription
  6884. * @private
  6885. * @static
  6886. */
  6887. _inject: function(when, fn, obj, sFn) {
  6888. // object id
  6889. var id = Y.stamp(obj), o, sid;
  6890. if (! this.objs[id]) {
  6891. // create a map entry for the obj if it doesn't exist
  6892. this.objs[id] = {};
  6893. }
  6894. o = this.objs[id];
  6895. if (! o[sFn]) {
  6896. // create a map entry for the method if it doesn't exist
  6897. o[sFn] = new Y.Do.Method(obj, sFn);
  6898. // re-route the method to our wrapper
  6899. obj[sFn] =
  6900. function() {
  6901. return o[sFn].exec.apply(o[sFn], arguments);
  6902. };
  6903. }
  6904. // subscriber id
  6905. sid = id + Y.stamp(fn) + sFn;
  6906. // register the callback
  6907. o[sFn].register(sid, fn, when);
  6908. return new Y.EventHandle(o[sFn], sid);
  6909. },
  6910. /**
  6911. * Detach a before or after subscription.
  6912. *
  6913. * @method detach
  6914. * @param handle {string} the subscription handle
  6915. * @static
  6916. */
  6917. detach: function(handle) {
  6918. if (handle.detach) {
  6919. handle.detach();
  6920. }
  6921. },
  6922. _unload: function(e, me) {
  6923. }
  6924. };
  6925. Y.Do = DO;
  6926. //////////////////////////////////////////////////////////////////////////
  6927. /**
  6928. * Contains the return value from the wrapped method, accessible
  6929. * by 'after' event listeners.
  6930. *
  6931. * @property Do.originalRetVal
  6932. * @static
  6933. * @since 3.2.0
  6934. */
  6935. /**
  6936. * Contains the current state of the return value, consumable by
  6937. * 'after' event listeners, and updated if an after subscriber
  6938. * changes the return value generated by the wrapped function.
  6939. *
  6940. * @property Do.currentRetVal
  6941. * @static
  6942. * @since 3.2.0
  6943. */
  6944. //////////////////////////////////////////////////////////////////////////
  6945. /**
  6946. * Wrapper for a displaced method with aop enabled
  6947. * @class Do.Method
  6948. * @constructor
  6949. * @param obj The object to operate on
  6950. * @param sFn The name of the method to displace
  6951. */
  6952. DO.Method = function(obj, sFn) {
  6953. this.obj = obj;
  6954. this.methodName = sFn;
  6955. this.method = obj[sFn];
  6956. this.before = {};
  6957. this.after = {};
  6958. };
  6959. /**
  6960. * Register a aop subscriber
  6961. * @method register
  6962. * @param sid {string} the subscriber id
  6963. * @param fn {Function} the function to execute
  6964. * @param when {string} when to execute the function
  6965. */
  6966. DO.Method.prototype.register = function (sid, fn, when) {
  6967. if (when) {
  6968. this.after[sid] = fn;
  6969. } else {
  6970. this.before[sid] = fn;
  6971. }
  6972. };
  6973. /**
  6974. * Unregister a aop subscriber
  6975. * @method delete
  6976. * @param sid {string} the subscriber id
  6977. * @param fn {Function} the function to execute
  6978. * @param when {string} when to execute the function
  6979. */
  6980. DO.Method.prototype._delete = function (sid) {
  6981. // Y.log('Y.Do._delete: ' + sid, 'info', 'Event');
  6982. delete this.before[sid];
  6983. delete this.after[sid];
  6984. };
  6985. /**
  6986. * <p>Execute the wrapped method. All arguments are passed into the wrapping
  6987. * functions. If any of the before wrappers return an instance of
  6988. * <code>Y.Do.Halt</code> or <code>Y.Do.Prevent</code>, neither the wrapped
  6989. * function nor any after phase subscribers will be executed.</p>
  6990. *
  6991. * <p>The return value will be the return value of the wrapped function or one
  6992. * provided by a wrapper function via an instance of <code>Y.Do.Halt</code> or
  6993. * <code>Y.Do.AlterReturn</code>.
  6994. *
  6995. * @method exec
  6996. * @param arg* {any} Arguments are passed to the wrapping and wrapped functions
  6997. * @return {any} Return value of wrapped function unless overwritten (see above)
  6998. */
  6999. DO.Method.prototype.exec = function () {
  7000. var args = Y.Array(arguments, 0, true),
  7001. i, ret, newRet,
  7002. bf = this.before,
  7003. af = this.after,
  7004. prevented = false;
  7005. // execute before
  7006. for (i in bf) {
  7007. if (bf.hasOwnProperty(i)) {
  7008. ret = bf[i].apply(this.obj, args);
  7009. if (ret) {
  7010. switch (ret.constructor) {
  7011. case DO.Halt:
  7012. return ret.retVal;
  7013. case DO.AlterArgs:
  7014. args = ret.newArgs;
  7015. break;
  7016. case DO.Prevent:
  7017. prevented = true;
  7018. break;
  7019. default:
  7020. }
  7021. }
  7022. }
  7023. }
  7024. // execute method
  7025. if (!prevented) {
  7026. ret = this.method.apply(this.obj, args);
  7027. }
  7028. DO.originalRetVal = ret;
  7029. DO.currentRetVal = ret;
  7030. // execute after methods.
  7031. for (i in af) {
  7032. if (af.hasOwnProperty(i)) {
  7033. newRet = af[i].apply(this.obj, args);
  7034. // Stop processing if a Halt object is returned
  7035. if (newRet && newRet.constructor == DO.Halt) {
  7036. return newRet.retVal;
  7037. // Check for a new return value
  7038. } else if (newRet && newRet.constructor == DO.AlterReturn) {
  7039. ret = newRet.newRetVal;
  7040. // Update the static retval state
  7041. DO.currentRetVal = ret;
  7042. }
  7043. }
  7044. }
  7045. return ret;
  7046. };
  7047. //////////////////////////////////////////////////////////////////////////
  7048. /**
  7049. * Return an AlterArgs object when you want to change the arguments that
  7050. * were passed into the function. Useful for Do.before subscribers. An
  7051. * example would be a service that scrubs out illegal characters prior to
  7052. * executing the core business logic.
  7053. * @class Do.AlterArgs
  7054. * @constructor
  7055. * @param msg {String} (optional) Explanation of the altered return value
  7056. * @param newArgs {Array} Call parameters to be used for the original method
  7057. * instead of the arguments originally passed in.
  7058. */
  7059. DO.AlterArgs = function(msg, newArgs) {
  7060. this.msg = msg;
  7061. this.newArgs = newArgs;
  7062. };
  7063. /**
  7064. * Return an AlterReturn object when you want to change the result returned
  7065. * from the core method to the caller. Useful for Do.after subscribers.
  7066. * @class Do.AlterReturn
  7067. * @constructor
  7068. * @param msg {String} (optional) Explanation of the altered return value
  7069. * @param newRetVal {any} Return value passed to code that invoked the wrapped
  7070. * function.
  7071. */
  7072. DO.AlterReturn = function(msg, newRetVal) {
  7073. this.msg = msg;
  7074. this.newRetVal = newRetVal;
  7075. };
  7076. /**
  7077. * Return a Halt object when you want to terminate the execution
  7078. * of all subsequent subscribers as well as the wrapped method
  7079. * if it has not exectued yet. Useful for Do.before subscribers.
  7080. * @class Do.Halt
  7081. * @constructor
  7082. * @param msg {String} (optional) Explanation of why the termination was done
  7083. * @param retVal {any} Return value passed to code that invoked the wrapped
  7084. * function.
  7085. */
  7086. DO.Halt = function(msg, retVal) {
  7087. this.msg = msg;
  7088. this.retVal = retVal;
  7089. };
  7090. /**
  7091. * Return a Prevent object when you want to prevent the wrapped function
  7092. * from executing, but want the remaining listeners to execute. Useful
  7093. * for Do.before subscribers.
  7094. * @class Do.Prevent
  7095. * @constructor
  7096. * @param msg {String} (optional) Explanation of why the termination was done
  7097. */
  7098. DO.Prevent = function(msg) {
  7099. this.msg = msg;
  7100. };
  7101. /**
  7102. * Return an Error object when you want to terminate the execution
  7103. * of all subsequent method calls.
  7104. * @class Do.Error
  7105. * @constructor
  7106. * @param msg {String} (optional) Explanation of the altered return value
  7107. * @param retVal {any} Return value passed to code that invoked the wrapped
  7108. * function.
  7109. * @deprecated use Y.Do.Halt or Y.Do.Prevent
  7110. */
  7111. DO.Error = DO.Halt;
  7112. //////////////////////////////////////////////////////////////////////////
  7113. // Y["Event"] && Y.Event.addListener(window, "unload", Y.Do._unload, Y.Do);
  7114. /**
  7115. * Custom event engine, DOM event listener abstraction layer, synthetic DOM
  7116. * events.
  7117. * @module event-custom
  7118. * @submodule event-custom-base
  7119. */
  7120. // var onsubscribeType = "_event:onsub",
  7121. var AFTER = 'after',
  7122. CONFIGS = [
  7123. 'broadcast',
  7124. 'monitored',
  7125. 'bubbles',
  7126. 'context',
  7127. 'contextFn',
  7128. 'currentTarget',
  7129. 'defaultFn',
  7130. 'defaultTargetOnly',
  7131. 'details',
  7132. 'emitFacade',
  7133. 'fireOnce',
  7134. 'async',
  7135. 'host',
  7136. 'preventable',
  7137. 'preventedFn',
  7138. 'queuable',
  7139. 'silent',
  7140. 'stoppedFn',
  7141. 'target',
  7142. 'type'
  7143. ],
  7144. YUI3_SIGNATURE = 9,
  7145. YUI_LOG = 'yui:log';
  7146. /**
  7147. * The CustomEvent class lets you define events for your application
  7148. * that can be subscribed to by one or more independent component.
  7149. *
  7150. * @param {String} type The type of event, which is passed to the callback
  7151. * when the event fires.
  7152. * @param {object} o configuration object.
  7153. * @class CustomEvent
  7154. * @constructor
  7155. */
  7156. Y.CustomEvent = function(type, o) {
  7157. // if (arguments.length > 2) {
  7158. // this.log('CustomEvent context and silent are now in the config', 'warn', 'Event');
  7159. // }
  7160. o = o || {};
  7161. this.id = Y.stamp(this);
  7162. /**
  7163. * The type of event, returned to subscribers when the event fires
  7164. * @property type
  7165. * @type string
  7166. */
  7167. this.type = type;
  7168. /**
  7169. * The context the the event will fire from by default. Defaults to the YUI
  7170. * instance.
  7171. * @property context
  7172. * @type object
  7173. */
  7174. this.context = Y;
  7175. /**
  7176. * Monitor when an event is attached or detached.
  7177. *
  7178. * @property monitored
  7179. * @type boolean
  7180. */
  7181. // this.monitored = false;
  7182. this.logSystem = (type == YUI_LOG);
  7183. /**
  7184. * If 0, this event does not broadcast. If 1, the YUI instance is notified
  7185. * every time this event fires. If 2, the YUI instance and the YUI global
  7186. * (if event is enabled on the global) are notified every time this event
  7187. * fires.
  7188. * @property broadcast
  7189. * @type int
  7190. */
  7191. // this.broadcast = 0;
  7192. /**
  7193. * By default all custom events are logged in the debug build, set silent
  7194. * to true to disable debug outpu for this event.
  7195. * @property silent
  7196. * @type boolean
  7197. */
  7198. this.silent = this.logSystem;
  7199. /**
  7200. * Specifies whether this event should be queued when the host is actively
  7201. * processing an event. This will effect exectution order of the callbacks
  7202. * for the various events.
  7203. * @property queuable
  7204. * @type boolean
  7205. * @default false
  7206. */
  7207. // this.queuable = false;
  7208. /**
  7209. * The subscribers to this event
  7210. * @property subscribers
  7211. * @type Subscriber {}
  7212. */
  7213. this.subscribers = {};
  7214. /**
  7215. * 'After' subscribers
  7216. * @property afters
  7217. * @type Subscriber {}
  7218. */
  7219. this.afters = {};
  7220. /**
  7221. * This event has fired if true
  7222. *
  7223. * @property fired
  7224. * @type boolean
  7225. * @default false;
  7226. */
  7227. // this.fired = false;
  7228. /**
  7229. * An array containing the arguments the custom event
  7230. * was last fired with.
  7231. * @property firedWith
  7232. * @type Array
  7233. */
  7234. // this.firedWith;
  7235. /**
  7236. * This event should only fire one time if true, and if
  7237. * it has fired, any new subscribers should be notified
  7238. * immediately.
  7239. *
  7240. * @property fireOnce
  7241. * @type boolean
  7242. * @default false;
  7243. */
  7244. // this.fireOnce = false;
  7245. /**
  7246. * fireOnce listeners will fire syncronously unless async
  7247. * is set to true
  7248. * @property async
  7249. * @type boolean
  7250. * @default false
  7251. */
  7252. //this.async = false;
  7253. /**
  7254. * Flag for stopPropagation that is modified during fire()
  7255. * 1 means to stop propagation to bubble targets. 2 means
  7256. * to also stop additional subscribers on this target.
  7257. * @property stopped
  7258. * @type int
  7259. */
  7260. // this.stopped = 0;
  7261. /**
  7262. * Flag for preventDefault that is modified during fire().
  7263. * if it is not 0, the default behavior for this event
  7264. * @property prevented
  7265. * @type int
  7266. */
  7267. // this.prevented = 0;
  7268. /**
  7269. * Specifies the host for this custom event. This is used
  7270. * to enable event bubbling
  7271. * @property host
  7272. * @type EventTarget
  7273. */
  7274. // this.host = null;
  7275. /**
  7276. * The default function to execute after event listeners
  7277. * have fire, but only if the default action was not
  7278. * prevented.
  7279. * @property defaultFn
  7280. * @type Function
  7281. */
  7282. // this.defaultFn = null;
  7283. /**
  7284. * The function to execute if a subscriber calls
  7285. * stopPropagation or stopImmediatePropagation
  7286. * @property stoppedFn
  7287. * @type Function
  7288. */
  7289. // this.stoppedFn = null;
  7290. /**
  7291. * The function to execute if a subscriber calls
  7292. * preventDefault
  7293. * @property preventedFn
  7294. * @type Function
  7295. */
  7296. // this.preventedFn = null;
  7297. /**
  7298. * Specifies whether or not this event's default function
  7299. * can be cancelled by a subscriber by executing preventDefault()
  7300. * on the event facade
  7301. * @property preventable
  7302. * @type boolean
  7303. * @default true
  7304. */
  7305. this.preventable = true;
  7306. /**
  7307. * Specifies whether or not a subscriber can stop the event propagation
  7308. * via stopPropagation(), stopImmediatePropagation(), or halt()
  7309. *
  7310. * Events can only bubble if emitFacade is true.
  7311. *
  7312. * @property bubbles
  7313. * @type boolean
  7314. * @default true
  7315. */
  7316. this.bubbles = true;
  7317. /**
  7318. * Supports multiple options for listener signatures in order to
  7319. * port YUI 2 apps.
  7320. * @property signature
  7321. * @type int
  7322. * @default 9
  7323. */
  7324. this.signature = YUI3_SIGNATURE;
  7325. this.subCount = 0;
  7326. this.afterCount = 0;
  7327. // this.hasSubscribers = false;
  7328. // this.hasAfters = false;
  7329. /**
  7330. * If set to true, the custom event will deliver an EventFacade object
  7331. * that is similar to a DOM event object.
  7332. * @property emitFacade
  7333. * @type boolean
  7334. * @default false
  7335. */
  7336. // this.emitFacade = false;
  7337. this.applyConfig(o, true);
  7338. // this.log("Creating " + this.type);
  7339. };
  7340. Y.CustomEvent.prototype = {
  7341. constructor: Y.CustomEvent,
  7342. /**
  7343. * Returns the number of subscribers for this event as the sum of the on()
  7344. * subscribers and after() subscribers.
  7345. *
  7346. * @method hasSubs
  7347. * @return Number
  7348. */
  7349. hasSubs: function(when) {
  7350. var s = this.subCount, a = this.afterCount, sib = this.sibling;
  7351. if (sib) {
  7352. s += sib.subCount;
  7353. a += sib.afterCount;
  7354. }
  7355. if (when) {
  7356. return (when == 'after') ? a : s;
  7357. }
  7358. return (s + a);
  7359. },
  7360. /**
  7361. * Monitor the event state for the subscribed event. The first parameter
  7362. * is what should be monitored, the rest are the normal parameters when
  7363. * subscribing to an event.
  7364. * @method monitor
  7365. * @param what {string} what to monitor ('detach', 'attach', 'publish').
  7366. * @return {EventHandle} return value from the monitor event subscription.
  7367. */
  7368. monitor: function(what) {
  7369. this.monitored = true;
  7370. var type = this.id + '|' + this.type + '_' + what,
  7371. args = Y.Array(arguments, 0, true);
  7372. args[0] = type;
  7373. return this.host.on.apply(this.host, args);
  7374. },
  7375. /**
  7376. * Get all of the subscribers to this event and any sibling event
  7377. * @method getSubs
  7378. * @return {Array} first item is the on subscribers, second the after.
  7379. */
  7380. getSubs: function() {
  7381. var s = Y.merge(this.subscribers), a = Y.merge(this.afters), sib = this.sibling;
  7382. if (sib) {
  7383. Y.mix(s, sib.subscribers);
  7384. Y.mix(a, sib.afters);
  7385. }
  7386. return [s, a];
  7387. },
  7388. /**
  7389. * Apply configuration properties. Only applies the CONFIG whitelist
  7390. * @method applyConfig
  7391. * @param o hash of properties to apply.
  7392. * @param force {boolean} if true, properties that exist on the event
  7393. * will be overwritten.
  7394. */
  7395. applyConfig: function(o, force) {
  7396. if (o) {
  7397. Y.mix(this, o, force, CONFIGS);
  7398. }
  7399. },
  7400. /**
  7401. * Create the Subscription for subscribing function, context, and bound
  7402. * arguments. If this is a fireOnce event, the subscriber is immediately
  7403. * notified.
  7404. *
  7405. * @method _on
  7406. * @param fn {Function} Subscription callback
  7407. * @param [context] {Object} Override `this` in the callback
  7408. * @param [args] {Array} bound arguments that will be passed to the callback after the arguments generated by fire()
  7409. * @param [when] {String} "after" to slot into after subscribers
  7410. * @return {EventHandle}
  7411. * @protected
  7412. */
  7413. _on: function(fn, context, args, when) {
  7414. if (!fn) {
  7415. this.log('Invalid callback for CE: ' + this.type);
  7416. }
  7417. var s = new Y.Subscriber(fn, context, args, when);
  7418. if (this.fireOnce && this.fired) {
  7419. if (this.async) {
  7420. setTimeout(Y.bind(this._notify, this, s, this.firedWith), 0);
  7421. } else {
  7422. this._notify(s, this.firedWith);
  7423. }
  7424. }
  7425. if (when == AFTER) {
  7426. this.afters[s.id] = s;
  7427. this.afterCount++;
  7428. } else {
  7429. this.subscribers[s.id] = s;
  7430. this.subCount++;
  7431. }
  7432. return new Y.EventHandle(this, s);
  7433. },
  7434. /**
  7435. * Listen for this event
  7436. * @method subscribe
  7437. * @param {Function} fn The function to execute.
  7438. * @return {EventHandle} Unsubscribe handle.
  7439. * @deprecated use on.
  7440. */
  7441. subscribe: function(fn, context) {
  7442. Y.log('ce.subscribe deprecated, use "on"', 'warn', 'deprecated');
  7443. var a = (arguments.length > 2) ? Y.Array(arguments, 2, true) : null;
  7444. return this._on(fn, context, a, true);
  7445. },
  7446. /**
  7447. * Listen for this event
  7448. * @method on
  7449. * @param {Function} fn The function to execute.
  7450. * @param {object} context optional execution context.
  7451. * @param {mixed} arg* 0..n additional arguments to supply to the subscriber
  7452. * when the event fires.
  7453. * @return {EventHandle} An object with a detach method to detch the handler(s).
  7454. */
  7455. on: function(fn, context) {
  7456. var a = (arguments.length > 2) ? Y.Array(arguments, 2, true) : null;
  7457. if (this.host) {
  7458. this.host._monitor('attach', this.type, {
  7459. args: arguments
  7460. });
  7461. }
  7462. return this._on(fn, context, a, true);
  7463. },
  7464. /**
  7465. * Listen for this event after the normal subscribers have been notified and
  7466. * the default behavior has been applied. If a normal subscriber prevents the
  7467. * default behavior, it also prevents after listeners from firing.
  7468. * @method after
  7469. * @param {Function} fn The function to execute.
  7470. * @param {object} context optional execution context.
  7471. * @param {mixed} arg* 0..n additional arguments to supply to the subscriber
  7472. * when the event fires.
  7473. * @return {EventHandle} handle Unsubscribe handle.
  7474. */
  7475. after: function(fn, context) {
  7476. var a = (arguments.length > 2) ? Y.Array(arguments, 2, true) : null;
  7477. return this._on(fn, context, a, AFTER);
  7478. },
  7479. /**
  7480. * Detach listeners.
  7481. * @method detach
  7482. * @param {Function} fn The subscribed function to remove, if not supplied
  7483. * all will be removed.
  7484. * @param {Object} context The context object passed to subscribe.
  7485. * @return {int} returns the number of subscribers unsubscribed.
  7486. */
  7487. detach: function(fn, context) {
  7488. // unsubscribe handle
  7489. if (fn && fn.detach) {
  7490. return fn.detach();
  7491. }
  7492. var i, s,
  7493. found = 0,
  7494. subs = Y.merge(this.subscribers, this.afters);
  7495. for (i in subs) {
  7496. if (subs.hasOwnProperty(i)) {
  7497. s = subs[i];
  7498. if (s && (!fn || fn === s.fn)) {
  7499. this._delete(s);
  7500. found++;
  7501. }
  7502. }
  7503. }
  7504. return found;
  7505. },
  7506. /**
  7507. * Detach listeners.
  7508. * @method unsubscribe
  7509. * @param {Function} fn The subscribed function to remove, if not supplied
  7510. * all will be removed.
  7511. * @param {Object} context The context object passed to subscribe.
  7512. * @return {int|undefined} returns the number of subscribers unsubscribed.
  7513. * @deprecated use detach.
  7514. */
  7515. unsubscribe: function() {
  7516. return this.detach.apply(this, arguments);
  7517. },
  7518. /**
  7519. * Notify a single subscriber
  7520. * @method _notify
  7521. * @param {Subscriber} s the subscriber.
  7522. * @param {Array} args the arguments array to apply to the listener.
  7523. * @protected
  7524. */
  7525. _notify: function(s, args, ef) {
  7526. this.log(this.type + '->' + 'sub: ' + s.id);
  7527. var ret;
  7528. ret = s.notify(args, this);
  7529. if (false === ret || this.stopped > 1) {
  7530. this.log(this.type + ' cancelled by subscriber');
  7531. return false;
  7532. }
  7533. return true;
  7534. },
  7535. /**
  7536. * Logger abstraction to centralize the application of the silent flag
  7537. * @method log
  7538. * @param {string} msg message to log.
  7539. * @param {string} cat log category.
  7540. */
  7541. log: function(msg, cat) {
  7542. if (!this.silent) {
  7543. Y.log(this.id + ': ' + msg, cat || 'info', 'event');
  7544. }
  7545. },
  7546. /**
  7547. * Notifies the subscribers. The callback functions will be executed
  7548. * from the context specified when the event was created, and with the
  7549. * following parameters:
  7550. * <ul>
  7551. * <li>The type of event</li>
  7552. * <li>All of the arguments fire() was executed with as an array</li>
  7553. * <li>The custom object (if any) that was passed into the subscribe()
  7554. * method</li>
  7555. * </ul>
  7556. * @method fire
  7557. * @param {Object*} arguments an arbitrary set of parameters to pass to
  7558. * the handler.
  7559. * @return {boolean} false if one of the subscribers returned false,
  7560. * true otherwise.
  7561. *
  7562. */
  7563. fire: function() {
  7564. if (this.fireOnce && this.fired) {
  7565. this.log('fireOnce event: ' + this.type + ' already fired');
  7566. return true;
  7567. } else {
  7568. var args = Y.Array(arguments, 0, true);
  7569. // this doesn't happen if the event isn't published
  7570. // this.host._monitor('fire', this.type, args);
  7571. this.fired = true;
  7572. this.firedWith = args;
  7573. if (this.emitFacade) {
  7574. return this.fireComplex(args);
  7575. } else {
  7576. return this.fireSimple(args);
  7577. }
  7578. }
  7579. },
  7580. /**
  7581. * Set up for notifying subscribers of non-emitFacade events.
  7582. *
  7583. * @method fireSimple
  7584. * @param args {Array} Arguments passed to fire()
  7585. * @return Boolean false if a subscriber returned false
  7586. * @protected
  7587. */
  7588. fireSimple: function(args) {
  7589. this.stopped = 0;
  7590. this.prevented = 0;
  7591. if (this.hasSubs()) {
  7592. // this._procSubs(Y.merge(this.subscribers, this.afters), args);
  7593. var subs = this.getSubs();
  7594. this._procSubs(subs[0], args);
  7595. this._procSubs(subs[1], args);
  7596. }
  7597. this._broadcast(args);
  7598. return this.stopped ? false : true;
  7599. },
  7600. // Requires the event-custom-complex module for full funcitonality.
  7601. fireComplex: function(args) {
  7602. Y.log('Missing event-custom-complex needed to emit a facade for: ' + this.type);
  7603. args[0] = args[0] || {};
  7604. return this.fireSimple(args);
  7605. },
  7606. /**
  7607. * Notifies a list of subscribers.
  7608. *
  7609. * @method _procSubs
  7610. * @param subs {Array} List of subscribers
  7611. * @param args {Array} Arguments passed to fire()
  7612. * @param ef {}
  7613. * @return Boolean false if a subscriber returns false or stops the event
  7614. * propagation via e.stopPropagation(),
  7615. * e.stopImmediatePropagation(), or e.halt()
  7616. * @private
  7617. */
  7618. _procSubs: function(subs, args, ef) {
  7619. var s, i;
  7620. for (i in subs) {
  7621. if (subs.hasOwnProperty(i)) {
  7622. s = subs[i];
  7623. if (s && s.fn) {
  7624. if (false === this._notify(s, args, ef)) {
  7625. this.stopped = 2;
  7626. }
  7627. if (this.stopped == 2) {
  7628. return false;
  7629. }
  7630. }
  7631. }
  7632. }
  7633. return true;
  7634. },
  7635. /**
  7636. * Notifies the YUI instance if the event is configured with broadcast = 1,
  7637. * and both the YUI instance and Y.Global if configured with broadcast = 2.
  7638. *
  7639. * @method _broadcast
  7640. * @param args {Array} Arguments sent to fire()
  7641. * @private
  7642. */
  7643. _broadcast: function(args) {
  7644. if (!this.stopped && this.broadcast) {
  7645. var a = Y.Array(args);
  7646. a.unshift(this.type);
  7647. if (this.host !== Y) {
  7648. Y.fire.apply(Y, a);
  7649. }
  7650. if (this.broadcast == 2) {
  7651. Y.Global.fire.apply(Y.Global, a);
  7652. }
  7653. }
  7654. },
  7655. /**
  7656. * Removes all listeners
  7657. * @method unsubscribeAll
  7658. * @return {int} The number of listeners unsubscribed.
  7659. * @deprecated use detachAll.
  7660. */
  7661. unsubscribeAll: function() {
  7662. return this.detachAll.apply(this, arguments);
  7663. },
  7664. /**
  7665. * Removes all listeners
  7666. * @method detachAll
  7667. * @return {int} The number of listeners unsubscribed.
  7668. */
  7669. detachAll: function() {
  7670. return this.detach();
  7671. },
  7672. /**
  7673. * Deletes the subscriber from the internal store of on() and after()
  7674. * subscribers.
  7675. *
  7676. * @method _delete
  7677. * @param subscriber object.
  7678. * @private
  7679. */
  7680. _delete: function(s) {
  7681. if (s) {
  7682. if (this.subscribers[s.id]) {
  7683. delete this.subscribers[s.id];
  7684. this.subCount--;
  7685. }
  7686. if (this.afters[s.id]) {
  7687. delete this.afters[s.id];
  7688. this.afterCount--;
  7689. }
  7690. }
  7691. if (this.host) {
  7692. this.host._monitor('detach', this.type, {
  7693. ce: this,
  7694. sub: s
  7695. });
  7696. }
  7697. if (s) {
  7698. // delete s.fn;
  7699. // delete s.context;
  7700. s.deleted = true;
  7701. }
  7702. }
  7703. };
  7704. /**
  7705. * Stores the subscriber information to be used when the event fires.
  7706. * @param {Function} fn The wrapped function to execute.
  7707. * @param {Object} context The value of the keyword 'this' in the listener.
  7708. * @param {Array} args* 0..n additional arguments to supply the listener.
  7709. *
  7710. * @class Subscriber
  7711. * @constructor
  7712. */
  7713. Y.Subscriber = function(fn, context, args) {
  7714. /**
  7715. * The callback that will be execute when the event fires
  7716. * This is wrapped by Y.rbind if obj was supplied.
  7717. * @property fn
  7718. * @type Function
  7719. */
  7720. this.fn = fn;
  7721. /**
  7722. * Optional 'this' keyword for the listener
  7723. * @property context
  7724. * @type Object
  7725. */
  7726. this.context = context;
  7727. /**
  7728. * Unique subscriber id
  7729. * @property id
  7730. * @type String
  7731. */
  7732. this.id = Y.stamp(this);
  7733. /**
  7734. * Additional arguments to propagate to the subscriber
  7735. * @property args
  7736. * @type Array
  7737. */
  7738. this.args = args;
  7739. /**
  7740. * Custom events for a given fire transaction.
  7741. * @property events
  7742. * @type {EventTarget}
  7743. */
  7744. // this.events = null;
  7745. /**
  7746. * This listener only reacts to the event once
  7747. * @property once
  7748. */
  7749. // this.once = false;
  7750. };
  7751. Y.Subscriber.prototype = {
  7752. constructor: Y.Subscriber,
  7753. _notify: function(c, args, ce) {
  7754. if (this.deleted && !this.postponed) {
  7755. if (this.postponed) {
  7756. delete this.fn;
  7757. delete this.context;
  7758. } else {
  7759. delete this.postponed;
  7760. return null;
  7761. }
  7762. }
  7763. var a = this.args, ret;
  7764. switch (ce.signature) {
  7765. case 0:
  7766. ret = this.fn.call(c, ce.type, args, c);
  7767. break;
  7768. case 1:
  7769. ret = this.fn.call(c, args[0] || null, c);
  7770. break;
  7771. default:
  7772. if (a || args) {
  7773. args = args || [];
  7774. a = (a) ? args.concat(a) : args;
  7775. ret = this.fn.apply(c, a);
  7776. } else {
  7777. ret = this.fn.call(c);
  7778. }
  7779. }
  7780. if (this.once) {
  7781. ce._delete(this);
  7782. }
  7783. return ret;
  7784. },
  7785. /**
  7786. * Executes the subscriber.
  7787. * @method notify
  7788. * @param args {Array} Arguments array for the subscriber.
  7789. * @param ce {CustomEvent} The custom event that sent the notification.
  7790. */
  7791. notify: function(args, ce) {
  7792. var c = this.context,
  7793. ret = true;
  7794. if (!c) {
  7795. c = (ce.contextFn) ? ce.contextFn() : ce.context;
  7796. }
  7797. // only catch errors if we will not re-throw them.
  7798. if (Y.config.throwFail) {
  7799. ret = this._notify(c, args, ce);
  7800. } else {
  7801. try {
  7802. ret = this._notify(c, args, ce);
  7803. } catch (e) {
  7804. Y.error(this + ' failed: ' + e.message, e);
  7805. }
  7806. }
  7807. return ret;
  7808. },
  7809. /**
  7810. * Returns true if the fn and obj match this objects properties.
  7811. * Used by the unsubscribe method to match the right subscriber.
  7812. *
  7813. * @method contains
  7814. * @param {Function} fn the function to execute.
  7815. * @param {Object} context optional 'this' keyword for the listener.
  7816. * @return {boolean} true if the supplied arguments match this
  7817. * subscriber's signature.
  7818. */
  7819. contains: function(fn, context) {
  7820. if (context) {
  7821. return ((this.fn == fn) && this.context == context);
  7822. } else {
  7823. return (this.fn == fn);
  7824. }
  7825. }
  7826. };
  7827. /**
  7828. * Return value from all subscribe operations
  7829. * @class EventHandle
  7830. * @constructor
  7831. * @param {CustomEvent} evt the custom event.
  7832. * @param {Subscriber} sub the subscriber.
  7833. */
  7834. Y.EventHandle = function(evt, sub) {
  7835. /**
  7836. * The custom event
  7837. * @type CustomEvent
  7838. */
  7839. this.evt = evt;
  7840. /**
  7841. * The subscriber object
  7842. * @type Subscriber
  7843. */
  7844. this.sub = sub;
  7845. };
  7846. Y.EventHandle.prototype = {
  7847. batch: function(f, c) {
  7848. f.call(c || this, this);
  7849. if (Y.Lang.isArray(this.evt)) {
  7850. Y.Array.each(this.evt, function(h) {
  7851. h.batch.call(c || h, f);
  7852. });
  7853. }
  7854. },
  7855. /**
  7856. * Detaches this subscriber
  7857. * @method detach
  7858. * @return {int} the number of detached listeners
  7859. */
  7860. detach: function() {
  7861. var evt = this.evt, detached = 0, i;
  7862. if (evt) {
  7863. // Y.log('EventHandle.detach: ' + this.sub, 'info', 'Event');
  7864. if (Y.Lang.isArray(evt)) {
  7865. for (i = 0; i < evt.length; i++) {
  7866. detached += evt[i].detach();
  7867. }
  7868. } else {
  7869. evt._delete(this.sub);
  7870. detached = 1;
  7871. }
  7872. }
  7873. return detached;
  7874. },
  7875. /**
  7876. * Monitor the event state for the subscribed event. The first parameter
  7877. * is what should be monitored, the rest are the normal parameters when
  7878. * subscribing to an event.
  7879. * @method monitor
  7880. * @param what {string} what to monitor ('attach', 'detach', 'publish').
  7881. * @return {EventHandle} return value from the monitor event subscription.
  7882. */
  7883. monitor: function(what) {
  7884. return this.evt.monitor.apply(this.evt, arguments);
  7885. }
  7886. };
  7887. /**
  7888. * Custom event engine, DOM event listener abstraction layer, synthetic DOM
  7889. * events.
  7890. * @module event-custom
  7891. * @submodule event-custom-base
  7892. */
  7893. /**
  7894. * EventTarget provides the implementation for any object to
  7895. * publish, subscribe and fire to custom events, and also
  7896. * alows other EventTargets to target the object with events
  7897. * sourced from the other object.
  7898. * EventTarget is designed to be used with Y.augment to wrap
  7899. * EventCustom in an interface that allows events to be listened to
  7900. * and fired by name. This makes it possible for implementing code to
  7901. * subscribe to an event that either has not been created yet, or will
  7902. * not be created at all.
  7903. * @class EventTarget
  7904. * @param opts a configuration object
  7905. * @config emitFacade {boolean} if true, all events will emit event
  7906. * facade payloads by default (default false)
  7907. * @config prefix {string} the prefix to apply to non-prefixed event names
  7908. * @config chain {boolean} if true, on/after/detach return the host to allow
  7909. * chaining, otherwise they return an EventHandle (default false)
  7910. */
  7911. var L = Y.Lang,
  7912. PREFIX_DELIMITER = ':',
  7913. CATEGORY_DELIMITER = '|',
  7914. AFTER_PREFIX = '~AFTER~',
  7915. YArray = Y.Array,
  7916. _wildType = Y.cached(function(type) {
  7917. return type.replace(/(.*)(:)(.*)/, "*$2$3");
  7918. }),
  7919. /**
  7920. * If the instance has a prefix attribute and the
  7921. * event type is not prefixed, the instance prefix is
  7922. * applied to the supplied type.
  7923. * @method _getType
  7924. * @private
  7925. */
  7926. _getType = Y.cached(function(type, pre) {
  7927. if (!pre || !L.isString(type) || type.indexOf(PREFIX_DELIMITER) > -1) {
  7928. return type;
  7929. }
  7930. return pre + PREFIX_DELIMITER + type;
  7931. }),
  7932. /**
  7933. * Returns an array with the detach key (if provided),
  7934. * and the prefixed event name from _getType
  7935. * Y.on('detachcategory| menu:click', fn)
  7936. * @method _parseType
  7937. * @private
  7938. */
  7939. _parseType = Y.cached(function(type, pre) {
  7940. var t = type, detachcategory, after, i;
  7941. if (!L.isString(t)) {
  7942. return t;
  7943. }
  7944. i = t.indexOf(AFTER_PREFIX);
  7945. if (i > -1) {
  7946. after = true;
  7947. t = t.substr(AFTER_PREFIX.length);
  7948. // Y.log(t);
  7949. }
  7950. i = t.indexOf(CATEGORY_DELIMITER);
  7951. if (i > -1) {
  7952. detachcategory = t.substr(0, (i));
  7953. t = t.substr(i+1);
  7954. if (t == '*') {
  7955. t = null;
  7956. }
  7957. }
  7958. // detach category, full type with instance prefix, is this an after listener, short type
  7959. return [detachcategory, (pre) ? _getType(t, pre) : t, after, t];
  7960. }),
  7961. ET = function(opts) {
  7962. // Y.log('EventTarget constructor executed: ' + this._yuid);
  7963. var o = (L.isObject(opts)) ? opts : {};
  7964. this._yuievt = this._yuievt || {
  7965. id: Y.guid(),
  7966. events: {},
  7967. targets: {},
  7968. config: o,
  7969. chain: ('chain' in o) ? o.chain : Y.config.chain,
  7970. bubbling: false,
  7971. defaults: {
  7972. context: o.context || this,
  7973. host: this,
  7974. emitFacade: o.emitFacade,
  7975. fireOnce: o.fireOnce,
  7976. queuable: o.queuable,
  7977. monitored: o.monitored,
  7978. broadcast: o.broadcast,
  7979. defaultTargetOnly: o.defaultTargetOnly,
  7980. bubbles: ('bubbles' in o) ? o.bubbles : true
  7981. }
  7982. };
  7983. };
  7984. ET.prototype = {
  7985. constructor: ET,
  7986. /**
  7987. * Listen to a custom event hosted by this object one time.
  7988. * This is the equivalent to <code>on</code> except the
  7989. * listener is immediatelly detached when it is executed.
  7990. * @method once
  7991. * @param type {string} The type of the event
  7992. * @param fn {Function} The callback
  7993. * @param context {object} optional execution context.
  7994. * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
  7995. * @return the event target or a detach handle per 'chain' config
  7996. */
  7997. once: function() {
  7998. var handle = this.on.apply(this, arguments);
  7999. handle.batch(function(hand) {
  8000. if (hand.sub) {
  8001. hand.sub.once = true;
  8002. }
  8003. });
  8004. return handle;
  8005. },
  8006. /**
  8007. * Listen to a custom event hosted by this object one time.
  8008. * This is the equivalent to <code>after</code> except the
  8009. * listener is immediatelly detached when it is executed.
  8010. * @method onceAfter
  8011. * @param type {string} The type of the event
  8012. * @param fn {Function} The callback
  8013. * @param context {object} optional execution context.
  8014. * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
  8015. * @return the event target or a detach handle per 'chain' config
  8016. */
  8017. onceAfter: function() {
  8018. var args = YArray(arguments, 0, true);
  8019. args[0] = AFTER_PREFIX + args[0];
  8020. return this.once.apply(this, args);
  8021. },
  8022. /**
  8023. * Takes the type parameter passed to 'on' and parses out the
  8024. * various pieces that could be included in the type. If the
  8025. * event type is passed without a prefix, it will be expanded
  8026. * to include the prefix one is supplied or the event target
  8027. * is configured with a default prefix.
  8028. * @method parseType
  8029. * @param {string} type the type
  8030. * @param {string} [pre=this._yuievt.config.prefix] the prefix
  8031. * @since 3.3.0
  8032. * @return {Array} an array containing:
  8033. * * the detach category, if supplied,
  8034. * * the prefixed event type,
  8035. * * whether or not this is an after listener,
  8036. * * the supplied event type
  8037. */
  8038. parseType: function(type, pre) {
  8039. return _parseType(type, pre || this._yuievt.config.prefix);
  8040. },
  8041. /**
  8042. * Subscribe to a custom event hosted by this object
  8043. * @method on
  8044. * @param type {string} The type of the event
  8045. * @param fn {Function} The callback
  8046. * @param context {object} optional execution context.
  8047. * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
  8048. * @return the event target or a detach handle per 'chain' config
  8049. */
  8050. on: function(type, fn, context) {
  8051. var parts = _parseType(type, this._yuievt.config.prefix), f, c, args, ret, ce,
  8052. detachcategory, handle, store = Y.Env.evt.handles, after, adapt, shorttype,
  8053. Node = Y.Node, n, domevent, isArr;
  8054. // full name, args, detachcategory, after
  8055. this._monitor('attach', parts[1], {
  8056. args: arguments,
  8057. category: parts[0],
  8058. after: parts[2]
  8059. });
  8060. if (L.isObject(type)) {
  8061. if (L.isFunction(type)) {
  8062. return Y.Do.before.apply(Y.Do, arguments);
  8063. }
  8064. f = fn;
  8065. c = context;
  8066. args = YArray(arguments, 0, true);
  8067. ret = [];
  8068. if (L.isArray(type)) {
  8069. isArr = true;
  8070. }
  8071. after = type._after;
  8072. delete type._after;
  8073. Y.each(type, function(v, k) {
  8074. if (L.isObject(v)) {
  8075. f = v.fn || ((L.isFunction(v)) ? v : f);
  8076. c = v.context || c;
  8077. }
  8078. var nv = (after) ? AFTER_PREFIX : '';
  8079. args[0] = nv + ((isArr) ? v : k);
  8080. args[1] = f;
  8081. args[2] = c;
  8082. ret.push(this.on.apply(this, args));
  8083. }, this);
  8084. return (this._yuievt.chain) ? this : new Y.EventHandle(ret);
  8085. }
  8086. detachcategory = parts[0];
  8087. after = parts[2];
  8088. shorttype = parts[3];
  8089. // extra redirection so we catch adaptor events too. take a look at this.
  8090. if (Node && Y.instanceOf(this, Node) && (shorttype in Node.DOM_EVENTS)) {
  8091. args = YArray(arguments, 0, true);
  8092. args.splice(2, 0, Node.getDOMNode(this));
  8093. // Y.log("Node detected, redirecting with these args: " + args);
  8094. return Y.on.apply(Y, args);
  8095. }
  8096. type = parts[1];
  8097. if (Y.instanceOf(this, YUI)) {
  8098. adapt = Y.Env.evt.plugins[type];
  8099. args = YArray(arguments, 0, true);
  8100. args[0] = shorttype;
  8101. if (Node) {
  8102. n = args[2];
  8103. if (Y.instanceOf(n, Y.NodeList)) {
  8104. n = Y.NodeList.getDOMNodes(n);
  8105. } else if (Y.instanceOf(n, Node)) {
  8106. n = Node.getDOMNode(n);
  8107. }
  8108. domevent = (shorttype in Node.DOM_EVENTS);
  8109. // Captures both DOM events and event plugins.
  8110. if (domevent) {
  8111. args[2] = n;
  8112. }
  8113. }
  8114. // check for the existance of an event adaptor
  8115. if (adapt) {
  8116. Y.log('Using adaptor for ' + shorttype + ', ' + n, 'info', 'event');
  8117. handle = adapt.on.apply(Y, args);
  8118. } else if ((!type) || domevent) {
  8119. handle = Y.Event._attach(args);
  8120. }
  8121. }
  8122. if (!handle) {
  8123. ce = this._yuievt.events[type] || this.publish(type);
  8124. handle = ce._on(fn, context, (arguments.length > 3) ? YArray(arguments, 3, true) : null, (after) ? 'after' : true);
  8125. }
  8126. if (detachcategory) {
  8127. store[detachcategory] = store[detachcategory] || {};
  8128. store[detachcategory][type] = store[detachcategory][type] || [];
  8129. store[detachcategory][type].push(handle);
  8130. }
  8131. return (this._yuievt.chain) ? this : handle;
  8132. },
  8133. /**
  8134. * subscribe to an event
  8135. * @method subscribe
  8136. * @deprecated use on
  8137. */
  8138. subscribe: function() {
  8139. Y.log('EventTarget subscribe() is deprecated, use on()', 'warn', 'deprecated');
  8140. return this.on.apply(this, arguments);
  8141. },
  8142. /**
  8143. * Detach one or more listeners the from the specified event
  8144. * @method detach
  8145. * @param type {string|Object} Either the handle to the subscriber or the
  8146. * type of event. If the type
  8147. * is not specified, it will attempt to remove
  8148. * the listener from all hosted events.
  8149. * @param fn {Function} The subscribed function to unsubscribe, if not
  8150. * supplied, all subscribers will be removed.
  8151. * @param context {Object} The custom object passed to subscribe. This is
  8152. * optional, but if supplied will be used to
  8153. * disambiguate multiple listeners that are the same
  8154. * (e.g., you subscribe many object using a function
  8155. * that lives on the prototype)
  8156. * @return {EventTarget} the host
  8157. */
  8158. detach: function(type, fn, context) {
  8159. var evts = this._yuievt.events, i,
  8160. Node = Y.Node, isNode = Node && (Y.instanceOf(this, Node));
  8161. // detachAll disabled on the Y instance.
  8162. if (!type && (this !== Y)) {
  8163. for (i in evts) {
  8164. if (evts.hasOwnProperty(i)) {
  8165. evts[i].detach(fn, context);
  8166. }
  8167. }
  8168. if (isNode) {
  8169. Y.Event.purgeElement(Node.getDOMNode(this));
  8170. }
  8171. return this;
  8172. }
  8173. var parts = _parseType(type, this._yuievt.config.prefix),
  8174. detachcategory = L.isArray(parts) ? parts[0] : null,
  8175. shorttype = (parts) ? parts[3] : null,
  8176. adapt, store = Y.Env.evt.handles, detachhost, cat, args,
  8177. ce,
  8178. keyDetacher = function(lcat, ltype, host) {
  8179. var handles = lcat[ltype], ce, i;
  8180. if (handles) {
  8181. for (i = handles.length - 1; i >= 0; --i) {
  8182. ce = handles[i].evt;
  8183. if (ce.host === host || ce.el === host) {
  8184. handles[i].detach();
  8185. }
  8186. }
  8187. }
  8188. };
  8189. if (detachcategory) {
  8190. cat = store[detachcategory];
  8191. type = parts[1];
  8192. detachhost = (isNode) ? Y.Node.getDOMNode(this) : this;
  8193. if (cat) {
  8194. if (type) {
  8195. keyDetacher(cat, type, detachhost);
  8196. } else {
  8197. for (i in cat) {
  8198. if (cat.hasOwnProperty(i)) {
  8199. keyDetacher(cat, i, detachhost);
  8200. }
  8201. }
  8202. }
  8203. return this;
  8204. }
  8205. // If this is an event handle, use it to detach
  8206. } else if (L.isObject(type) && type.detach) {
  8207. type.detach();
  8208. return this;
  8209. // extra redirection so we catch adaptor events too. take a look at this.
  8210. } else if (isNode && ((!shorttype) || (shorttype in Node.DOM_EVENTS))) {
  8211. args = YArray(arguments, 0, true);
  8212. args[2] = Node.getDOMNode(this);
  8213. Y.detach.apply(Y, args);
  8214. return this;
  8215. }
  8216. adapt = Y.Env.evt.plugins[shorttype];
  8217. // The YUI instance handles DOM events and adaptors
  8218. if (Y.instanceOf(this, YUI)) {
  8219. args = YArray(arguments, 0, true);
  8220. // use the adaptor specific detach code if
  8221. if (adapt && adapt.detach) {
  8222. adapt.detach.apply(Y, args);
  8223. return this;
  8224. // DOM event fork
  8225. } else if (!type || (!adapt && Node && (type in Node.DOM_EVENTS))) {
  8226. args[0] = type;
  8227. Y.Event.detach.apply(Y.Event, args);
  8228. return this;
  8229. }
  8230. }
  8231. // ce = evts[type];
  8232. ce = evts[parts[1]];
  8233. if (ce) {
  8234. ce.detach(fn, context);
  8235. }
  8236. return this;
  8237. },
  8238. /**
  8239. * detach a listener
  8240. * @method unsubscribe
  8241. * @deprecated use detach
  8242. */
  8243. unsubscribe: function() {
  8244. Y.log('EventTarget unsubscribe() is deprecated, use detach()', 'warn', 'deprecated');
  8245. return this.detach.apply(this, arguments);
  8246. },
  8247. /**
  8248. * Removes all listeners from the specified event. If the event type
  8249. * is not specified, all listeners from all hosted custom events will
  8250. * be removed.
  8251. * @method detachAll
  8252. * @param type {string} The type, or name of the event
  8253. */
  8254. detachAll: function(type) {
  8255. return this.detach(type);
  8256. },
  8257. /**
  8258. * Removes all listeners from the specified event. If the event type
  8259. * is not specified, all listeners from all hosted custom events will
  8260. * be removed.
  8261. * @method unsubscribeAll
  8262. * @param type {string} The type, or name of the event
  8263. * @deprecated use detachAll
  8264. */
  8265. unsubscribeAll: function() {
  8266. Y.log('EventTarget unsubscribeAll() is deprecated, use detachAll()', 'warn', 'deprecated');
  8267. return this.detachAll.apply(this, arguments);
  8268. },
  8269. /**
  8270. * Creates a new custom event of the specified type. If a custom event
  8271. * by that name already exists, it will not be re-created. In either
  8272. * case the custom event is returned.
  8273. *
  8274. * @method publish
  8275. *
  8276. * @param type {string} the type, or name of the event
  8277. * @param opts {object} optional config params. Valid properties are:
  8278. *
  8279. * <ul>
  8280. * <li>
  8281. * 'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
  8282. * </li>
  8283. * <li>
  8284. * 'bubbles': whether or not this event bubbles (true)
  8285. * Events can only bubble if emitFacade is true.
  8286. * </li>
  8287. * <li>
  8288. * 'context': the default execution context for the listeners (this)
  8289. * </li>
  8290. * <li>
  8291. * 'defaultFn': the default function to execute when this event fires if preventDefault was not called
  8292. * </li>
  8293. * <li>
  8294. * 'emitFacade': whether or not this event emits a facade (false)
  8295. * </li>
  8296. * <li>
  8297. * 'prefix': the prefix for this targets events, e.g., 'menu' in 'menu:click'
  8298. * </li>
  8299. * <li>
  8300. * 'fireOnce': if an event is configured to fire once, new subscribers after
  8301. * the fire will be notified immediately.
  8302. * </li>
  8303. * <li>
  8304. * 'async': fireOnce event listeners will fire synchronously if the event has already
  8305. * fired unless async is true.
  8306. * </li>
  8307. * <li>
  8308. * 'preventable': whether or not preventDefault() has an effect (true)
  8309. * </li>
  8310. * <li>
  8311. * 'preventedFn': a function that is executed when preventDefault is called
  8312. * </li>
  8313. * <li>
  8314. * 'queuable': whether or not this event can be queued during bubbling (false)
  8315. * </li>
  8316. * <li>
  8317. * 'silent': if silent is true, debug messages are not provided for this event.
  8318. * </li>
  8319. * <li>
  8320. * 'stoppedFn': a function that is executed when stopPropagation is called
  8321. * </li>
  8322. *
  8323. * <li>
  8324. * 'monitored': specifies whether or not this event should send notifications about
  8325. * when the event has been attached, detached, or published.
  8326. * </li>
  8327. * <li>
  8328. * 'type': the event type (valid option if not provided as the first parameter to publish)
  8329. * </li>
  8330. * </ul>
  8331. *
  8332. * @return {CustomEvent} the custom event
  8333. *
  8334. */
  8335. publish: function(type, opts) {
  8336. var events, ce, ret, defaults,
  8337. edata = this._yuievt,
  8338. pre = edata.config.prefix;
  8339. type = (pre) ? _getType(type, pre) : type;
  8340. this._monitor('publish', type, {
  8341. args: arguments
  8342. });
  8343. if (L.isObject(type)) {
  8344. ret = {};
  8345. Y.each(type, function(v, k) {
  8346. ret[k] = this.publish(k, v || opts);
  8347. }, this);
  8348. return ret;
  8349. }
  8350. events = edata.events;
  8351. ce = events[type];
  8352. if (ce) {
  8353. // ce.log("publish applying new config to published event: '"+type+"' exists", 'info', 'event');
  8354. if (opts) {
  8355. ce.applyConfig(opts, true);
  8356. }
  8357. } else {
  8358. defaults = edata.defaults;
  8359. // apply defaults
  8360. ce = new Y.CustomEvent(type,
  8361. (opts) ? Y.merge(defaults, opts) : defaults);
  8362. events[type] = ce;
  8363. }
  8364. // make sure we turn the broadcast flag off if this
  8365. // event was published as a result of bubbling
  8366. // if (opts instanceof Y.CustomEvent) {
  8367. // events[type].broadcast = false;
  8368. // }
  8369. return events[type];
  8370. },
  8371. /**
  8372. * This is the entry point for the event monitoring system.
  8373. * You can monitor 'attach', 'detach', 'fire', and 'publish'.
  8374. * When configured, these events generate an event. click ->
  8375. * click_attach, click_detach, click_publish -- these can
  8376. * be subscribed to like other events to monitor the event
  8377. * system. Inividual published events can have monitoring
  8378. * turned on or off (publish can't be turned off before it
  8379. * it published) by setting the events 'monitor' config.
  8380. *
  8381. * @method _monitor
  8382. * @param what {String} 'attach', 'detach', 'fire', or 'publish'
  8383. * @param type {String} Name of the event being monitored
  8384. * @param o {Object} Information about the event interaction, such as
  8385. * fire() args, subscription category, publish config
  8386. * @private
  8387. */
  8388. _monitor: function(what, type, o) {
  8389. var monitorevt, ce = this.getEvent(type);
  8390. if ((this._yuievt.config.monitored && (!ce || ce.monitored)) || (ce && ce.monitored)) {
  8391. monitorevt = type + '_' + what;
  8392. // Y.log('monitoring: ' + monitorevt);
  8393. o.monitored = what;
  8394. this.fire.call(this, monitorevt, o);
  8395. }
  8396. },
  8397. /**
  8398. * Fire a custom event by name. The callback functions will be executed
  8399. * from the context specified when the event was created, and with the
  8400. * following parameters.
  8401. *
  8402. * If the custom event object hasn't been created, then the event hasn't
  8403. * been published and it has no subscribers. For performance sake, we
  8404. * immediate exit in this case. This means the event won't bubble, so
  8405. * if the intention is that a bubble target be notified, the event must
  8406. * be published on this object first.
  8407. *
  8408. * The first argument is the event type, and any additional arguments are
  8409. * passed to the listeners as parameters. If the first of these is an
  8410. * object literal, and the event is configured to emit an event facade,
  8411. * that object is mixed into the event facade and the facade is provided
  8412. * in place of the original object.
  8413. *
  8414. * @method fire
  8415. * @param type {String|Object} The type of the event, or an object that contains
  8416. * a 'type' property.
  8417. * @param arguments {Object*} an arbitrary set of parameters to pass to
  8418. * the handler. If the first of these is an object literal and the event is
  8419. * configured to emit an event facade, the event facade will replace that
  8420. * parameter after the properties the object literal contains are copied to
  8421. * the event facade.
  8422. * @return {EventTarget} the event host
  8423. *
  8424. */
  8425. fire: function(type) {
  8426. var typeIncluded = L.isString(type),
  8427. t = (typeIncluded) ? type : (type && type.type),
  8428. ce, ret, pre = this._yuievt.config.prefix, ce2,
  8429. args = (typeIncluded) ? YArray(arguments, 1, true) : arguments;
  8430. t = (pre) ? _getType(t, pre) : t;
  8431. this._monitor('fire', t, {
  8432. args: args
  8433. });
  8434. ce = this.getEvent(t, true);
  8435. ce2 = this.getSibling(t, ce);
  8436. if (ce2 && !ce) {
  8437. ce = this.publish(t);
  8438. }
  8439. // this event has not been published or subscribed to
  8440. if (!ce) {
  8441. if (this._yuievt.hasTargets) {
  8442. return this.bubble({ type: t }, args, this);
  8443. }
  8444. // otherwise there is nothing to be done
  8445. ret = true;
  8446. } else {
  8447. ce.sibling = ce2;
  8448. ret = ce.fire.apply(ce, args);
  8449. }
  8450. return (this._yuievt.chain) ? this : ret;
  8451. },
  8452. getSibling: function(type, ce) {
  8453. var ce2;
  8454. // delegate to *:type events if there are subscribers
  8455. if (type.indexOf(PREFIX_DELIMITER) > -1) {
  8456. type = _wildType(type);
  8457. // console.log(type);
  8458. ce2 = this.getEvent(type, true);
  8459. if (ce2) {
  8460. // console.log("GOT ONE: " + type);
  8461. ce2.applyConfig(ce);
  8462. ce2.bubbles = false;
  8463. ce2.broadcast = 0;
  8464. // ret = ce2.fire.apply(ce2, a);
  8465. }
  8466. }
  8467. return ce2;
  8468. },
  8469. /**
  8470. * Returns the custom event of the provided type has been created, a
  8471. * falsy value otherwise
  8472. * @method getEvent
  8473. * @param type {string} the type, or name of the event
  8474. * @param prefixed {string} if true, the type is prefixed already
  8475. * @return {CustomEvent} the custom event or null
  8476. */
  8477. getEvent: function(type, prefixed) {
  8478. var pre, e;
  8479. if (!prefixed) {
  8480. pre = this._yuievt.config.prefix;
  8481. type = (pre) ? _getType(type, pre) : type;
  8482. }
  8483. e = this._yuievt.events;
  8484. return e[type] || null;
  8485. },
  8486. /**
  8487. * Subscribe to a custom event hosted by this object. The
  8488. * supplied callback will execute after any listeners add
  8489. * via the subscribe method, and after the default function,
  8490. * if configured for the event, has executed.
  8491. * @method after
  8492. * @param type {string} The type of the event
  8493. * @param fn {Function} The callback
  8494. * @param context {object} optional execution context.
  8495. * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
  8496. * @return the event target or a detach handle per 'chain' config
  8497. */
  8498. after: function(type, fn) {
  8499. var a = YArray(arguments, 0, true);
  8500. switch (L.type(type)) {
  8501. case 'function':
  8502. return Y.Do.after.apply(Y.Do, arguments);
  8503. case 'array':
  8504. // YArray.each(a[0], function(v) {
  8505. // v = AFTER_PREFIX + v;
  8506. // });
  8507. // break;
  8508. case 'object':
  8509. a[0]._after = true;
  8510. break;
  8511. default:
  8512. a[0] = AFTER_PREFIX + type;
  8513. }
  8514. return this.on.apply(this, a);
  8515. },
  8516. /**
  8517. * Executes the callback before a DOM event, custom event
  8518. * or method. If the first argument is a function, it
  8519. * is assumed the target is a method. For DOM and custom
  8520. * events, this is an alias for Y.on.
  8521. *
  8522. * For DOM and custom events:
  8523. * type, callback, context, 0-n arguments
  8524. *
  8525. * For methods:
  8526. * callback, object (method host), methodName, context, 0-n arguments
  8527. *
  8528. * @method before
  8529. * @return detach handle
  8530. */
  8531. before: function() {
  8532. return this.on.apply(this, arguments);
  8533. }
  8534. };
  8535. Y.EventTarget = ET;
  8536. // make Y an event target
  8537. Y.mix(Y, ET.prototype);
  8538. ET.call(Y, { bubbles: false });
  8539. YUI.Env.globalEvents = YUI.Env.globalEvents || new ET();
  8540. /**
  8541. * Hosts YUI page level events. This is where events bubble to
  8542. * when the broadcast config is set to 2. This property is
  8543. * only available if the custom event module is loaded.
  8544. * @property Global
  8545. * @type EventTarget
  8546. * @for YUI
  8547. */
  8548. Y.Global = YUI.Env.globalEvents;
  8549. // @TODO implement a global namespace function on Y.Global?
  8550. /**
  8551. * <code>YUI</code>'s <code>on</code> method is a unified interface for subscribing to
  8552. * most events exposed by YUI. This includes custom events, DOM events, and
  8553. * function events. <code>detach</code> is also provided to remove listeners
  8554. * serviced by this function.
  8555. *
  8556. * The signature that <code>on</code> accepts varies depending on the type
  8557. * of event being consumed. Refer to the specific methods that will
  8558. * service a specific request for additional information about subscribing
  8559. * to that type of event.
  8560. *
  8561. * <ul>
  8562. * <li>Custom events. These events are defined by various
  8563. * modules in the library. This type of event is delegated to
  8564. * <code>EventTarget</code>'s <code>on</code> method.
  8565. * <ul>
  8566. * <li>The type of the event</li>
  8567. * <li>The callback to execute</li>
  8568. * <li>An optional context object</li>
  8569. * <li>0..n additional arguments to supply the callback.</li>
  8570. * </ul>
  8571. * Example:
  8572. * <code>Y.on('drag:drophit', function() { // start work });</code>
  8573. * </li>
  8574. * <li>DOM events. These are moments reported by the browser related
  8575. * to browser functionality and user interaction.
  8576. * This type of event is delegated to <code>Event</code>'s
  8577. * <code>attach</code> method.
  8578. * <ul>
  8579. * <li>The type of the event</li>
  8580. * <li>The callback to execute</li>
  8581. * <li>The specification for the Node(s) to attach the listener
  8582. * to. This can be a selector, collections, or Node/Element
  8583. * refereces.</li>
  8584. * <li>An optional context object</li>
  8585. * <li>0..n additional arguments to supply the callback.</li>
  8586. * </ul>
  8587. * Example:
  8588. * <code>Y.on('click', function(e) { // something was clicked }, '#someelement');</code>
  8589. * </li>
  8590. * <li>Function events. These events can be used to react before or after a
  8591. * function is executed. This type of event is delegated to <code>Event.Do</code>'s
  8592. * <code>before</code> method.
  8593. * <ul>
  8594. * <li>The callback to execute</li>
  8595. * <li>The object that has the function that will be listened for.</li>
  8596. * <li>The name of the function to listen for.</li>
  8597. * <li>An optional context object</li>
  8598. * <li>0..n additional arguments to supply the callback.</li>
  8599. * </ul>
  8600. * Example <code>Y.on(function(arg1, arg2, etc) { // obj.methodname was executed }, obj 'methodname');</code>
  8601. * </li>
  8602. * </ul>
  8603. *
  8604. * <code>on</code> corresponds to the moment before any default behavior of
  8605. * the event. <code>after</code> works the same way, but these listeners
  8606. * execute after the event's default behavior. <code>before</code> is an
  8607. * alias for <code>on</code>.
  8608. *
  8609. * @method on
  8610. * @param type event type (this parameter does not apply for function events)
  8611. * @param fn the callback
  8612. * @param context optionally change the value of 'this' in the callback
  8613. * @param args* 0..n additional arguments to pass to the callback.
  8614. * @return the event target or a detach handle per 'chain' config
  8615. * @for YUI
  8616. */
  8617. /**
  8618. * Listen for an event one time. Equivalent to <code>on</code>, except that
  8619. * the listener is immediately detached when executed.
  8620. * @see on
  8621. * @method once
  8622. * @param type event type (this parameter does not apply for function events)
  8623. * @param fn the callback
  8624. * @param context optionally change the value of 'this' in the callback
  8625. * @param args* 0..n additional arguments to pass to the callback.
  8626. * @return the event target or a detach handle per 'chain' config
  8627. * @for YUI
  8628. */
  8629. /**
  8630. * after() is a unified interface for subscribing to
  8631. * most events exposed by YUI. This includes custom events,
  8632. * DOM events, and AOP events. This works the same way as
  8633. * the on() function, only it operates after any default
  8634. * behavior for the event has executed. @see <code>on</code> for more
  8635. * information.
  8636. * @method after
  8637. * @param type event type (this parameter does not apply for function events)
  8638. * @param fn the callback
  8639. * @param context optionally change the value of 'this' in the callback
  8640. * @param args* 0..n additional arguments to pass to the callback.
  8641. * @return the event target or a detach handle per 'chain' config
  8642. * @for YUI
  8643. */
  8644. }, '3.4.0' ,{requires:['oop']});
  8645. YUI.add('event-custom-complex', function(Y) {
  8646. /**
  8647. * Adds event facades, preventable default behavior, and bubbling.
  8648. * events.
  8649. * @module event-custom
  8650. * @submodule event-custom-complex
  8651. */
  8652. var FACADE,
  8653. FACADE_KEYS,
  8654. EMPTY = {},
  8655. CEProto = Y.CustomEvent.prototype,
  8656. ETProto = Y.EventTarget.prototype;
  8657. /**
  8658. * Wraps and protects a custom event for use when emitFacade is set to true.
  8659. * Requires the event-custom-complex module
  8660. * @class EventFacade
  8661. * @param e {Event} the custom event
  8662. * @param currentTarget {HTMLElement} the element the listener was attached to
  8663. */
  8664. Y.EventFacade = function(e, currentTarget) {
  8665. e = e || EMPTY;
  8666. this._event = e;
  8667. /**
  8668. * The arguments passed to fire
  8669. * @property details
  8670. * @type Array
  8671. */
  8672. this.details = e.details;
  8673. /**
  8674. * The event type, this can be overridden by the fire() payload
  8675. * @property type
  8676. * @type string
  8677. */
  8678. this.type = e.type;
  8679. /**
  8680. * The real event type
  8681. * @property type
  8682. * @type string
  8683. */
  8684. this._type = e.type;
  8685. //////////////////////////////////////////////////////
  8686. /**
  8687. * Node reference for the targeted eventtarget
  8688. * @property target
  8689. * @type Node
  8690. */
  8691. this.target = e.target;
  8692. /**
  8693. * Node reference for the element that the listener was attached to.
  8694. * @property currentTarget
  8695. * @type Node
  8696. */
  8697. this.currentTarget = currentTarget;
  8698. /**
  8699. * Node reference to the relatedTarget
  8700. * @property relatedTarget
  8701. * @type Node
  8702. */
  8703. this.relatedTarget = e.relatedTarget;
  8704. };
  8705. Y.extend(Y.EventFacade, Object, {
  8706. /**
  8707. * Stops the propagation to the next bubble target
  8708. * @method stopPropagation
  8709. */
  8710. stopPropagation: function() {
  8711. this._event.stopPropagation();
  8712. this.stopped = 1;
  8713. },
  8714. /**
  8715. * Stops the propagation to the next bubble target and
  8716. * prevents any additional listeners from being exectued
  8717. * on the current target.
  8718. * @method stopImmediatePropagation
  8719. */
  8720. stopImmediatePropagation: function() {
  8721. this._event.stopImmediatePropagation();
  8722. this.stopped = 2;
  8723. },
  8724. /**
  8725. * Prevents the event's default behavior
  8726. * @method preventDefault
  8727. */
  8728. preventDefault: function() {
  8729. this._event.preventDefault();
  8730. this.prevented = 1;
  8731. },
  8732. /**
  8733. * Stops the event propagation and prevents the default
  8734. * event behavior.
  8735. * @method halt
  8736. * @param immediate {boolean} if true additional listeners
  8737. * on the current target will not be executed
  8738. */
  8739. halt: function(immediate) {
  8740. this._event.halt(immediate);
  8741. this.prevented = 1;
  8742. this.stopped = (immediate) ? 2 : 1;
  8743. }
  8744. });
  8745. CEProto.fireComplex = function(args) {
  8746. var es, ef, q, queue, ce, ret, events, subs, postponed,
  8747. self = this, host = self.host || self, next, oldbubble;
  8748. if (self.stack) {
  8749. // queue this event if the current item in the queue bubbles
  8750. if (self.queuable && self.type != self.stack.next.type) {
  8751. self.log('queue ' + self.type);
  8752. self.stack.queue.push([self, args]);
  8753. return true;
  8754. }
  8755. }
  8756. es = self.stack || {
  8757. // id of the first event in the stack
  8758. id: self.id,
  8759. next: self,
  8760. silent: self.silent,
  8761. stopped: 0,
  8762. prevented: 0,
  8763. bubbling: null,
  8764. type: self.type,
  8765. // defaultFnQueue: new Y.Queue(),
  8766. afterQueue: new Y.Queue(),
  8767. defaultTargetOnly: self.defaultTargetOnly,
  8768. queue: []
  8769. };
  8770. subs = self.getSubs();
  8771. self.stopped = (self.type !== es.type) ? 0 : es.stopped;
  8772. self.prevented = (self.type !== es.type) ? 0 : es.prevented;
  8773. self.target = self.target || host;
  8774. events = new Y.EventTarget({
  8775. fireOnce: true,
  8776. context: host
  8777. });
  8778. self.events = events;
  8779. if (self.stoppedFn) {
  8780. events.on('stopped', self.stoppedFn);
  8781. }
  8782. self.currentTarget = host;
  8783. self.details = args.slice(); // original arguments in the details
  8784. // self.log("Firing " + self + ", " + "args: " + args);
  8785. self.log("Firing " + self.type);
  8786. self._facade = null; // kill facade to eliminate stale properties
  8787. ef = self._getFacade(args);
  8788. if (Y.Lang.isObject(args[0])) {
  8789. args[0] = ef;
  8790. } else {
  8791. args.unshift(ef);
  8792. }
  8793. // if (subCount) {
  8794. if (subs[0]) {
  8795. // self._procSubs(Y.merge(self.subscribers), args, ef);
  8796. self._procSubs(subs[0], args, ef);
  8797. }
  8798. // bubble if this is hosted in an event target and propagation has not been stopped
  8799. if (self.bubbles && host.bubble && !self.stopped) {
  8800. oldbubble = es.bubbling;
  8801. // self.bubbling = true;
  8802. es.bubbling = self.type;
  8803. // if (host !== ef.target || es.type != self.type) {
  8804. if (es.type != self.type) {
  8805. es.stopped = 0;
  8806. es.prevented = 0;
  8807. }
  8808. ret = host.bubble(self, args, null, es);
  8809. self.stopped = Math.max(self.stopped, es.stopped);
  8810. self.prevented = Math.max(self.prevented, es.prevented);
  8811. // self.bubbling = false;
  8812. es.bubbling = oldbubble;
  8813. }
  8814. if (self.prevented) {
  8815. if (self.preventedFn) {
  8816. self.preventedFn.apply(host, args);
  8817. }
  8818. } else if (self.defaultFn &&
  8819. ((!self.defaultTargetOnly && !es.defaultTargetOnly) ||
  8820. host === ef.target)) {
  8821. self.defaultFn.apply(host, args);
  8822. }
  8823. // broadcast listeners are fired as discreet events on the
  8824. // YUI instance and potentially the YUI global.
  8825. self._broadcast(args);
  8826. // Queue the after
  8827. if (subs[1] && !self.prevented && self.stopped < 2) {
  8828. if (es.id === self.id || self.type != host._yuievt.bubbling) {
  8829. self._procSubs(subs[1], args, ef);
  8830. while ((next = es.afterQueue.last())) {
  8831. next();
  8832. }
  8833. } else {
  8834. postponed = subs[1];
  8835. if (es.execDefaultCnt) {
  8836. postponed = Y.merge(postponed);
  8837. Y.each(postponed, function(s) {
  8838. s.postponed = true;
  8839. });
  8840. }
  8841. es.afterQueue.add(function() {
  8842. self._procSubs(postponed, args, ef);
  8843. });
  8844. }
  8845. }
  8846. self.target = null;
  8847. if (es.id === self.id) {
  8848. queue = es.queue;
  8849. while (queue.length) {
  8850. q = queue.pop();
  8851. ce = q[0];
  8852. // set up stack to allow the next item to be processed
  8853. es.next = ce;
  8854. ce.fire.apply(ce, q[1]);
  8855. }
  8856. self.stack = null;
  8857. }
  8858. ret = !(self.stopped);
  8859. if (self.type != host._yuievt.bubbling) {
  8860. es.stopped = 0;
  8861. es.prevented = 0;
  8862. self.stopped = 0;
  8863. self.prevented = 0;
  8864. }
  8865. return ret;
  8866. };
  8867. CEProto._getFacade = function() {
  8868. var ef = this._facade, o, o2,
  8869. args = this.details;
  8870. if (!ef) {
  8871. ef = new Y.EventFacade(this, this.currentTarget);
  8872. }
  8873. // if the first argument is an object literal, apply the
  8874. // properties to the event facade
  8875. o = args && args[0];
  8876. if (Y.Lang.isObject(o, true)) {
  8877. o2 = {};
  8878. // protect the event facade properties
  8879. Y.mix(o2, ef, true, FACADE_KEYS);
  8880. // mix the data
  8881. Y.mix(ef, o, true);
  8882. // restore ef
  8883. Y.mix(ef, o2, true, FACADE_KEYS);
  8884. // Allow the event type to be faked
  8885. // http://yuilibrary.com/projects/yui3/ticket/2528376
  8886. ef.type = o.type || ef.type;
  8887. }
  8888. // update the details field with the arguments
  8889. // ef.type = this.type;
  8890. ef.details = this.details;
  8891. // use the original target when the event bubbled to this target
  8892. ef.target = this.originalTarget || this.target;
  8893. ef.currentTarget = this.currentTarget;
  8894. ef.stopped = 0;
  8895. ef.prevented = 0;
  8896. this._facade = ef;
  8897. return this._facade;
  8898. };
  8899. /**
  8900. * Stop propagation to bubble targets
  8901. * @for CustomEvent
  8902. * @method stopPropagation
  8903. */
  8904. CEProto.stopPropagation = function() {
  8905. this.stopped = 1;
  8906. if (this.stack) {
  8907. this.stack.stopped = 1;
  8908. }
  8909. this.events.fire('stopped', this);
  8910. };
  8911. /**
  8912. * Stops propagation to bubble targets, and prevents any remaining
  8913. * subscribers on the current target from executing.
  8914. * @method stopImmediatePropagation
  8915. */
  8916. CEProto.stopImmediatePropagation = function() {
  8917. this.stopped = 2;
  8918. if (this.stack) {
  8919. this.stack.stopped = 2;
  8920. }
  8921. this.events.fire('stopped', this);
  8922. };
  8923. /**
  8924. * Prevents the execution of this event's defaultFn
  8925. * @method preventDefault
  8926. */
  8927. CEProto.preventDefault = function() {
  8928. if (this.preventable) {
  8929. this.prevented = 1;
  8930. if (this.stack) {
  8931. this.stack.prevented = 1;
  8932. }
  8933. }
  8934. };
  8935. /**
  8936. * Stops the event propagation and prevents the default
  8937. * event behavior.
  8938. * @method halt
  8939. * @param immediate {boolean} if true additional listeners
  8940. * on the current target will not be executed
  8941. */
  8942. CEProto.halt = function(immediate) {
  8943. if (immediate) {
  8944. this.stopImmediatePropagation();
  8945. } else {
  8946. this.stopPropagation();
  8947. }
  8948. this.preventDefault();
  8949. };
  8950. /**
  8951. * Registers another EventTarget as a bubble target. Bubble order
  8952. * is determined by the order registered. Multiple targets can
  8953. * be specified.
  8954. *
  8955. * Events can only bubble if emitFacade is true.
  8956. *
  8957. * Included in the event-custom-complex submodule.
  8958. *
  8959. * @method addTarget
  8960. * @param o {EventTarget} the target to add
  8961. * @for EventTarget
  8962. */
  8963. ETProto.addTarget = function(o) {
  8964. this._yuievt.targets[Y.stamp(o)] = o;
  8965. this._yuievt.hasTargets = true;
  8966. };
  8967. /**
  8968. * Returns an array of bubble targets for this object.
  8969. * @method getTargets
  8970. * @return EventTarget[]
  8971. */
  8972. ETProto.getTargets = function() {
  8973. return Y.Object.values(this._yuievt.targets);
  8974. };
  8975. /**
  8976. * Removes a bubble target
  8977. * @method removeTarget
  8978. * @param o {EventTarget} the target to remove
  8979. * @for EventTarget
  8980. */
  8981. ETProto.removeTarget = function(o) {
  8982. delete this._yuievt.targets[Y.stamp(o)];
  8983. };
  8984. /**
  8985. * Propagate an event. Requires the event-custom-complex module.
  8986. * @method bubble
  8987. * @param evt {CustomEvent} the custom event to propagate
  8988. * @return {boolean} the aggregated return value from Event.Custom.fire
  8989. * @for EventTarget
  8990. */
  8991. ETProto.bubble = function(evt, args, target, es) {
  8992. var targs = this._yuievt.targets, ret = true,
  8993. t, type = evt && evt.type, ce, i, bc, ce2,
  8994. originalTarget = target || (evt && evt.target) || this,
  8995. oldbubble;
  8996. if (!evt || ((!evt.stopped) && targs)) {
  8997. // Y.log('Bubbling ' + evt.type);
  8998. for (i in targs) {
  8999. if (targs.hasOwnProperty(i)) {
  9000. t = targs[i];
  9001. ce = t.getEvent(type, true);
  9002. ce2 = t.getSibling(type, ce);
  9003. if (ce2 && !ce) {
  9004. ce = t.publish(type);
  9005. }
  9006. oldbubble = t._yuievt.bubbling;
  9007. t._yuievt.bubbling = type;
  9008. // if this event was not published on the bubble target,
  9009. // continue propagating the event.
  9010. if (!ce) {
  9011. if (t._yuievt.hasTargets) {
  9012. t.bubble(evt, args, originalTarget, es);
  9013. }
  9014. } else {
  9015. ce.sibling = ce2;
  9016. // set the original target to that the target payload on the
  9017. // facade is correct.
  9018. ce.target = originalTarget;
  9019. ce.originalTarget = originalTarget;
  9020. ce.currentTarget = t;
  9021. bc = ce.broadcast;
  9022. ce.broadcast = false;
  9023. // default publish may not have emitFacade true -- that
  9024. // shouldn't be what the implementer meant To Do
  9025. ce.emitFacade = true;
  9026. ce.stack = es;
  9027. ret = ret && ce.fire.apply(ce, args || evt.details || []);
  9028. ce.broadcast = bc;
  9029. ce.originalTarget = null;
  9030. // stopPropagation() was called
  9031. if (ce.stopped) {
  9032. break;
  9033. }
  9034. }
  9035. t._yuievt.bubbling = oldbubble;
  9036. }
  9037. }
  9038. }
  9039. return ret;
  9040. };
  9041. FACADE = new Y.EventFacade();
  9042. FACADE_KEYS = Y.Object.keys(FACADE);
  9043. }, '3.4.0' ,{requires:['event-custom-base']});
  9044. YUI.add('node-core', function(Y) {
  9045. /**
  9046. * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
  9047. * @module node
  9048. * @submodule node-core
  9049. */
  9050. /**
  9051. * The Node class provides a wrapper for manipulating DOM Nodes.
  9052. * Node properties can be accessed via the set/get methods.
  9053. * Use `Y.one()` to retrieve Node instances.
  9054. *
  9055. * <strong>NOTE:</strong> Node properties are accessed using
  9056. * the <code>set</code> and <code>get</code> methods.
  9057. *
  9058. * @class Node
  9059. * @constructor
  9060. * @param {DOMNode} node the DOM node to be mapped to the Node instance.
  9061. * @uses EventTarget
  9062. */
  9063. // "globals"
  9064. var DOT = '.',
  9065. NODE_NAME = 'nodeName',
  9066. NODE_TYPE = 'nodeType',
  9067. OWNER_DOCUMENT = 'ownerDocument',
  9068. TAG_NAME = 'tagName',
  9069. UID = '_yuid',
  9070. EMPTY_OBJ = {},
  9071. _slice = Array.prototype.slice,
  9072. Y_DOM = Y.DOM,
  9073. Y_Node = function(node) {
  9074. if (!this.getDOMNode) { // support optional "new"
  9075. return new Y_Node(node);
  9076. }
  9077. if (typeof node == 'string') {
  9078. node = Y_Node._fromString(node);
  9079. if (!node) {
  9080. return null; // NOTE: return
  9081. }
  9082. }
  9083. var uid = (node.nodeType !== 9) ? node.uniqueID : node[UID];
  9084. if (uid && Y_Node._instances[uid] && Y_Node._instances[uid]._node !== node) {
  9085. node[UID] = null; // unset existing uid to prevent collision (via clone or hack)
  9086. }
  9087. uid = uid || Y.stamp(node);
  9088. if (!uid) { // stamp failed; likely IE non-HTMLElement
  9089. uid = Y.guid();
  9090. }
  9091. this[UID] = uid;
  9092. /**
  9093. * The underlying DOM node bound to the Y.Node instance
  9094. * @property _node
  9095. * @private
  9096. */
  9097. this._node = node;
  9098. this._stateProxy = node; // when augmented with Attribute
  9099. if (this._initPlugins) { // when augmented with Plugin.Host
  9100. this._initPlugins();
  9101. }
  9102. },
  9103. // used with previous/next/ancestor tests
  9104. _wrapFn = function(fn) {
  9105. var ret = null;
  9106. if (fn) {
  9107. ret = (typeof fn == 'string') ?
  9108. function(n) {
  9109. return Y.Selector.test(n, fn);
  9110. } :
  9111. function(n) {
  9112. return fn(Y.one(n));
  9113. };
  9114. }
  9115. return ret;
  9116. };
  9117. // end "globals"
  9118. Y_Node.ATTRS = {};
  9119. Y_Node.DOM_EVENTS = {};
  9120. Y_Node._fromString = function(node) {
  9121. if (node) {
  9122. if (node.indexOf('doc') === 0) { // doc OR document
  9123. node = Y.config.doc;
  9124. } else if (node.indexOf('win') === 0) { // win OR window
  9125. node = Y.config.win;
  9126. } else {
  9127. node = Y.Selector.query(node, null, true);
  9128. }
  9129. }
  9130. return node || null;
  9131. };
  9132. /**
  9133. * The name of the component
  9134. * @static
  9135. * @property NAME
  9136. */
  9137. Y_Node.NAME = 'node';
  9138. /*
  9139. * The pattern used to identify ARIA attributes
  9140. */
  9141. Y_Node.re_aria = /^(?:role$|aria-)/;
  9142. Y_Node.SHOW_TRANSITION = 'fadeIn';
  9143. Y_Node.HIDE_TRANSITION = 'fadeOut';
  9144. /**
  9145. * A list of Node instances that have been created
  9146. * @private
  9147. * @property _instances
  9148. * @static
  9149. *
  9150. */
  9151. Y_Node._instances = {};
  9152. /**
  9153. * Retrieves the DOM node bound to a Node instance
  9154. * @method getDOMNode
  9155. * @static
  9156. *
  9157. * @param {Y.Node || HTMLNode} node The Node instance or an HTMLNode
  9158. * @return {HTMLNode} The DOM node bound to the Node instance. If a DOM node is passed
  9159. * as the node argument, it is simply returned.
  9160. */
  9161. Y_Node.getDOMNode = function(node) {
  9162. if (node) {
  9163. return (node.nodeType) ? node : node._node || null;
  9164. }
  9165. return null;
  9166. };
  9167. /**
  9168. * Checks Node return values and wraps DOM Nodes as Y.Node instances
  9169. * and DOM Collections / Arrays as Y.NodeList instances.
  9170. * Other return values just pass thru. If undefined is returned (e.g. no return)
  9171. * then the Node instance is returned for chainability.
  9172. * @method scrubVal
  9173. * @static
  9174. *
  9175. * @param {any} node The Node instance or an HTMLNode
  9176. * @return {Y.Node | Y.NodeList | any} Depends on what is returned from the DOM node.
  9177. */
  9178. Y_Node.scrubVal = function(val, node) {
  9179. if (val) { // only truthy values are risky
  9180. if (typeof val == 'object' || typeof val == 'function') { // safari nodeList === function
  9181. if (NODE_TYPE in val || Y_DOM.isWindow(val)) {// node || window
  9182. val = Y.one(val);
  9183. } else if ((val.item && !val._nodes) || // dom collection or Node instance
  9184. (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes
  9185. val = Y.all(val);
  9186. }
  9187. }
  9188. } else if (typeof val === 'undefined') {
  9189. val = node; // for chaining
  9190. } else if (val === null) {
  9191. val = null; // IE: DOM null not the same as null
  9192. }
  9193. return val;
  9194. };
  9195. /**
  9196. * Adds methods to the Y.Node prototype, routing through scrubVal.
  9197. * @method addMethod
  9198. * @static
  9199. *
  9200. * @param {String} name The name of the method to add
  9201. * @param {Function} fn The function that becomes the method
  9202. * @param {Object} context An optional context to call the method with
  9203. * (defaults to the Node instance)
  9204. * @return {any} Depends on what is returned from the DOM node.
  9205. */
  9206. Y_Node.addMethod = function(name, fn, context) {
  9207. if (name && fn && typeof fn == 'function') {
  9208. Y_Node.prototype[name] = function() {
  9209. var args = _slice.call(arguments),
  9210. node = this,
  9211. ret;
  9212. if (args[0] && Y.instanceOf(args[0], Y_Node)) {
  9213. args[0] = args[0]._node;
  9214. }
  9215. if (args[1] && Y.instanceOf(args[1], Y_Node)) {
  9216. args[1] = args[1]._node;
  9217. }
  9218. args.unshift(node._node);
  9219. ret = fn.apply(node, args);
  9220. if (ret) { // scrub truthy
  9221. ret = Y_Node.scrubVal(ret, node);
  9222. }
  9223. (typeof ret != 'undefined') || (ret = node);
  9224. return ret;
  9225. };
  9226. } else {
  9227. Y.log('unable to add method: ' + name, 'warn', 'Node');
  9228. }
  9229. };
  9230. /**
  9231. * Imports utility methods to be added as Y.Node methods.
  9232. * @method importMethod
  9233. * @static
  9234. *
  9235. * @param {Object} host The object that contains the method to import.
  9236. * @param {String} name The name of the method to import
  9237. * @param {String} altName An optional name to use in place of the host name
  9238. * @param {Object} context An optional context to call the method with
  9239. */
  9240. Y_Node.importMethod = function(host, name, altName) {
  9241. if (typeof name == 'string') {
  9242. altName = altName || name;
  9243. Y_Node.addMethod(altName, host[name], host);
  9244. } else {
  9245. Y.Array.each(name, function(n) {
  9246. Y_Node.importMethod(host, n);
  9247. });
  9248. }
  9249. };
  9250. /**
  9251. * Retrieves a NodeList based on the given CSS selector.
  9252. * @method all
  9253. *
  9254. * @param {string} selector The CSS selector to test against.
  9255. * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
  9256. * @for YUI
  9257. */
  9258. /**
  9259. * Returns a single Node instance bound to the node or the
  9260. * first element matching the given selector. Returns null if no match found.
  9261. * <strong>Note:</strong> For chaining purposes you may want to
  9262. * use <code>Y.all</code>, which returns a NodeList when no match is found.
  9263. * @method one
  9264. * @param {String | HTMLElement} node a node or Selector
  9265. * @return {Y.Node | null} a Node instance or null if no match found.
  9266. * @for YUI
  9267. */
  9268. /**
  9269. * Returns a single Node instance bound to the node or the
  9270. * first element matching the given selector. Returns null if no match found.
  9271. * <strong>Note:</strong> For chaining purposes you may want to
  9272. * use <code>Y.all</code>, which returns a NodeList when no match is found.
  9273. * @method one
  9274. * @static
  9275. * @param {String | HTMLElement} node a node or Selector
  9276. * @return {Y.Node | null} a Node instance or null if no match found.
  9277. * @for Node
  9278. */
  9279. Y_Node.one = function(node) {
  9280. var instance = null,
  9281. cachedNode,
  9282. uid;
  9283. if (node) {
  9284. if (typeof node == 'string') {
  9285. node = Y_Node._fromString(node);
  9286. if (!node) {
  9287. return null; // NOTE: return
  9288. }
  9289. } else if (node.getDOMNode) {
  9290. return node; // NOTE: return
  9291. }
  9292. if (node.nodeType || Y.DOM.isWindow(node)) { // avoid bad input (numbers, boolean, etc)
  9293. uid = (node.uniqueID && node.nodeType !== 9) ? node.uniqueID : node._yuid;
  9294. instance = Y_Node._instances[uid]; // reuse exising instances
  9295. cachedNode = instance ? instance._node : null;
  9296. if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match
  9297. instance = new Y_Node(node);
  9298. if (node.nodeType != 11) { // dont cache document fragment
  9299. Y_Node._instances[instance[UID]] = instance; // cache node
  9300. }
  9301. }
  9302. }
  9303. }
  9304. return instance;
  9305. };
  9306. /**
  9307. * The default setter for DOM properties
  9308. * Called with instance context (this === the Node instance)
  9309. * @method DEFAULT_SETTER
  9310. * @static
  9311. * @param {String} name The attribute/property being set
  9312. * @param {any} val The value to be set
  9313. * @return {any} The value
  9314. */
  9315. Y_Node.DEFAULT_SETTER = function(name, val) {
  9316. var node = this._stateProxy,
  9317. strPath;
  9318. if (name.indexOf(DOT) > -1) {
  9319. strPath = name;
  9320. name = name.split(DOT);
  9321. // only allow when defined on node
  9322. Y.Object.setValue(node, name, val);
  9323. } else if (typeof node[name] != 'undefined') { // pass thru DOM properties
  9324. node[name] = val;
  9325. }
  9326. return val;
  9327. };
  9328. /**
  9329. * The default getter for DOM properties
  9330. * Called with instance context (this === the Node instance)
  9331. * @method DEFAULT_GETTER
  9332. * @static
  9333. * @param {String} name The attribute/property to look up
  9334. * @return {any} The current value
  9335. */
  9336. Y_Node.DEFAULT_GETTER = function(name) {
  9337. var node = this._stateProxy,
  9338. val;
  9339. if (name.indexOf && name.indexOf(DOT) > -1) {
  9340. val = Y.Object.getValue(node, name.split(DOT));
  9341. } else if (typeof node[name] != 'undefined') { // pass thru from DOM
  9342. val = node[name];
  9343. }
  9344. return val;
  9345. };
  9346. Y.mix(Y_Node.prototype, {
  9347. /**
  9348. * The method called when outputting Node instances as strings
  9349. * @method toString
  9350. * @return {String} A string representation of the Node instance
  9351. */
  9352. toString: function() {
  9353. var str = this[UID] + ': not bound to a node',
  9354. node = this._node,
  9355. attrs, id, className;
  9356. if (node) {
  9357. attrs = node.attributes;
  9358. id = (attrs && attrs.id) ? node.getAttribute('id') : null;
  9359. className = (attrs && attrs.className) ? node.getAttribute('className') : null;
  9360. str = node[NODE_NAME];
  9361. if (id) {
  9362. str += '#' + id;
  9363. }
  9364. if (className) {
  9365. str += '.' + className.replace(' ', '.');
  9366. }
  9367. // TODO: add yuid?
  9368. str += ' ' + this[UID];
  9369. }
  9370. return str;
  9371. },
  9372. /**
  9373. * Returns an attribute value on the Node instance.
  9374. * Unless pre-configured (via `Node.ATTRS`), get hands
  9375. * off to the underlying DOM node. Only valid
  9376. * attributes/properties for the node will be queried.
  9377. * @method get
  9378. * @param {String} attr The attribute
  9379. * @return {any} The current value of the attribute
  9380. */
  9381. get: function(attr) {
  9382. var val;
  9383. if (this._getAttr) { // use Attribute imple
  9384. val = this._getAttr(attr);
  9385. } else {
  9386. val = this._get(attr);
  9387. }
  9388. if (val) {
  9389. val = Y_Node.scrubVal(val, this);
  9390. } else if (val === null) {
  9391. val = null; // IE: DOM null is not true null (even though they ===)
  9392. }
  9393. return val;
  9394. },
  9395. /**
  9396. * Helper method for get.
  9397. * @method _get
  9398. * @private
  9399. * @param {String} attr The attribute
  9400. * @return {any} The current value of the attribute
  9401. */
  9402. _get: function(attr) {
  9403. var attrConfig = Y_Node.ATTRS[attr],
  9404. val;
  9405. if (attrConfig && attrConfig.getter) {
  9406. val = attrConfig.getter.call(this);
  9407. } else if (Y_Node.re_aria.test(attr)) {
  9408. val = this._node.getAttribute(attr, 2);
  9409. } else {
  9410. val = Y_Node.DEFAULT_GETTER.apply(this, arguments);
  9411. }
  9412. return val;
  9413. },
  9414. /**
  9415. * Sets an attribute on the Node instance.
  9416. * Unless pre-configured (via Node.ATTRS), set hands
  9417. * off to the underlying DOM node. Only valid
  9418. * attributes/properties for the node will be set.
  9419. * To set custom attributes use setAttribute.
  9420. * @method set
  9421. * @param {String} attr The attribute to be set.
  9422. * @param {any} val The value to set the attribute to.
  9423. * @chainable
  9424. */
  9425. set: function(attr, val) {
  9426. var attrConfig = Y_Node.ATTRS[attr];
  9427. if (this._setAttr) { // use Attribute imple
  9428. this._setAttr.apply(this, arguments);
  9429. } else { // use setters inline
  9430. if (attrConfig && attrConfig.setter) {
  9431. attrConfig.setter.call(this, val, attr);
  9432. } else if (Y_Node.re_aria.test(attr)) { // special case Aria
  9433. this._node.setAttribute(attr, val);
  9434. } else {
  9435. Y_Node.DEFAULT_SETTER.apply(this, arguments);
  9436. }
  9437. }
  9438. return this;
  9439. },
  9440. /**
  9441. * Sets multiple attributes.
  9442. * @method setAttrs
  9443. * @param {Object} attrMap an object of name/value pairs to set
  9444. * @chainable
  9445. */
  9446. setAttrs: function(attrMap) {
  9447. if (this._setAttrs) { // use Attribute imple
  9448. this._setAttrs(attrMap);
  9449. } else { // use setters inline
  9450. Y.Object.each(attrMap, function(v, n) {
  9451. this.set(n, v);
  9452. }, this);
  9453. }
  9454. return this;
  9455. },
  9456. /**
  9457. * Returns an object containing the values for the requested attributes.
  9458. * @method getAttrs
  9459. * @param {Array} attrs an array of attributes to get values
  9460. * @return {Object} An object with attribute name/value pairs.
  9461. */
  9462. getAttrs: function(attrs) {
  9463. var ret = {};
  9464. if (this._getAttrs) { // use Attribute imple
  9465. this._getAttrs(attrs);
  9466. } else { // use setters inline
  9467. Y.Array.each(attrs, function(v, n) {
  9468. ret[v] = this.get(v);
  9469. }, this);
  9470. }
  9471. return ret;
  9472. },
  9473. /**
  9474. * Compares nodes to determine if they match.
  9475. * Node instances can be compared to each other and/or HTMLElements.
  9476. * @method compareTo
  9477. * @param {HTMLElement | Node} refNode The reference node to compare to the node.
  9478. * @return {Boolean} True if the nodes match, false if they do not.
  9479. */
  9480. compareTo: function(refNode) {
  9481. var node = this._node;
  9482. if (Y.instanceOf(refNode, Y_Node)) {
  9483. refNode = refNode._node;
  9484. }
  9485. return node === refNode;
  9486. },
  9487. /**
  9488. * Determines whether the node is appended to the document.
  9489. * @method inDoc
  9490. * @param {Node|HTMLElement} doc optional An optional document to check against.
  9491. * Defaults to current document.
  9492. * @return {Boolean} Whether or not this node is appended to the document.
  9493. */
  9494. inDoc: function(doc) {
  9495. var node = this._node;
  9496. doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT];
  9497. if (doc.documentElement) {
  9498. return Y_DOM.contains(doc.documentElement, node);
  9499. }
  9500. },
  9501. getById: function(id) {
  9502. var node = this._node,
  9503. ret = Y_DOM.byId(id, node[OWNER_DOCUMENT]);
  9504. if (ret && Y_DOM.contains(node, ret)) {
  9505. ret = Y.one(ret);
  9506. } else {
  9507. ret = null;
  9508. }
  9509. return ret;
  9510. },
  9511. /**
  9512. * Returns the nearest ancestor that passes the test applied by supplied boolean method.
  9513. * @method ancestor
  9514. * @param {String | Function} fn A selector string or boolean method for testing elements.
  9515. * @param {Boolean} testSelf optional Whether or not to include the element in the scan
  9516. * If a function is used, it receives the current node being tested as the only argument.
  9517. * @return {Node} The matching Node instance or null if not found
  9518. */
  9519. ancestor: function(fn, testSelf) {
  9520. return Y.one(Y_DOM.ancestor(this._node, _wrapFn(fn), testSelf));
  9521. },
  9522. /**
  9523. * Returns the ancestors that pass the test applied by supplied boolean method.
  9524. * @method ancestors
  9525. * @param {String | Function} fn A selector string or boolean method for testing elements.
  9526. * @param {Boolean} testSelf optional Whether or not to include the element in the scan
  9527. * If a function is used, it receives the current node being tested as the only argument.
  9528. * @return {NodeList} A NodeList instance containing the matching elements
  9529. */
  9530. ancestors: function(fn, testSelf) {
  9531. return Y.all(Y_DOM.ancestors(this._node, _wrapFn(fn), testSelf));
  9532. },
  9533. /**
  9534. * Returns the previous matching sibling.
  9535. * Returns the nearest element node sibling if no method provided.
  9536. * @method previous
  9537. * @param {String | Function} fn A selector or boolean method for testing elements.
  9538. * If a function is used, it receives the current node being tested as the only argument.
  9539. * @return {Node} Node instance or null if not found
  9540. */
  9541. previous: function(fn, all) {
  9542. return Y.one(Y_DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all));
  9543. },
  9544. /**
  9545. * Returns the next matching sibling.
  9546. * Returns the nearest element node sibling if no method provided.
  9547. * @method next
  9548. * @param {String | Function} fn A selector or boolean method for testing elements.
  9549. * If a function is used, it receives the current node being tested as the only argument.
  9550. * @return {Node} Node instance or null if not found
  9551. */
  9552. next: function(fn, all) {
  9553. return Y.one(Y_DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all));
  9554. },
  9555. /**
  9556. * Returns all matching siblings.
  9557. * Returns all siblings if no method provided.
  9558. * @method siblings
  9559. * @param {String | Function} fn A selector or boolean method for testing elements.
  9560. * If a function is used, it receives the current node being tested as the only argument.
  9561. * @return {NodeList} NodeList instance bound to found siblings
  9562. */
  9563. siblings: function(fn) {
  9564. return Y.all(Y_DOM.siblings(this._node, _wrapFn(fn)));
  9565. },
  9566. /**
  9567. * Retrieves a Node instance of nodes based on the given CSS selector.
  9568. * @method one
  9569. *
  9570. * @param {string} selector The CSS selector to test against.
  9571. * @return {Node} A Node instance for the matching HTMLElement.
  9572. */
  9573. one: function(selector) {
  9574. return Y.one(Y.Selector.query(selector, this._node, true));
  9575. },
  9576. /**
  9577. * Retrieves a NodeList based on the given CSS selector.
  9578. * @method all
  9579. *
  9580. * @param {string} selector The CSS selector to test against.
  9581. * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
  9582. */
  9583. all: function(selector) {
  9584. var nodelist = Y.all(Y.Selector.query(selector, this._node));
  9585. nodelist._query = selector;
  9586. nodelist._queryRoot = this._node;
  9587. return nodelist;
  9588. },
  9589. // TODO: allow fn test
  9590. /**
  9591. * Test if the supplied node matches the supplied selector.
  9592. * @method test
  9593. *
  9594. * @param {string} selector The CSS selector to test against.
  9595. * @return {boolean} Whether or not the node matches the selector.
  9596. */
  9597. test: function(selector) {
  9598. return Y.Selector.test(this._node, selector);
  9599. },
  9600. /**
  9601. * Removes the node from its parent.
  9602. * Shortcut for myNode.get('parentNode').removeChild(myNode);
  9603. * @method remove
  9604. * @param {Boolean} destroy whether or not to call destroy() on the node
  9605. * after removal.
  9606. * @chainable
  9607. *
  9608. */
  9609. remove: function(destroy) {
  9610. var node = this._node;
  9611. if (node && node.parentNode) {
  9612. node.parentNode.removeChild(node);
  9613. }
  9614. if (destroy) {
  9615. this.destroy();
  9616. }
  9617. return this;
  9618. },
  9619. /**
  9620. * Replace the node with the other node. This is a DOM update only
  9621. * and does not change the node bound to the Node instance.
  9622. * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode);
  9623. * @method replace
  9624. * @param {Y.Node || HTMLNode} newNode Node to be inserted
  9625. * @chainable
  9626. *
  9627. */
  9628. replace: function(newNode) {
  9629. var node = this._node;
  9630. if (typeof newNode == 'string') {
  9631. newNode = Y_Node.create(newNode);
  9632. }
  9633. node.parentNode.replaceChild(Y_Node.getDOMNode(newNode), node);
  9634. return this;
  9635. },
  9636. /**
  9637. * @method replaceChild
  9638. * @for Node
  9639. * @param {String | HTMLElement | Node} node Node to be inserted
  9640. * @param {HTMLElement | Node} refNode Node to be replaced
  9641. * @return {Node} The replaced node
  9642. */
  9643. replaceChild: function(node, refNode) {
  9644. if (typeof node == 'string') {
  9645. node = Y_DOM.create(node);
  9646. }
  9647. return Y.one(this._node.replaceChild(Y_Node.getDOMNode(node), Y_Node.getDOMNode(refNode)));
  9648. },
  9649. /**
  9650. * Nulls internal node references, removes any plugins and event listeners
  9651. * @method destroy
  9652. * @param {Boolean} recursivePurge (optional) Whether or not to remove listeners from the
  9653. * node's subtree (default is false)
  9654. *
  9655. */
  9656. destroy: function(recursive) {
  9657. var UID = Y.config.doc.uniqueID ? 'uniqueID' : '_yuid',
  9658. instance;
  9659. this.purge(); // TODO: only remove events add via this Node
  9660. if (this.unplug) { // may not be a PluginHost
  9661. this.unplug();
  9662. }
  9663. this.clearData();
  9664. if (recursive) {
  9665. Y.NodeList.each(this.all('*'), function(node) {
  9666. instance = Y_Node._instances[node[UID]];
  9667. if (instance) {
  9668. instance.destroy();
  9669. }
  9670. });
  9671. }
  9672. this._node = null;
  9673. this._stateProxy = null;
  9674. delete Y_Node._instances[this._yuid];
  9675. },
  9676. /**
  9677. * Invokes a method on the Node instance
  9678. * @method invoke
  9679. * @param {String} method The name of the method to invoke
  9680. * @param {Any} a, b, c, etc. Arguments to invoke the method with.
  9681. * @return Whatever the underly method returns.
  9682. * DOM Nodes and Collections return values
  9683. * are converted to Node/NodeList instances.
  9684. *
  9685. */
  9686. invoke: function(method, a, b, c, d, e) {
  9687. var node = this._node,
  9688. ret;
  9689. if (a && Y.instanceOf(a, Y_Node)) {
  9690. a = a._node;
  9691. }
  9692. if (b && Y.instanceOf(b, Y_Node)) {
  9693. b = b._node;
  9694. }
  9695. ret = node[method](a, b, c, d, e);
  9696. return Y_Node.scrubVal(ret, this);
  9697. },
  9698. /**
  9699. * @method swap
  9700. * @description Swap DOM locations with the given node.
  9701. * This does not change which DOM node each Node instance refers to.
  9702. * @param {Node} otherNode The node to swap with
  9703. * @chainable
  9704. */
  9705. swap: Y.config.doc.documentElement.swapNode ?
  9706. function(otherNode) {
  9707. this._node.swapNode(Y_Node.getDOMNode(otherNode));
  9708. } :
  9709. function(otherNode) {
  9710. otherNode = Y_Node.getDOMNode(otherNode);
  9711. var node = this._node,
  9712. parent = otherNode.parentNode,
  9713. nextSibling = otherNode.nextSibling;
  9714. if (nextSibling === node) {
  9715. parent.insertBefore(node, otherNode);
  9716. } else if (otherNode === node.nextSibling) {
  9717. parent.insertBefore(otherNode, node);
  9718. } else {
  9719. node.parentNode.replaceChild(otherNode, node);
  9720. Y_DOM.addHTML(parent, node, nextSibling);
  9721. }
  9722. return this;
  9723. },
  9724. /**
  9725. * @method getData
  9726. * @description Retrieves arbitrary data stored on a Node instance.
  9727. * This is not stored with the DOM node.
  9728. * @param {string} name Optional name of the data field to retrieve.
  9729. * If no name is given, all data is returned.
  9730. * @return {any | Object} Whatever is stored at the given field,
  9731. * or an object hash of all fields.
  9732. */
  9733. getData: function(name) {
  9734. var ret;
  9735. this._data = this._data || {};
  9736. if (arguments.length) {
  9737. ret = this._data[name];
  9738. } else {
  9739. ret = this._data;
  9740. }
  9741. return ret;
  9742. },
  9743. /**
  9744. * @method setData
  9745. * @description Stores arbitrary data on a Node instance.
  9746. * This is not stored with the DOM node.
  9747. * @param {string} name The name of the field to set. If no name
  9748. * is given, name is treated as the data and overrides any existing data.
  9749. * @param {any} val The value to be assigned to the field.
  9750. * @chainable
  9751. */
  9752. setData: function(name, val) {
  9753. this._data = this._data || {};
  9754. if (arguments.length > 1) {
  9755. this._data[name] = val;
  9756. } else {
  9757. this._data = name;
  9758. }
  9759. return this;
  9760. },
  9761. /**
  9762. * @method clearData
  9763. * @description Clears stored data.
  9764. * @param {string} name The name of the field to clear. If no name
  9765. * is given, all data is cleared.
  9766. * @chainable
  9767. */
  9768. clearData: function(name) {
  9769. if ('_data' in this) {
  9770. if (name) {
  9771. delete this._data[name];
  9772. } else {
  9773. delete this._data;
  9774. }
  9775. }
  9776. return this;
  9777. },
  9778. hasMethod: function(method) {
  9779. var node = this._node;
  9780. return !!(node && method in node &&
  9781. typeof node[method] != 'unknown' &&
  9782. (typeof node[method] == 'function' ||
  9783. String(node[method]).indexOf('function') === 1)); // IE reports as object, prepends space
  9784. },
  9785. isFragment: function() {
  9786. return (this.get('nodeType') === 11);
  9787. },
  9788. /**
  9789. * Removes and destroys all of the nodes within the node.
  9790. * @method empty
  9791. * @chainable
  9792. */
  9793. empty: function() {
  9794. this.get('childNodes').remove().destroy(true);
  9795. return this;
  9796. },
  9797. /**
  9798. * Returns the DOM node bound to the Node instance
  9799. * @method getDOMNode
  9800. * @return {DOMNode}
  9801. */
  9802. getDOMNode: function() {
  9803. return this._node;
  9804. }
  9805. }, true);
  9806. Y.Node = Y_Node;
  9807. Y.one = Y_Node.one;
  9808. /**
  9809. * The NodeList module provides support for managing collections of Nodes.
  9810. * @module node
  9811. * @submodule node-core
  9812. */
  9813. /**
  9814. * The NodeList class provides a wrapper for manipulating DOM NodeLists.
  9815. * NodeList properties can be accessed via the set/get methods.
  9816. * Use Y.all() to retrieve NodeList instances.
  9817. *
  9818. * @class NodeList
  9819. * @constructor
  9820. */
  9821. var NodeList = function(nodes) {
  9822. var tmp = [];
  9823. if (typeof nodes === 'string') { // selector query
  9824. this._query = nodes;
  9825. nodes = Y.Selector.query(nodes);
  9826. } else if (nodes.nodeType || Y_DOM.isWindow(nodes)) { // domNode || window
  9827. nodes = [nodes];
  9828. } else if (Y.instanceOf(nodes, Y.Node)) {
  9829. nodes = [nodes._node];
  9830. } else if (Y.instanceOf(nodes[0], Y.Node)) { // allow array of Y.Nodes
  9831. Y.Array.each(nodes, function(node) {
  9832. if (node._node) {
  9833. tmp.push(node._node);
  9834. }
  9835. });
  9836. nodes = tmp;
  9837. } else { // array of domNodes or domNodeList (no mixed array of Y.Node/domNodes)
  9838. nodes = Y.Array(nodes, 0, true);
  9839. }
  9840. /**
  9841. * The underlying array of DOM nodes bound to the Y.NodeList instance
  9842. * @property _nodes
  9843. * @private
  9844. */
  9845. this._nodes = nodes;
  9846. };
  9847. NodeList.NAME = 'NodeList';
  9848. /**
  9849. * Retrieves the DOM nodes bound to a NodeList instance
  9850. * @method getDOMNodes
  9851. * @static
  9852. *
  9853. * @param {Y.NodeList} nodelist The NodeList instance
  9854. * @return {Array} The array of DOM nodes bound to the NodeList
  9855. */
  9856. NodeList.getDOMNodes = function(nodelist) {
  9857. return (nodelist && nodelist._nodes) ? nodelist._nodes : nodelist;
  9858. };
  9859. NodeList.each = function(instance, fn, context) {
  9860. var nodes = instance._nodes;
  9861. if (nodes && nodes.length) {
  9862. Y.Array.each(nodes, fn, context || instance);
  9863. } else {
  9864. Y.log('no nodes bound to ' + this, 'warn', 'NodeList');
  9865. }
  9866. };
  9867. NodeList.addMethod = function(name, fn, context) {
  9868. if (name && fn) {
  9869. NodeList.prototype[name] = function() {
  9870. var ret = [],
  9871. args = arguments;
  9872. Y.Array.each(this._nodes, function(node) {
  9873. var UID = (node.uniqueID && node.nodeType !== 9 ) ? 'uniqueID' : '_yuid',
  9874. instance = Y.Node._instances[node[UID]],
  9875. ctx,
  9876. result;
  9877. if (!instance) {
  9878. instance = NodeList._getTempNode(node);
  9879. }
  9880. ctx = context || instance;
  9881. result = fn.apply(ctx, args);
  9882. if (result !== undefined && result !== instance) {
  9883. ret[ret.length] = result;
  9884. }
  9885. });
  9886. // TODO: remove tmp pointer
  9887. return ret.length ? ret : this;
  9888. };
  9889. } else {
  9890. Y.log('unable to add method: ' + name + ' to NodeList', 'warn', 'node');
  9891. }
  9892. };
  9893. NodeList.importMethod = function(host, name, altName) {
  9894. if (typeof name === 'string') {
  9895. altName = altName || name;
  9896. NodeList.addMethod(name, host[name]);
  9897. } else {
  9898. Y.Array.each(name, function(n) {
  9899. NodeList.importMethod(host, n);
  9900. });
  9901. }
  9902. };
  9903. NodeList._getTempNode = function(node) {
  9904. var tmp = NodeList._tempNode;
  9905. if (!tmp) {
  9906. tmp = Y.Node.create('<div></div>');
  9907. NodeList._tempNode = tmp;
  9908. }
  9909. tmp._node = node;
  9910. tmp._stateProxy = node;
  9911. return tmp;
  9912. };
  9913. Y.mix(NodeList.prototype, {
  9914. /**
  9915. * Retrieves the Node instance at the given index.
  9916. * @method item
  9917. *
  9918. * @param {Number} index The index of the target Node.
  9919. * @return {Node} The Node instance at the given index.
  9920. */
  9921. item: function(index) {
  9922. return Y.one((this._nodes || [])[index]);
  9923. },
  9924. /**
  9925. * Applies the given function to each Node in the NodeList.
  9926. * @method each
  9927. * @param {Function} fn The function to apply. It receives 3 arguments:
  9928. * the current node instance, the node's index, and the NodeList instance
  9929. * @param {Object} context optional An optional context to apply the function with
  9930. * Default context is the current Node instance
  9931. * @chainable
  9932. */
  9933. each: function(fn, context) {
  9934. var instance = this;
  9935. Y.Array.each(this._nodes, function(node, index) {
  9936. node = Y.one(node);
  9937. return fn.call(context || node, node, index, instance);
  9938. });
  9939. return instance;
  9940. },
  9941. batch: function(fn, context) {
  9942. var nodelist = this;
  9943. Y.Array.each(this._nodes, function(node, index) {
  9944. var instance = Y.Node._instances[node[UID]];
  9945. if (!instance) {
  9946. instance = NodeList._getTempNode(node);
  9947. }
  9948. return fn.call(context || instance, instance, index, nodelist);
  9949. });
  9950. return nodelist;
  9951. },
  9952. /**
  9953. * Executes the function once for each node until a true value is returned.
  9954. * @method some
  9955. * @param {Function} fn The function to apply. It receives 3 arguments:
  9956. * the current node instance, the node's index, and the NodeList instance
  9957. * @param {Object} context optional An optional context to execute the function from.
  9958. * Default context is the current Node instance
  9959. * @return {Boolean} Whether or not the function returned true for any node.
  9960. */
  9961. some: function(fn, context) {
  9962. var instance = this;
  9963. return Y.Array.some(this._nodes, function(node, index) {
  9964. node = Y.one(node);
  9965. context = context || node;
  9966. return fn.call(context, node, index, instance);
  9967. });
  9968. },
  9969. /**
  9970. * Creates a documenFragment from the nodes bound to the NodeList instance
  9971. * @method toFrag
  9972. * @return Node a Node instance bound to the documentFragment
  9973. */
  9974. toFrag: function() {
  9975. return Y.one(Y.DOM._nl2frag(this._nodes));
  9976. },
  9977. /**
  9978. * Returns the index of the node in the NodeList instance
  9979. * or -1 if the node isn't found.
  9980. * @method indexOf
  9981. * @param {Y.Node || DOMNode} node the node to search for
  9982. * @return {Int} the index of the node value or -1 if not found
  9983. */
  9984. indexOf: function(node) {
  9985. return Y.Array.indexOf(this._nodes, Y.Node.getDOMNode(node));
  9986. },
  9987. /**
  9988. * Filters the NodeList instance down to only nodes matching the given selector.
  9989. * @method filter
  9990. * @param {String} selector The selector to filter against
  9991. * @return {NodeList} NodeList containing the updated collection
  9992. * @see Selector
  9993. */
  9994. filter: function(selector) {
  9995. return Y.all(Y.Selector.filter(this._nodes, selector));
  9996. },
  9997. /**
  9998. * Creates a new NodeList containing all nodes at every n indices, where
  9999. * remainder n % index equals r.
  10000. * (zero-based index).
  10001. * @method modulus
  10002. * @param {Int} n The offset to use (return every nth node)
  10003. * @param {Int} r An optional remainder to use with the modulus operation (defaults to zero)
  10004. * @return {NodeList} NodeList containing the updated collection
  10005. */
  10006. modulus: function(n, r) {
  10007. r = r || 0;
  10008. var nodes = [];
  10009. NodeList.each(this, function(node, i) {
  10010. if (i % n === r) {
  10011. nodes.push(node);
  10012. }
  10013. });
  10014. return Y.all(nodes);
  10015. },
  10016. /**
  10017. * Creates a new NodeList containing all nodes at odd indices
  10018. * (zero-based index).
  10019. * @method odd
  10020. * @return {NodeList} NodeList containing the updated collection
  10021. */
  10022. odd: function() {
  10023. return this.modulus(2, 1);
  10024. },
  10025. /**
  10026. * Creates a new NodeList containing all nodes at even indices
  10027. * (zero-based index), including zero.
  10028. * @method even
  10029. * @return {NodeList} NodeList containing the updated collection
  10030. */
  10031. even: function() {
  10032. return this.modulus(2);
  10033. },
  10034. destructor: function() {
  10035. },
  10036. /**
  10037. * Reruns the initial query, when created using a selector query
  10038. * @method refresh
  10039. * @chainable
  10040. */
  10041. refresh: function() {
  10042. var doc,
  10043. nodes = this._nodes,
  10044. query = this._query,
  10045. root = this._queryRoot;
  10046. if (query) {
  10047. if (!root) {
  10048. if (nodes && nodes[0] && nodes[0].ownerDocument) {
  10049. root = nodes[0].ownerDocument;
  10050. }
  10051. }
  10052. this._nodes = Y.Selector.query(query, root);
  10053. }
  10054. return this;
  10055. },
  10056. _prepEvtArgs: function(type, fn, context) {
  10057. // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
  10058. var args = Y.Array(arguments, 0, true);
  10059. if (args.length < 2) { // type only (event hash) just add nodes
  10060. args[2] = this._nodes;
  10061. } else {
  10062. args.splice(2, 0, this._nodes);
  10063. }
  10064. args[3] = context || this; // default to NodeList instance as context
  10065. return args;
  10066. },
  10067. /**
  10068. * Applies an event listener to each Node bound to the NodeList.
  10069. * @method on
  10070. * @param {String} type The event being listened for
  10071. * @param {Function} fn The handler to call when the event fires
  10072. * @param {Object} context The context to call the handler with.
  10073. * Default is the NodeList instance.
  10074. * @param {Object} context The context to call the handler with.
  10075. * param {mixed} arg* 0..n additional arguments to supply to the subscriber
  10076. * when the event fires.
  10077. * @return {Object} Returns an event handle that can later be use to detach().
  10078. * @see Event.on
  10079. */
  10080. on: function(type, fn, context) {
  10081. return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
  10082. },
  10083. /**
  10084. * Applies an one-time event listener to each Node bound to the NodeList.
  10085. * @method once
  10086. * @param {String} type The event being listened for
  10087. * @param {Function} fn The handler to call when the event fires
  10088. * @param {Object} context The context to call the handler with.
  10089. * Default is the NodeList instance.
  10090. * @return {Object} Returns an event handle that can later be use to detach().
  10091. * @see Event.on
  10092. */
  10093. once: function(type, fn, context) {
  10094. return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
  10095. },
  10096. /**
  10097. * Applies an event listener to each Node bound to the NodeList.
  10098. * The handler is called only after all on() handlers are called
  10099. * and the event is not prevented.
  10100. * @method after
  10101. * @param {String} type The event being listened for
  10102. * @param {Function} fn The handler to call when the event fires
  10103. * @param {Object} context The context to call the handler with.
  10104. * Default is the NodeList instance.
  10105. * @return {Object} Returns an event handle that can later be use to detach().
  10106. * @see Event.on
  10107. */
  10108. after: function(type, fn, context) {
  10109. return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
  10110. },
  10111. /**
  10112. * Returns the current number of items in the NodeList.
  10113. * @method size
  10114. * @return {Int} The number of items in the NodeList.
  10115. */
  10116. size: function() {
  10117. return this._nodes.length;
  10118. },
  10119. /**
  10120. * Determines if the instance is bound to any nodes
  10121. * @method isEmpty
  10122. * @return {Boolean} Whether or not the NodeList is bound to any nodes
  10123. */
  10124. isEmpty: function() {
  10125. return this._nodes.length < 1;
  10126. },
  10127. toString: function() {
  10128. var str = '',
  10129. errorMsg = this[UID] + ': not bound to any nodes',
  10130. nodes = this._nodes,
  10131. node;
  10132. if (nodes && nodes[0]) {
  10133. node = nodes[0];
  10134. str += node[NODE_NAME];
  10135. if (node.id) {
  10136. str += '#' + node.id;
  10137. }
  10138. if (node.className) {
  10139. str += '.' + node.className.replace(' ', '.');
  10140. }
  10141. if (nodes.length > 1) {
  10142. str += '...[' + nodes.length + ' items]';
  10143. }
  10144. }
  10145. return str || errorMsg;
  10146. },
  10147. /**
  10148. * Returns the DOM node bound to the Node instance
  10149. * @method getDOMNodes
  10150. * @return {Array}
  10151. */
  10152. getDOMNodes: function() {
  10153. return this._nodes;
  10154. }
  10155. }, true);
  10156. NodeList.importMethod(Y.Node.prototype, [
  10157. /** Called on each Node instance
  10158. * @method destroy
  10159. * @see Node.destroy
  10160. */
  10161. 'destroy',
  10162. /** Called on each Node instance
  10163. * @method empty
  10164. * @see Node.empty
  10165. */
  10166. 'empty',
  10167. /** Called on each Node instance
  10168. * @method remove
  10169. * @see Node.remove
  10170. */
  10171. 'remove',
  10172. /** Called on each Node instance
  10173. * @method set
  10174. * @see Node.set
  10175. */
  10176. 'set'
  10177. ]);
  10178. // one-off implementation to convert array of Nodes to NodeList
  10179. // e.g. Y.all('input').get('parentNode');
  10180. /** Called on each Node instance
  10181. * @method get
  10182. * @see Node
  10183. */
  10184. NodeList.prototype.get = function(attr) {
  10185. var ret = [],
  10186. nodes = this._nodes,
  10187. isNodeList = false,
  10188. getTemp = NodeList._getTempNode,
  10189. instance,
  10190. val;
  10191. if (nodes[0]) {
  10192. instance = Y.Node._instances[nodes[0]._yuid] || getTemp(nodes[0]);
  10193. val = instance._get(attr);
  10194. if (val && val.nodeType) {
  10195. isNodeList = true;
  10196. }
  10197. }
  10198. Y.Array.each(nodes, function(node) {
  10199. instance = Y.Node._instances[node._yuid];
  10200. if (!instance) {
  10201. instance = getTemp(node);
  10202. }
  10203. val = instance._get(attr);
  10204. if (!isNodeList) { // convert array of Nodes to NodeList
  10205. val = Y.Node.scrubVal(val, instance);
  10206. }
  10207. ret.push(val);
  10208. });
  10209. return (isNodeList) ? Y.all(ret) : ret;
  10210. };
  10211. Y.NodeList = NodeList;
  10212. Y.all = function(nodes) {
  10213. return new NodeList(nodes);
  10214. };
  10215. Y.Node.all = Y.all;
  10216. /**
  10217. * @module node
  10218. * @submodule node-core
  10219. */
  10220. var Y_NodeList = Y.NodeList,
  10221. ArrayProto = Array.prototype,
  10222. ArrayMethods = {
  10223. /** Returns a new NodeList combining the given NodeList(s)
  10224. * @for NodeList
  10225. * @method concat
  10226. * @param {NodeList | Array} valueN Arrays/NodeLists and/or values to
  10227. * concatenate to the resulting NodeList
  10228. * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
  10229. */
  10230. 'concat': 1,
  10231. /** Removes the first last from the NodeList and returns it.
  10232. * @for NodeList
  10233. * @method pop
  10234. * @return {Node} The last item in the NodeList.
  10235. */
  10236. 'pop': 0,
  10237. /** Adds the given Node(s) to the end of the NodeList.
  10238. * @for NodeList
  10239. * @method push
  10240. * @param {Node | DOMNode} nodes One or more nodes to add to the end of the NodeList.
  10241. */
  10242. 'push': 0,
  10243. /** Removes the first item from the NodeList and returns it.
  10244. * @for NodeList
  10245. * @method shift
  10246. * @return {Node} The first item in the NodeList.
  10247. */
  10248. 'shift': 0,
  10249. /** Returns a new NodeList comprising the Nodes in the given range.
  10250. * @for NodeList
  10251. * @method slice
  10252. * @param {Number} begin Zero-based index at which to begin extraction.
  10253. As a negative index, start indicates an offset from the end of the sequence. slice(-2) extracts the second-to-last element and the last element in the sequence.
  10254. * @param {Number} end Zero-based index at which to end extraction. slice extracts up to but not including end.
  10255. slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3).
  10256. As a negative index, end indicates an offset from the end of the sequence. slice(2,-1) extracts the third element through the second-to-last element in the sequence.
  10257. If end is omitted, slice extracts to the end of the sequence.
  10258. * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
  10259. */
  10260. 'slice': 1,
  10261. /** Changes the content of the NodeList, adding new elements while removing old elements.
  10262. * @for NodeList
  10263. * @method splice
  10264. * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
  10265. * @param {Number} howMany An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed. In this case, you should specify at least one new element. If no howMany parameter is specified (second syntax above, which is a SpiderMonkey extension), all elements after index are removed.
  10266. * {Node | DOMNode| element1, ..., elementN
  10267. The elements to add to the array. If you don't specify any elements, splice simply removes elements from the array.
  10268. * @return {NodeList} The element(s) removed.
  10269. */
  10270. 'splice': 1,
  10271. /** Adds the given Node(s) to the beginning of the NodeList.
  10272. * @for NodeList
  10273. * @method push
  10274. * @param {Node | DOMNode} nodes One or more nodes to add to the NodeList.
  10275. */
  10276. 'unshift': 0
  10277. };
  10278. Y.Object.each(ArrayMethods, function(returnNodeList, name) {
  10279. Y_NodeList.prototype[name] = function() {
  10280. var args = [],
  10281. i = 0,
  10282. arg,
  10283. ret;
  10284. while (typeof (arg = arguments[i++]) != 'undefined') { // use DOM nodes/nodeLists
  10285. args.push(arg._node || arg._nodes || arg);
  10286. }
  10287. ret = ArrayProto[name].apply(this._nodes, args);
  10288. if (returnNodeList) {
  10289. ret = Y.all(ret);
  10290. } else {
  10291. ret = Y.Node.scrubVal(ret);
  10292. }
  10293. return ret;
  10294. };
  10295. });
  10296. /**
  10297. * @module node
  10298. * @submodule node-core
  10299. */
  10300. Y.Array.each([
  10301. /**
  10302. * Passes through To DoM method.
  10303. * @for Node
  10304. * @method removeChild
  10305. * @param {HTMLElement | Node} node Node to be removed
  10306. * @return {Node} The removed node
  10307. */
  10308. 'removeChild',
  10309. /**
  10310. * Passes through To DoM method.
  10311. * @method hasChildNodes
  10312. * @return {Boolean} Whether or not the node has any childNodes
  10313. */
  10314. 'hasChildNodes',
  10315. /**
  10316. * Passes through To DoM method.
  10317. * @method cloneNode
  10318. * @param {Boolean} deep Whether or not to perform a deep clone, which includes
  10319. * subtree and attributes
  10320. * @return {Node} The clone
  10321. */
  10322. 'cloneNode',
  10323. /**
  10324. * Passes through To DoM method.
  10325. * @method hasAttribute
  10326. * @param {String} attribute The attribute to test for
  10327. * @return {Boolean} Whether or not the attribute is present
  10328. */
  10329. 'hasAttribute',
  10330. /**
  10331. * Passes through To DoM method.
  10332. * @method removeAttribute
  10333. * @param {String} attribute The attribute to be removed
  10334. * @chainable
  10335. */
  10336. 'removeAttribute',
  10337. /**
  10338. * Passes through To DoM method.
  10339. * @method scrollIntoView
  10340. * @chainable
  10341. */
  10342. 'scrollIntoView',
  10343. /**
  10344. * Passes through To DoM method.
  10345. * @method getElementsByTagName
  10346. * @param {String} tagName The tagName to collect
  10347. * @return {NodeList} A NodeList representing the HTMLCollection
  10348. */
  10349. 'getElementsByTagName',
  10350. /**
  10351. * Passes through To DoM method.
  10352. * @method focus
  10353. * @chainable
  10354. */
  10355. 'focus',
  10356. /**
  10357. * Passes through To DoM method.
  10358. * @method blur
  10359. * @chainable
  10360. */
  10361. 'blur',
  10362. /**
  10363. * Passes through To DoM method.
  10364. * Only valid on FORM elements
  10365. * @method submit
  10366. * @chainable
  10367. */
  10368. 'submit',
  10369. /**
  10370. * Passes through To DoM method.
  10371. * Only valid on FORM elements
  10372. * @method reset
  10373. * @chainable
  10374. */
  10375. 'reset',
  10376. /**
  10377. * Passes through To DoM method.
  10378. * @method select
  10379. * @chainable
  10380. */
  10381. 'select',
  10382. /**
  10383. * Passes through To DoM method.
  10384. * Only valid on TABLE elements
  10385. * @method createCaption
  10386. * @chainable
  10387. */
  10388. 'createCaption'
  10389. ], function(method) {
  10390. Y.log('adding: ' + method, 'info', 'node');
  10391. Y.Node.prototype[method] = function(arg1, arg2, arg3) {
  10392. var ret = this.invoke(method, arg1, arg2, arg3);
  10393. return ret;
  10394. };
  10395. });
  10396. Y.Node.importMethod(Y.DOM, [
  10397. /**
  10398. * Determines whether the node is an ancestor of another HTML element in the DOM hierarchy.
  10399. * @method contains
  10400. * @param {Node | HTMLElement} needle The possible node or descendent
  10401. * @return {Boolean} Whether or not this node is the needle its ancestor
  10402. */
  10403. 'contains',
  10404. /**
  10405. * Allows setting attributes on DOM nodes, normalizing in some cases.
  10406. * This passes through to the DOM node, allowing for custom attributes.
  10407. * @method setAttribute
  10408. * @for Node
  10409. * @for NodeList
  10410. * @chainable
  10411. * @param {string} name The attribute name
  10412. * @param {string} value The value to set
  10413. */
  10414. 'setAttribute',
  10415. /**
  10416. * Allows getting attributes on DOM nodes, normalizing in some cases.
  10417. * This passes through to the DOM node, allowing for custom attributes.
  10418. * @method getAttribute
  10419. * @for Node
  10420. * @for NodeList
  10421. * @param {string} name The attribute name
  10422. * @return {string} The attribute value
  10423. */
  10424. 'getAttribute',
  10425. /**
  10426. * Wraps the given HTML around the node.
  10427. * @method wrap
  10428. * @param {String} html The markup to wrap around the node.
  10429. * @chainable
  10430. * @for Node
  10431. */
  10432. 'wrap',
  10433. /**
  10434. * Removes the node's parent node.
  10435. * @method unwrap
  10436. * @chainable
  10437. */
  10438. 'unwrap',
  10439. /**
  10440. * Applies a unique ID to the node if none exists
  10441. * @method generateID
  10442. * @return {String} The existing or generated ID
  10443. */
  10444. 'generateID'
  10445. ]);
  10446. Y.NodeList.importMethod(Y.Node.prototype, [
  10447. /**
  10448. * Allows getting attributes on DOM nodes, normalizing in some cases.
  10449. * This passes through to the DOM node, allowing for custom attributes.
  10450. * @method getAttribute
  10451. * @see Node
  10452. * @for NodeList
  10453. * @param {string} name The attribute name
  10454. * @return {string} The attribute value
  10455. */
  10456. 'getAttribute',
  10457. /**
  10458. * Allows setting attributes on DOM nodes, normalizing in some cases.
  10459. * This passes through to the DOM node, allowing for custom attributes.
  10460. * @method setAttribute
  10461. * @see Node
  10462. * @for NodeList
  10463. * @chainable
  10464. * @param {string} name The attribute name
  10465. * @param {string} value The value to set
  10466. */
  10467. 'setAttribute',
  10468. /**
  10469. * Allows for removing attributes on DOM nodes.
  10470. * This passes through to the DOM node, allowing for custom attributes.
  10471. * @method removeAttribute
  10472. * @see Node
  10473. * @for NodeList
  10474. * @param {string} name The attribute to remove
  10475. */
  10476. 'removeAttribute',
  10477. /**
  10478. * Removes the parent node from node in the list.
  10479. * @method unwrap
  10480. * @chainable
  10481. */
  10482. 'unwrap',
  10483. /**
  10484. * Wraps the given HTML around each node.
  10485. * @method wrap
  10486. * @param {String} html The markup to wrap around the node.
  10487. * @chainable
  10488. */
  10489. 'wrap',
  10490. /**
  10491. * Applies a unique ID to each node if none exists
  10492. * @method generateID
  10493. * @return {String} The existing or generated ID
  10494. */
  10495. 'generateID'
  10496. ]);
  10497. }, '3.4.0' ,{requires:['dom-core', 'selector']});
  10498. YUI.add('node-base', function(Y) {
  10499. /**
  10500. * @module node
  10501. * @submodule node-base
  10502. */
  10503. var methods = [
  10504. /**
  10505. * Determines whether each node has the given className.
  10506. * @method hasClass
  10507. * @for Node
  10508. * @param {String} className the class name to search for
  10509. * @return {Boolean} Whether or not the element has the specified class
  10510. */
  10511. 'hasClass',
  10512. /**
  10513. * Adds a class name to each node.
  10514. * @method addClass
  10515. * @param {String} className the class name to add to the node's class attribute
  10516. * @chainable
  10517. */
  10518. 'addClass',
  10519. /**
  10520. * Removes a class name from each node.
  10521. * @method removeClass
  10522. * @param {String} className the class name to remove from the node's class attribute
  10523. * @chainable
  10524. */
  10525. 'removeClass',
  10526. /**
  10527. * Replace a class with another class for each node.
  10528. * If no oldClassName is present, the newClassName is simply added.
  10529. * @method replaceClass
  10530. * @param {String} oldClassName the class name to be replaced
  10531. * @param {String} newClassName the class name that will be replacing the old class name
  10532. * @chainable
  10533. */
  10534. 'replaceClass',
  10535. /**
  10536. * If the className exists on the node it is removed, if it doesn't exist it is added.
  10537. * @method toggleClass
  10538. * @param {String} className the class name to be toggled
  10539. * @param {Boolean} force Option to force adding or removing the class.
  10540. * @chainable
  10541. */
  10542. 'toggleClass'
  10543. ];
  10544. Y.Node.importMethod(Y.DOM, methods);
  10545. /**
  10546. * Determines whether each node has the given className.
  10547. * @method hasClass
  10548. * @see Node.hasClass
  10549. * @for NodeList
  10550. * @param {String} className the class name to search for
  10551. * @return {Array} An array of booleans for each node bound to the NodeList.
  10552. */
  10553. /**
  10554. * Adds a class name to each node.
  10555. * @method addClass
  10556. * @see Node.addClass
  10557. * @param {String} className the class name to add to the node's class attribute
  10558. * @chainable
  10559. */
  10560. /**
  10561. * Removes a class name from each node.
  10562. * @method removeClass
  10563. * @see Node.removeClass
  10564. * @param {String} className the class name to remove from the node's class attribute
  10565. * @chainable
  10566. */
  10567. /**
  10568. * Replace a class with another class for each node.
  10569. * If no oldClassName is present, the newClassName is simply added.
  10570. * @method replaceClass
  10571. * @see Node.replaceClass
  10572. * @param {String} oldClassName the class name to be replaced
  10573. * @param {String} newClassName the class name that will be replacing the old class name
  10574. * @chainable
  10575. */
  10576. /**
  10577. * If the className exists on the node it is removed, if it doesn't exist it is added.
  10578. * @method toggleClass
  10579. * @see Node.toggleClass
  10580. * @param {String} className the class name to be toggled
  10581. * @chainable
  10582. */
  10583. Y.NodeList.importMethod(Y.Node.prototype, methods);
  10584. /**
  10585. * @module node
  10586. * @submodule node-base
  10587. */
  10588. var Y_Node = Y.Node,
  10589. Y_DOM = Y.DOM;
  10590. /**
  10591. * Returns a new dom node using the provided markup string.
  10592. * @method create
  10593. * @static
  10594. * @param {String} html The markup used to create the element
  10595. * @param {HTMLDocument} doc An optional document context
  10596. * @return {Node} A Node instance bound to a DOM node or fragment
  10597. * @for Node
  10598. */
  10599. Y_Node.create = function(html, doc) {
  10600. if (doc && doc._node) {
  10601. doc = doc._node;
  10602. }
  10603. return Y.one(Y_DOM.create(html, doc));
  10604. };
  10605. Y.mix(Y_Node.prototype, {
  10606. /**
  10607. * Creates a new Node using the provided markup string.
  10608. * @method create
  10609. * @param {String} html The markup used to create the element
  10610. * @param {HTMLDocument} doc An optional document context
  10611. * @return {Node} A Node instance bound to a DOM node or fragment
  10612. */
  10613. create: Y_Node.create,
  10614. /**
  10615. * Inserts the content before the reference node.
  10616. * @method insert
  10617. * @param {String | Y.Node | HTMLElement | Y.NodeList | HTMLCollection} content The content to insert
  10618. * @param {Int | Y.Node | HTMLElement | String} where The position to insert at.
  10619. * Possible "where" arguments
  10620. * <dl>
  10621. * <dt>Y.Node</dt>
  10622. * <dd>The Node to insert before</dd>
  10623. * <dt>HTMLElement</dt>
  10624. * <dd>The element to insert before</dd>
  10625. * <dt>Int</dt>
  10626. * <dd>The index of the child element to insert before</dd>
  10627. * <dt>"replace"</dt>
  10628. * <dd>Replaces the existing HTML</dd>
  10629. * <dt>"before"</dt>
  10630. * <dd>Inserts before the existing HTML</dd>
  10631. * <dt>"before"</dt>
  10632. * <dd>Inserts content before the node</dd>
  10633. * <dt>"after"</dt>
  10634. * <dd>Inserts content after the node</dd>
  10635. * </dl>
  10636. * @chainable
  10637. */
  10638. insert: function(content, where) {
  10639. this._insert(content, where);
  10640. return this;
  10641. },
  10642. _insert: function(content, where) {
  10643. var node = this._node,
  10644. ret = null;
  10645. if (typeof where == 'number') { // allow index
  10646. where = this._node.childNodes[where];
  10647. } else if (where && where._node) { // Node
  10648. where = where._node;
  10649. }
  10650. if (content && typeof content != 'string') { // allow Node or NodeList/Array instances
  10651. content = content._node || content._nodes || content;
  10652. }
  10653. ret = Y_DOM.addHTML(node, content, where);
  10654. return ret;
  10655. },
  10656. /**
  10657. * Inserts the content as the firstChild of the node.
  10658. * @method prepend
  10659. * @param {String | Y.Node | HTMLElement} content The content to insert
  10660. * @chainable
  10661. */
  10662. prepend: function(content) {
  10663. return this.insert(content, 0);
  10664. },
  10665. /**
  10666. * Inserts the content as the lastChild of the node.
  10667. * @method append
  10668. * @param {String | Y.Node | HTMLElement} content The content to insert
  10669. * @chainable
  10670. */
  10671. append: function(content) {
  10672. return this.insert(content, null);
  10673. },
  10674. /**
  10675. * @method appendChild
  10676. * @param {String | HTMLElement | Node} node Node to be appended
  10677. * @return {Node} The appended node
  10678. */
  10679. appendChild: function(node) {
  10680. return Y_Node.scrubVal(this._insert(node));
  10681. },
  10682. /**
  10683. * @method insertBefore
  10684. * @param {String | HTMLElement | Node} newNode Node to be appended
  10685. * @param {HTMLElement | Node} refNode Node to be inserted before
  10686. * @return {Node} The inserted node
  10687. */
  10688. insertBefore: function(newNode, refNode) {
  10689. return Y.Node.scrubVal(this._insert(newNode, refNode));
  10690. },
  10691. /**
  10692. * Appends the node to the given node.
  10693. * @method appendTo
  10694. * @param {Y.Node | HTMLElement} node The node to append to
  10695. * @chainable
  10696. */
  10697. appendTo: function(node) {
  10698. Y.one(node).append(this);
  10699. return this;
  10700. },
  10701. /**
  10702. * Replaces the node's current content with the content.
  10703. * @method setContent
  10704. * @param {String | Y.Node | HTMLElement | Y.NodeList | HTMLCollection} content The content to insert
  10705. * @chainable
  10706. */
  10707. setContent: function(content) {
  10708. this._insert(content, 'replace');
  10709. return this;
  10710. },
  10711. /**
  10712. * Returns the node's current content (e.g. innerHTML)
  10713. * @method getContent
  10714. * @return {String} The current content
  10715. */
  10716. getContent: function(content) {
  10717. return this.get('innerHTML');
  10718. }
  10719. });
  10720. Y.NodeList.importMethod(Y.Node.prototype, [
  10721. /**
  10722. * Called on each Node instance
  10723. * @for NodeList
  10724. * @method append
  10725. * @see Node.append
  10726. */
  10727. 'append',
  10728. /** Called on each Node instance
  10729. * @method insert
  10730. * @see Node.insert
  10731. */
  10732. 'insert',
  10733. /**
  10734. * Called on each Node instance
  10735. * @for NodeList
  10736. * @method appendChild
  10737. * @see Node.appendChild
  10738. */
  10739. 'appendChild',
  10740. /** Called on each Node instance
  10741. * @method insertBefore
  10742. * @see Node.insertBefore
  10743. */
  10744. 'insertBefore',
  10745. /** Called on each Node instance
  10746. * @method prepend
  10747. * @see Node.prepend
  10748. */
  10749. 'prepend',
  10750. /** Called on each Node instance
  10751. * @method setContent
  10752. * @see Node.setContent
  10753. */
  10754. 'setContent',
  10755. /** Called on each Node instance
  10756. * @method getContent
  10757. * @see Node.getContent
  10758. */
  10759. 'getContent'
  10760. ]);
  10761. /**
  10762. * @module node
  10763. * @submodule node-base
  10764. */
  10765. var Y_Node = Y.Node,
  10766. Y_DOM = Y.DOM;
  10767. /**
  10768. * Static collection of configuration attributes for special handling
  10769. * @property ATTRS
  10770. * @static
  10771. * @type object
  10772. */
  10773. Y_Node.ATTRS = {
  10774. /**
  10775. * Allows for getting and setting the text of an element.
  10776. * Formatting is preserved and special characters are treated literally.
  10777. * @config text
  10778. * @type String
  10779. */
  10780. text: {
  10781. getter: function() {
  10782. return Y_DOM.getText(this._node);
  10783. },
  10784. setter: function(content) {
  10785. Y_DOM.setText(this._node, content);
  10786. return content;
  10787. }
  10788. },
  10789. /**
  10790. * Allows for getting and setting the text of an element.
  10791. * Formatting is preserved and special characters are treated literally.
  10792. * @config for
  10793. * @type String
  10794. */
  10795. 'for': {
  10796. getter: function() {
  10797. return Y_DOM.getAttribute(this._node, 'for');
  10798. },
  10799. setter: function(val) {
  10800. Y_DOM.setAttribute(this._node, 'for', val);
  10801. return val;
  10802. }
  10803. },
  10804. 'options': {
  10805. getter: function() {
  10806. return this._node.getElementsByTagName('option');
  10807. }
  10808. },
  10809. /**
  10810. * Returns a NodeList instance of all HTMLElement children.
  10811. * @readOnly
  10812. * @config children
  10813. * @type NodeList
  10814. */
  10815. 'children': {
  10816. getter: function() {
  10817. var node = this._node,
  10818. children = node.children,
  10819. childNodes, i, len;
  10820. if (!children) {
  10821. childNodes = node.childNodes;
  10822. children = [];
  10823. for (i = 0, len = childNodes.length; i < len; ++i) {
  10824. if (childNodes[i][TAG_NAME]) {
  10825. children[children.length] = childNodes[i];
  10826. }
  10827. }
  10828. }
  10829. return Y.all(children);
  10830. }
  10831. },
  10832. value: {
  10833. getter: function() {
  10834. return Y_DOM.getValue(this._node);
  10835. },
  10836. setter: function(val) {
  10837. Y_DOM.setValue(this._node, val);
  10838. return val;
  10839. }
  10840. }
  10841. };
  10842. Y.Node.importMethod(Y.DOM, [
  10843. /**
  10844. * Allows setting attributes on DOM nodes, normalizing in some cases.
  10845. * This passes through to the DOM node, allowing for custom attributes.
  10846. * @method setAttribute
  10847. * @for Node
  10848. * @for NodeList
  10849. * @chainable
  10850. * @param {string} name The attribute name
  10851. * @param {string} value The value to set
  10852. */
  10853. 'setAttribute',
  10854. /**
  10855. * Allows getting attributes on DOM nodes, normalizing in some cases.
  10856. * This passes through to the DOM node, allowing for custom attributes.
  10857. * @method getAttribute
  10858. * @for Node
  10859. * @for NodeList
  10860. * @param {string} name The attribute name
  10861. * @return {string} The attribute value
  10862. */
  10863. 'getAttribute'
  10864. ]);
  10865. /**
  10866. * @module node
  10867. * @submodule node-base
  10868. */
  10869. var Y_Node = Y.Node;
  10870. var Y_NodeList = Y.NodeList;
  10871. /**
  10872. * List of events that route To DoM events
  10873. * @static
  10874. * @property DOM_EVENTS
  10875. * @for Node
  10876. */
  10877. Y_Node.DOM_EVENTS = {
  10878. abort: 1,
  10879. beforeunload: 1,
  10880. blur: 1,
  10881. change: 1,
  10882. click: 1,
  10883. close: 1,
  10884. command: 1,
  10885. contextmenu: 1,
  10886. dblclick: 1,
  10887. DOMMouseScroll: 1,
  10888. drag: 1,
  10889. dragstart: 1,
  10890. dragenter: 1,
  10891. dragover: 1,
  10892. dragleave: 1,
  10893. dragend: 1,
  10894. drop: 1,
  10895. error: 1,
  10896. focus: 1,
  10897. key: 1,
  10898. keydown: 1,
  10899. keypress: 1,
  10900. keyup: 1,
  10901. load: 1,
  10902. message: 1,
  10903. mousedown: 1,
  10904. mouseenter: 1,
  10905. mouseleave: 1,
  10906. mousemove: 1,
  10907. mousemultiwheel: 1,
  10908. mouseout: 1,
  10909. mouseover: 1,
  10910. mouseup: 1,
  10911. mousewheel: 1,
  10912. orientationchange: 1,
  10913. reset: 1,
  10914. resize: 1,
  10915. select: 1,
  10916. selectstart: 1,
  10917. submit: 1,
  10918. scroll: 1,
  10919. textInput: 1,
  10920. unload: 1
  10921. };
  10922. // Add custom event adaptors to this list. This will make it so
  10923. // that delegate, key, available, contentready, etc all will
  10924. // be available through Node.on
  10925. Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins);
  10926. Y.augment(Y_Node, Y.EventTarget);
  10927. Y.mix(Y_Node.prototype, {
  10928. /**
  10929. * Removes event listeners from the node and (optionally) its subtree
  10930. * @method purge
  10931. * @param {Boolean} recurse (optional) Whether or not to remove listeners from the
  10932. * node's subtree
  10933. * @param {String} type (optional) Only remove listeners of the specified type
  10934. * @chainable
  10935. *
  10936. */
  10937. purge: function(recurse, type) {
  10938. Y.Event.purgeElement(this._node, recurse, type);
  10939. return this;
  10940. }
  10941. });
  10942. Y.mix(Y.NodeList.prototype, {
  10943. _prepEvtArgs: function(type, fn, context) {
  10944. // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
  10945. var args = Y.Array(arguments, 0, true);
  10946. if (args.length < 2) { // type only (event hash) just add nodes
  10947. args[2] = this._nodes;
  10948. } else {
  10949. args.splice(2, 0, this._nodes);
  10950. }
  10951. args[3] = context || this; // default to NodeList instance as context
  10952. return args;
  10953. },
  10954. /**
  10955. * Applies an event listener to each Node bound to the NodeList.
  10956. * @method on
  10957. * @param {String} type The event being listened for
  10958. * @param {Function} fn The handler to call when the event fires
  10959. * @param {Object} context The context to call the handler with.
  10960. * Default is the NodeList instance.
  10961. * @param {Object} context The context to call the handler with.
  10962. * param {mixed} arg* 0..n additional arguments to supply to the subscriber
  10963. * when the event fires.
  10964. * @return {Object} Returns an event handle that can later be use to detach().
  10965. * @see Event.on
  10966. * @for NodeList
  10967. */
  10968. on: function(type, fn, context) {
  10969. return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
  10970. },
  10971. /**
  10972. * Applies an one-time event listener to each Node bound to the NodeList.
  10973. * @method once
  10974. * @param {String} type The event being listened for
  10975. * @param {Function} fn The handler to call when the event fires
  10976. * @param {Object} context The context to call the handler with.
  10977. * Default is the NodeList instance.
  10978. * @return {Object} Returns an event handle that can later be use to detach().
  10979. * @see Event.on
  10980. */
  10981. once: function(type, fn, context) {
  10982. return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
  10983. },
  10984. /**
  10985. * Applies an event listener to each Node bound to the NodeList.
  10986. * The handler is called only after all on() handlers are called
  10987. * and the event is not prevented.
  10988. * @method after
  10989. * @param {String} type The event being listened for
  10990. * @param {Function} fn The handler to call when the event fires
  10991. * @param {Object} context The context to call the handler with.
  10992. * Default is the NodeList instance.
  10993. * @return {Object} Returns an event handle that can later be use to detach().
  10994. * @see Event.on
  10995. */
  10996. after: function(type, fn, context) {
  10997. return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
  10998. },
  10999. /**
  11000. * Applies an one-time event listener to each Node bound to the NodeList
  11001. * that will be called only after all on() handlers are called and the
  11002. * event is not prevented.
  11003. *
  11004. * @method onceAfter
  11005. * @param {String} type The event being listened for
  11006. * @param {Function} fn The handler to call when the event fires
  11007. * @param {Object} context The context to call the handler with.
  11008. * Default is the NodeList instance.
  11009. * @return {Object} Returns an event handle that can later be use to detach().
  11010. * @see Event.on
  11011. */
  11012. onceAfter: function(type, fn, context) {
  11013. return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments));
  11014. }
  11015. });
  11016. Y_NodeList.importMethod(Y.Node.prototype, [
  11017. /**
  11018. * Called on each Node instance
  11019. * @method detach
  11020. * @see Node.detach
  11021. */
  11022. 'detach',
  11023. /** Called on each Node instance
  11024. * @method detachAll
  11025. * @see Node.detachAll
  11026. */
  11027. 'detachAll'
  11028. ]);
  11029. Y.mix(Y.Node.ATTRS, {
  11030. offsetHeight: {
  11031. setter: function(h) {
  11032. Y.DOM.setHeight(this._node, h);
  11033. return h;
  11034. },
  11035. getter: function() {
  11036. return this._node.offsetHeight;
  11037. }
  11038. },
  11039. offsetWidth: {
  11040. setter: function(w) {
  11041. Y.DOM.setWidth(this._node, w);
  11042. return w;
  11043. },
  11044. getter: function() {
  11045. return this._node.offsetWidth;
  11046. }
  11047. }
  11048. });
  11049. Y.mix(Y.Node.prototype, {
  11050. sizeTo: function(w, h) {
  11051. var node;
  11052. if (arguments.length < 2) {
  11053. node = Y.one(w);
  11054. w = node.get('offsetWidth');
  11055. h = node.get('offsetHeight');
  11056. }
  11057. this.setAttrs({
  11058. offsetWidth: w,
  11059. offsetHeight: h
  11060. });
  11061. }
  11062. });
  11063. /**
  11064. * @module node
  11065. * @submodule node-base
  11066. */
  11067. var Y_Node = Y.Node;
  11068. Y.mix(Y_Node.prototype, {
  11069. /**
  11070. * Makes the node visible.
  11071. * If the "transition" module is loaded, show optionally
  11072. * animates the showing of the node using either the default
  11073. * transition effect ('fadeIn'), or the given named effect.
  11074. * @method show
  11075. * @for Node
  11076. * @param {String} name A named Transition effect to use as the show effect.
  11077. * @param {Object} config Options to use with the transition.
  11078. * @param {Function} callback An optional function to run after the transition completes.
  11079. * @chainable
  11080. */
  11081. show: function(callback) {
  11082. callback = arguments[arguments.length - 1];
  11083. this.toggleView(true, callback);
  11084. return this;
  11085. },
  11086. /**
  11087. * The implementation for showing nodes.
  11088. * Default is to toggle the style.display property.
  11089. * @method _show
  11090. * @protected
  11091. * @chainable
  11092. */
  11093. _show: function() {
  11094. this.setStyle('display', '');
  11095. },
  11096. _isHidden: function() {
  11097. return Y.DOM.getStyle(this._node, 'display') === 'none';
  11098. },
  11099. toggleView: function(on, callback) {
  11100. this._toggleView.apply(this, arguments);
  11101. },
  11102. _toggleView: function(on, callback) {
  11103. callback = arguments[arguments.length - 1];
  11104. // base on current state if not forcing
  11105. if (typeof on != 'boolean') {
  11106. on = (this._isHidden()) ? 1 : 0;
  11107. }
  11108. if (on) {
  11109. this._show();
  11110. } else {
  11111. this._hide();
  11112. }
  11113. if (typeof callback == 'function') {
  11114. callback.call(this);
  11115. }
  11116. return this;
  11117. },
  11118. /**
  11119. * Hides the node.
  11120. * If the "transition" module is loaded, hide optionally
  11121. * animates the hiding of the node using either the default
  11122. * transition effect ('fadeOut'), or the given named effect.
  11123. * @method hide
  11124. * @param {String} name A named Transition effect to use as the show effect.
  11125. * @param {Object} config Options to use with the transition.
  11126. * @param {Function} callback An optional function to run after the transition completes.
  11127. * @chainable
  11128. */
  11129. hide: function(callback) {
  11130. callback = arguments[arguments.length - 1];
  11131. this.toggleView(false, callback);
  11132. return this;
  11133. },
  11134. /**
  11135. * The implementation for hiding nodes.
  11136. * Default is to toggle the style.display property.
  11137. * @method _hide
  11138. * @protected
  11139. * @chainable
  11140. */
  11141. _hide: function() {
  11142. this.setStyle('display', 'none');
  11143. }
  11144. });
  11145. Y.NodeList.importMethod(Y.Node.prototype, [
  11146. /**
  11147. * Makes each node visible.
  11148. * If the "transition" module is loaded, show optionally
  11149. * animates the showing of the node using either the default
  11150. * transition effect ('fadeIn'), or the given named effect.
  11151. * @method show
  11152. * @param {String} name A named Transition effect to use as the show effect.
  11153. * @param {Object} config Options to use with the transition.
  11154. * @param {Function} callback An optional function to run after the transition completes.
  11155. * @for NodeList
  11156. * @chainable
  11157. */
  11158. 'show',
  11159. /**
  11160. * Hides each node.
  11161. * If the "transition" module is loaded, hide optionally
  11162. * animates the hiding of the node using either the default
  11163. * transition effect ('fadeOut'), or the given named effect.
  11164. * @method hide
  11165. * @param {String} name A named Transition effect to use as the show effect.
  11166. * @param {Object} config Options to use with the transition.
  11167. * @param {Function} callback An optional function to run after the transition completes.
  11168. * @chainable
  11169. */
  11170. 'hide',
  11171. 'toggleView'
  11172. ]);
  11173. if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8
  11174. Y.Node.prototype.hasAttribute = function(attr) {
  11175. if (attr === 'value') {
  11176. if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML
  11177. return true;
  11178. }
  11179. }
  11180. return !!(this._node.attributes[attr] &&
  11181. this._node.attributes[attr].specified);
  11182. };
  11183. }
  11184. // IE throws an error when calling focus() on an element that's invisible, not
  11185. // displayed, or disabled.
  11186. Y.Node.prototype.focus = function () {
  11187. try {
  11188. this._node.focus();
  11189. } catch (e) {
  11190. Y.log('error focusing node: ' + e.toString(), 'error', 'node');
  11191. }
  11192. return this;
  11193. };
  11194. // IE throws error when setting input.type = 'hidden',
  11195. // input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
  11196. Y.Node.ATTRS.type = {
  11197. setter: function(val) {
  11198. if (val === 'hidden') {
  11199. try {
  11200. this._node.type = 'hidden';
  11201. } catch(e) {
  11202. this.setStyle('display', 'none');
  11203. this._inputType = 'hidden';
  11204. }
  11205. } else {
  11206. try { // IE errors when changing the type from "hidden'
  11207. this._node.type = val;
  11208. } catch (e) {
  11209. Y.log('error setting type: ' + val, 'info', 'node');
  11210. }
  11211. }
  11212. return val;
  11213. },
  11214. getter: function() {
  11215. return this._inputType || this._node.type;
  11216. },
  11217. _bypassProxy: true // don't update DOM when using with Attribute
  11218. };
  11219. if (Y.config.doc.createElement('form').elements.nodeType) {
  11220. // IE: elements collection is also FORM node which trips up scrubVal.
  11221. Y.Node.ATTRS.elements = {
  11222. getter: function() {
  11223. return this.all('input, textarea, button, select');
  11224. }
  11225. };
  11226. }
  11227. }, '3.4.0' ,{requires:['dom-base', 'node-core', 'event-base']});
  11228. (function () {
  11229. var GLOBAL_ENV = YUI.Env;
  11230. if (!GLOBAL_ENV._ready) {
  11231. GLOBAL_ENV._ready = function() {
  11232. GLOBAL_ENV.DOMReady = true;
  11233. GLOBAL_ENV.remove(YUI.config.doc, 'DOMContentLoaded', GLOBAL_ENV._ready);
  11234. };
  11235. GLOBAL_ENV.add(YUI.config.doc, 'DOMContentLoaded', GLOBAL_ENV._ready);
  11236. }
  11237. })();
  11238. YUI.add('event-base', function(Y) {
  11239. /*
  11240. * DOM event listener abstraction layer
  11241. * @module event
  11242. * @submodule event-base
  11243. */
  11244. /**
  11245. * The domready event fires at the moment the browser's DOM is
  11246. * usable. In most cases, this is before images are fully
  11247. * downloaded, allowing you to provide a more responsive user
  11248. * interface.
  11249. *
  11250. * In YUI 3, domready subscribers will be notified immediately if
  11251. * that moment has already passed when the subscription is created.
  11252. *
  11253. * One exception is if the yui.js file is dynamically injected into
  11254. * the page. If this is done, you must tell the YUI instance that
  11255. * you did this in order for DOMReady (and window load events) to
  11256. * fire normally. That configuration option is 'injected' -- set
  11257. * it to true if the yui.js script is not included inline.
  11258. *
  11259. * This method is part of the 'event-ready' module, which is a
  11260. * submodule of 'event'.
  11261. *
  11262. * @event domready
  11263. * @for YUI
  11264. */
  11265. Y.publish('domready', {
  11266. fireOnce: true,
  11267. async: true
  11268. });
  11269. if (YUI.Env.DOMReady) {
  11270. Y.fire('domready');
  11271. } else {
  11272. Y.Do.before(function() { Y.fire('domready'); }, YUI.Env, '_ready');
  11273. }
  11274. /**
  11275. * Custom event engine, DOM event listener abstraction layer, synthetic DOM
  11276. * events.
  11277. * @module event
  11278. * @submodule event-base
  11279. */
  11280. /**
  11281. * Wraps a DOM event, properties requiring browser abstraction are
  11282. * fixed here. Provids a security layer when required.
  11283. * @class DOMEventFacade
  11284. * @param ev {Event} the DOM event
  11285. * @param currentTarget {HTMLElement} the element the listener was attached to
  11286. * @param wrapper {Event.Custom} the custom event wrapper for this DOM event
  11287. */
  11288. var ua = Y.UA,
  11289. EMPTY = {},
  11290. /**
  11291. * webkit key remapping required for Safari < 3.1
  11292. * @property webkitKeymap
  11293. * @private
  11294. */
  11295. webkitKeymap = {
  11296. 63232: 38, // up
  11297. 63233: 40, // down
  11298. 63234: 37, // left
  11299. 63235: 39, // right
  11300. 63276: 33, // page up
  11301. 63277: 34, // page down
  11302. 25: 9, // SHIFT-TAB (Safari provides a different key code in
  11303. // this case, even though the shiftKey modifier is set)
  11304. 63272: 46, // delete
  11305. 63273: 36, // home
  11306. 63275: 35 // end
  11307. },
  11308. /**
  11309. * Returns a wrapped node. Intended to be used on event targets,
  11310. * so it will return the node's parent if the target is a text
  11311. * node.
  11312. *
  11313. * If accessing a property of the node throws an error, this is
  11314. * probably the anonymous div wrapper Gecko adds inside text
  11315. * nodes. This likely will only occur when attempting to access
  11316. * the relatedTarget. In this case, we now return null because
  11317. * the anonymous div is completely useless and we do not know
  11318. * what the related target was because we can't even get to
  11319. * the element's parent node.
  11320. *
  11321. * @method resolve
  11322. * @private
  11323. */
  11324. resolve = function(n) {
  11325. if (!n) {
  11326. return n;
  11327. }
  11328. try {
  11329. if (n && 3 == n.nodeType) {
  11330. n = n.parentNode;
  11331. }
  11332. } catch(e) {
  11333. return null;
  11334. }
  11335. return Y.one(n);
  11336. },
  11337. DOMEventFacade = function(ev, currentTarget, wrapper) {
  11338. this._event = ev;
  11339. this._currentTarget = currentTarget;
  11340. this._wrapper = wrapper || EMPTY;
  11341. // if not lazy init
  11342. this.init();
  11343. };
  11344. Y.extend(DOMEventFacade, Object, {
  11345. init: function() {
  11346. var e = this._event,
  11347. overrides = this._wrapper.overrides,
  11348. x = e.pageX,
  11349. y = e.pageY,
  11350. c,
  11351. currentTarget = this._currentTarget;
  11352. this.altKey = e.altKey;
  11353. this.ctrlKey = e.ctrlKey;
  11354. this.metaKey = e.metaKey;
  11355. this.shiftKey = e.shiftKey;
  11356. this.type = (overrides && overrides.type) || e.type;
  11357. this.clientX = e.clientX;
  11358. this.clientY = e.clientY;
  11359. this.pageX = x;
  11360. this.pageY = y;
  11361. c = e.keyCode || e.charCode;
  11362. if (ua.webkit && (c in webkitKeymap)) {
  11363. c = webkitKeymap[c];
  11364. }
  11365. this.keyCode = c;
  11366. this.charCode = c;
  11367. this.which = e.which || e.charCode || c;
  11368. // this.button = e.button;
  11369. this.button = this.which;
  11370. this.target = resolve(e.target);
  11371. this.currentTarget = resolve(currentTarget);
  11372. this.relatedTarget = resolve(e.relatedTarget);
  11373. if (e.type == "mousewheel" || e.type == "DOMMouseScroll") {
  11374. this.wheelDelta = (e.detail) ? (e.detail * -1) : Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
  11375. }
  11376. if (this._touch) {
  11377. this._touch(e, currentTarget, this._wrapper);
  11378. }
  11379. },
  11380. stopPropagation: function() {
  11381. this._event.stopPropagation();
  11382. this._wrapper.stopped = 1;
  11383. this.stopped = 1;
  11384. },
  11385. stopImmediatePropagation: function() {
  11386. var e = this._event;
  11387. if (e.stopImmediatePropagation) {
  11388. e.stopImmediatePropagation();
  11389. } else {
  11390. this.stopPropagation();
  11391. }
  11392. this._wrapper.stopped = 2;
  11393. this.stopped = 2;
  11394. },
  11395. preventDefault: function(returnValue) {
  11396. var e = this._event;
  11397. e.preventDefault();
  11398. e.returnValue = returnValue || false;
  11399. this._wrapper.prevented = 1;
  11400. this.prevented = 1;
  11401. },
  11402. halt: function(immediate) {
  11403. if (immediate) {
  11404. this.stopImmediatePropagation();
  11405. } else {
  11406. this.stopPropagation();
  11407. }
  11408. this.preventDefault();
  11409. }
  11410. });
  11411. DOMEventFacade.resolve = resolve;
  11412. Y.DOM2EventFacade = DOMEventFacade;
  11413. Y.DOMEventFacade = DOMEventFacade;
  11414. /**
  11415. * The native event
  11416. * @property _event
  11417. */
  11418. /**
  11419. * The X location of the event on the page (including scroll)
  11420. * @property pageX
  11421. * @type int
  11422. */
  11423. /**
  11424. * The Y location of the event on the page (including scroll)
  11425. * @property pageY
  11426. * @type int
  11427. */
  11428. /**
  11429. * The keyCode for key events. Uses charCode if keyCode is not available
  11430. * @property keyCode
  11431. * @type int
  11432. */
  11433. /**
  11434. * The charCode for key events. Same as keyCode
  11435. * @property charCode
  11436. * @type int
  11437. */
  11438. /**
  11439. * The button that was pushed.
  11440. * @property button
  11441. * @type int
  11442. */
  11443. /**
  11444. * The button that was pushed. Same as button.
  11445. * @property which
  11446. * @type int
  11447. */
  11448. /**
  11449. * Node reference for the targeted element
  11450. * @propery target
  11451. * @type Node
  11452. */
  11453. /**
  11454. * Node reference for the element that the listener was attached to.
  11455. * @propery currentTarget
  11456. * @type Node
  11457. */
  11458. /**
  11459. * Node reference to the relatedTarget
  11460. * @propery relatedTarget
  11461. * @type Node
  11462. */
  11463. /**
  11464. * Number representing the direction and velocity of the movement of the mousewheel.
  11465. * Negative is down, the higher the number, the faster. Applies to the mousewheel event.
  11466. * @property wheelDelta
  11467. * @type int
  11468. */
  11469. /**
  11470. * Stops the propagation to the next bubble target
  11471. * @method stopPropagation
  11472. */
  11473. /**
  11474. * Stops the propagation to the next bubble target and
  11475. * prevents any additional listeners from being exectued
  11476. * on the current target.
  11477. * @method stopImmediatePropagation
  11478. */
  11479. /**
  11480. * Prevents the event's default behavior
  11481. * @method preventDefault
  11482. * @param returnValue {string} sets the returnValue of the event to this value
  11483. * (rather than the default false value). This can be used to add a customized
  11484. * confirmation query to the beforeunload event).
  11485. */
  11486. /**
  11487. * Stops the event propagation and prevents the default
  11488. * event behavior.
  11489. * @method halt
  11490. * @param immediate {boolean} if true additional listeners
  11491. * on the current target will not be executed
  11492. */
  11493. (function() {
  11494. /**
  11495. * DOM event listener abstraction layer
  11496. * @module event
  11497. * @submodule event-base
  11498. */
  11499. /**
  11500. * The event utility provides functions to add and remove event listeners,
  11501. * event cleansing. It also tries to automatically remove listeners it
  11502. * registers during the unload event.
  11503. *
  11504. * @class Event
  11505. * @static
  11506. */
  11507. Y.Env.evt.dom_wrappers = {};
  11508. Y.Env.evt.dom_map = {};
  11509. var _eventenv = Y.Env.evt,
  11510. config = Y.config,
  11511. win = config.win,
  11512. add = YUI.Env.add,
  11513. remove = YUI.Env.remove,
  11514. onLoad = function() {
  11515. YUI.Env.windowLoaded = true;
  11516. Y.Event._load();
  11517. remove(win, "load", onLoad);
  11518. },
  11519. onUnload = function() {
  11520. Y.Event._unload();
  11521. },
  11522. EVENT_READY = 'domready',
  11523. COMPAT_ARG = '~yui|2|compat~',
  11524. shouldIterate = function(o) {
  11525. try {
  11526. return (o && typeof o !== "string" && Y.Lang.isNumber(o.length) &&
  11527. !o.tagName && !o.alert);
  11528. } catch(ex) {
  11529. Y.log("collection check failure", "warn", "event");
  11530. return false;
  11531. }
  11532. },
  11533. // aliases to support DOM event subscription clean up when the last
  11534. // subscriber is detached. deleteAndClean overrides the DOM event's wrapper
  11535. // CustomEvent _delete method.
  11536. _ceProtoDelete = Y.CustomEvent.prototype._delete,
  11537. _deleteAndClean = function(s) {
  11538. var ret = _ceProtoDelete.apply(this, arguments);
  11539. if (!this.subCount && !this.afterCount) {
  11540. Y.Event._clean(this);
  11541. }
  11542. return ret;
  11543. },
  11544. Event = function() {
  11545. /**
  11546. * True after the onload event has fired
  11547. * @property _loadComplete
  11548. * @type boolean
  11549. * @static
  11550. * @private
  11551. */
  11552. var _loadComplete = false,
  11553. /**
  11554. * The number of times to poll after window.onload. This number is
  11555. * increased if additional late-bound handlers are requested after
  11556. * the page load.
  11557. * @property _retryCount
  11558. * @static
  11559. * @private
  11560. */
  11561. _retryCount = 0,
  11562. /**
  11563. * onAvailable listeners
  11564. * @property _avail
  11565. * @static
  11566. * @private
  11567. */
  11568. _avail = [],
  11569. /**
  11570. * Custom event wrappers for DOM events. Key is
  11571. * 'event:' + Element uid stamp + event type
  11572. * @property _wrappers
  11573. * @type Y.Event.Custom
  11574. * @static
  11575. * @private
  11576. */
  11577. _wrappers = _eventenv.dom_wrappers,
  11578. _windowLoadKey = null,
  11579. /**
  11580. * Custom event wrapper map DOM events. Key is
  11581. * Element uid stamp. Each item is a hash of custom event
  11582. * wrappers as provided in the _wrappers collection. This
  11583. * provides the infrastructure for getListeners.
  11584. * @property _el_events
  11585. * @static
  11586. * @private
  11587. */
  11588. _el_events = _eventenv.dom_map;
  11589. return {
  11590. /**
  11591. * The number of times we should look for elements that are not
  11592. * in the DOM at the time the event is requested after the document
  11593. * has been loaded. The default is 1000@amp;40 ms, so it will poll
  11594. * for 40 seconds or until all outstanding handlers are bound
  11595. * (whichever comes first).
  11596. * @property POLL_RETRYS
  11597. * @type int
  11598. * @static
  11599. * @final
  11600. */
  11601. POLL_RETRYS: 1000,
  11602. /**
  11603. * The poll interval in milliseconds
  11604. * @property POLL_INTERVAL
  11605. * @type int
  11606. * @static
  11607. * @final
  11608. */
  11609. POLL_INTERVAL: 40,
  11610. /**
  11611. * addListener/removeListener can throw errors in unexpected scenarios.
  11612. * These errors are suppressed, the method returns false, and this property
  11613. * is set
  11614. * @property lastError
  11615. * @static
  11616. * @type Error
  11617. */
  11618. lastError: null,
  11619. /**
  11620. * poll handle
  11621. * @property _interval
  11622. * @static
  11623. * @private
  11624. */
  11625. _interval: null,
  11626. /**
  11627. * document readystate poll handle
  11628. * @property _dri
  11629. * @static
  11630. * @private
  11631. */
  11632. _dri: null,
  11633. /**
  11634. * True when the document is initially usable
  11635. * @property DOMReady
  11636. * @type boolean
  11637. * @static
  11638. */
  11639. DOMReady: false,
  11640. /**
  11641. * @method startInterval
  11642. * @static
  11643. * @private
  11644. */
  11645. startInterval: function() {
  11646. if (!Event._interval) {
  11647. Event._interval = setInterval(Event._poll, Event.POLL_INTERVAL);
  11648. }
  11649. },
  11650. /**
  11651. * Executes the supplied callback when the item with the supplied
  11652. * id is found. This is meant to be used to execute behavior as
  11653. * soon as possible as the page loads. If you use this after the
  11654. * initial page load it will poll for a fixed time for the element.
  11655. * The number of times it will poll and the frequency are
  11656. * configurable. By default it will poll for 10 seconds.
  11657. *
  11658. * <p>The callback is executed with a single parameter:
  11659. * the custom object parameter, if provided.</p>
  11660. *
  11661. * @method onAvailable
  11662. *
  11663. * @param {string||string[]} id the id of the element, or an array
  11664. * of ids to look for.
  11665. * @param {function} fn what to execute when the element is found.
  11666. * @param {object} p_obj an optional object to be passed back as
  11667. * a parameter to fn.
  11668. * @param {boolean|object} p_override If set to true, fn will execute
  11669. * in the context of p_obj, if set to an object it
  11670. * will execute in the context of that object
  11671. * @param checkContent {boolean} check child node readiness (onContentReady)
  11672. * @static
  11673. * @deprecated Use Y.on("available")
  11674. */
  11675. // @TODO fix arguments
  11676. onAvailable: function(id, fn, p_obj, p_override, checkContent, compat) {
  11677. var a = Y.Array(id), i, availHandle;
  11678. // Y.log('onAvailable registered for: ' + id);
  11679. for (i=0; i<a.length; i=i+1) {
  11680. _avail.push({
  11681. id: a[i],
  11682. fn: fn,
  11683. obj: p_obj,
  11684. override: p_override,
  11685. checkReady: checkContent,
  11686. compat: compat
  11687. });
  11688. }
  11689. _retryCount = this.POLL_RETRYS;
  11690. // We want the first test to be immediate, but async
  11691. setTimeout(Event._poll, 0);
  11692. availHandle = new Y.EventHandle({
  11693. _delete: function() {
  11694. // set by the event system for lazy DOM listeners
  11695. if (availHandle.handle) {
  11696. availHandle.handle.detach();
  11697. return;
  11698. }
  11699. var i, j;
  11700. // otherwise try to remove the onAvailable listener(s)
  11701. for (i = 0; i < a.length; i++) {
  11702. for (j = 0; j < _avail.length; j++) {
  11703. if (a[i] === _avail[j].id) {
  11704. _avail.splice(j, 1);
  11705. }
  11706. }
  11707. }
  11708. }
  11709. });
  11710. return availHandle;
  11711. },
  11712. /**
  11713. * Works the same way as onAvailable, but additionally checks the
  11714. * state of sibling elements to determine if the content of the
  11715. * available element is safe to modify.
  11716. *
  11717. * <p>The callback is executed with a single parameter:
  11718. * the custom object parameter, if provided.</p>
  11719. *
  11720. * @method onContentReady
  11721. *
  11722. * @param {string} id the id of the element to look for.
  11723. * @param {function} fn what to execute when the element is ready.
  11724. * @param {object} obj an optional object to be passed back as
  11725. * a parameter to fn.
  11726. * @param {boolean|object} override If set to true, fn will execute
  11727. * in the context of p_obj. If an object, fn will
  11728. * exectute in the context of that object
  11729. *
  11730. * @static
  11731. * @deprecated Use Y.on("contentready")
  11732. */
  11733. // @TODO fix arguments
  11734. onContentReady: function(id, fn, obj, override, compat) {
  11735. return Event.onAvailable(id, fn, obj, override, true, compat);
  11736. },
  11737. /**
  11738. * Adds an event listener
  11739. *
  11740. * @method attach
  11741. *
  11742. * @param {String} type The type of event to append
  11743. * @param {Function} fn The method the event invokes
  11744. * @param {String|HTMLElement|Array|NodeList} el An id, an element
  11745. * reference, or a collection of ids and/or elements to assign the
  11746. * listener to.
  11747. * @param {Object} context optional context object
  11748. * @param {Boolean|object} args 0..n arguments to pass to the callback
  11749. * @return {EventHandle} an object to that can be used to detach the listener
  11750. *
  11751. * @static
  11752. */
  11753. attach: function(type, fn, el, context) {
  11754. return Event._attach(Y.Array(arguments, 0, true));
  11755. },
  11756. _createWrapper: function (el, type, capture, compat, facade) {
  11757. var cewrapper,
  11758. ek = Y.stamp(el),
  11759. key = 'event:' + ek + type;
  11760. if (false === facade) {
  11761. key += 'native';
  11762. }
  11763. if (capture) {
  11764. key += 'capture';
  11765. }
  11766. cewrapper = _wrappers[key];
  11767. if (!cewrapper) {
  11768. // create CE wrapper
  11769. cewrapper = Y.publish(key, {
  11770. silent: true,
  11771. bubbles: false,
  11772. contextFn: function() {
  11773. if (compat) {
  11774. return cewrapper.el;
  11775. } else {
  11776. cewrapper.nodeRef = cewrapper.nodeRef || Y.one(cewrapper.el);
  11777. return cewrapper.nodeRef;
  11778. }
  11779. }
  11780. });
  11781. cewrapper.overrides = {};
  11782. // for later removeListener calls
  11783. cewrapper.el = el;
  11784. cewrapper.key = key;
  11785. cewrapper.domkey = ek;
  11786. cewrapper.type = type;
  11787. cewrapper.fn = function(e) {
  11788. cewrapper.fire(Event.getEvent(e, el, (compat || (false === facade))));
  11789. };
  11790. cewrapper.capture = capture;
  11791. if (el == win && type == "load") {
  11792. // window load happens once
  11793. cewrapper.fireOnce = true;
  11794. _windowLoadKey = key;
  11795. }
  11796. cewrapper._delete = _deleteAndClean;
  11797. _wrappers[key] = cewrapper;
  11798. _el_events[ek] = _el_events[ek] || {};
  11799. _el_events[ek][key] = cewrapper;
  11800. add(el, type, cewrapper.fn, capture);
  11801. }
  11802. return cewrapper;
  11803. },
  11804. _attach: function(args, conf) {
  11805. var compat,
  11806. handles, oEl, cewrapper, context,
  11807. fireNow = false, ret,
  11808. type = args[0],
  11809. fn = args[1],
  11810. el = args[2] || win,
  11811. facade = conf && conf.facade,
  11812. capture = conf && conf.capture,
  11813. overrides = conf && conf.overrides;
  11814. if (args[args.length-1] === COMPAT_ARG) {
  11815. compat = true;
  11816. }
  11817. if (!fn || !fn.call) {
  11818. // throw new TypeError(type + " attach call failed, callback undefined");
  11819. Y.log(type + " attach call failed, invalid callback", "error", "event");
  11820. return false;
  11821. }
  11822. // The el argument can be an array of elements or element ids.
  11823. if (shouldIterate(el)) {
  11824. handles=[];
  11825. Y.each(el, function(v, k) {
  11826. args[2] = v;
  11827. handles.push(Event._attach(args.slice(), conf));
  11828. });
  11829. // return (handles.length === 1) ? handles[0] : handles;
  11830. return new Y.EventHandle(handles);
  11831. // If the el argument is a string, we assume it is
  11832. // actually the id of the element. If the page is loaded
  11833. // we convert el to the actual element, otherwise we
  11834. // defer attaching the event until the element is
  11835. // ready
  11836. } else if (Y.Lang.isString(el)) {
  11837. // oEl = (compat) ? Y.DOM.byId(el) : Y.Selector.query(el);
  11838. if (compat) {
  11839. oEl = Y.DOM.byId(el);
  11840. } else {
  11841. oEl = Y.Selector.query(el);
  11842. switch (oEl.length) {
  11843. case 0:
  11844. oEl = null;
  11845. break;
  11846. case 1:
  11847. oEl = oEl[0];
  11848. break;
  11849. default:
  11850. args[2] = oEl;
  11851. return Event._attach(args, conf);
  11852. }
  11853. }
  11854. if (oEl) {
  11855. el = oEl;
  11856. // Not found = defer adding the event until the element is available
  11857. } else {
  11858. // Y.log(el + ' not found');
  11859. ret = Event.onAvailable(el, function() {
  11860. // Y.log('lazy attach: ' + args);
  11861. ret.handle = Event._attach(args, conf);
  11862. }, Event, true, false, compat);
  11863. return ret;
  11864. }
  11865. }
  11866. // Element should be an html element or node
  11867. if (!el) {
  11868. Y.log("unable to attach event " + type, "warn", "event");
  11869. return false;
  11870. }
  11871. if (Y.Node && Y.instanceOf(el, Y.Node)) {
  11872. el = Y.Node.getDOMNode(el);
  11873. }
  11874. cewrapper = Event._createWrapper(el, type, capture, compat, facade);
  11875. if (overrides) {
  11876. Y.mix(cewrapper.overrides, overrides);
  11877. }
  11878. if (el == win && type == "load") {
  11879. // if the load is complete, fire immediately.
  11880. // all subscribers, including the current one
  11881. // will be notified.
  11882. if (YUI.Env.windowLoaded) {
  11883. fireNow = true;
  11884. }
  11885. }
  11886. if (compat) {
  11887. args.pop();
  11888. }
  11889. context = args[3];
  11890. // set context to the Node if not specified
  11891. // ret = cewrapper.on.apply(cewrapper, trimmedArgs);
  11892. ret = cewrapper._on(fn, context, (args.length > 4) ? args.slice(4) : null);
  11893. if (fireNow) {
  11894. cewrapper.fire();
  11895. }
  11896. return ret;
  11897. },
  11898. /**
  11899. * Removes an event listener. Supports the signature the event was bound
  11900. * with, but the preferred way to remove listeners is using the handle
  11901. * that is returned when using Y.on
  11902. *
  11903. * @method detach
  11904. *
  11905. * @param {String} type the type of event to remove.
  11906. * @param {Function} fn the method the event invokes. If fn is
  11907. * undefined, then all event handlers for the type of event are
  11908. * removed.
  11909. * @param {String|HTMLElement|Array|NodeList|EventHandle} el An
  11910. * event handle, an id, an element reference, or a collection
  11911. * of ids and/or elements to remove the listener from.
  11912. * @return {boolean} true if the unbind was successful, false otherwise.
  11913. * @static
  11914. */
  11915. detach: function(type, fn, el, obj) {
  11916. var args=Y.Array(arguments, 0, true), compat, l, ok, i,
  11917. id, ce;
  11918. if (args[args.length-1] === COMPAT_ARG) {
  11919. compat = true;
  11920. // args.pop();
  11921. }
  11922. if (type && type.detach) {
  11923. return type.detach();
  11924. }
  11925. // The el argument can be a string
  11926. if (typeof el == "string") {
  11927. // el = (compat) ? Y.DOM.byId(el) : Y.all(el);
  11928. if (compat) {
  11929. el = Y.DOM.byId(el);
  11930. } else {
  11931. el = Y.Selector.query(el);
  11932. l = el.length;
  11933. if (l < 1) {
  11934. el = null;
  11935. } else if (l == 1) {
  11936. el = el[0];
  11937. }
  11938. }
  11939. // return Event.detach.apply(Event, args);
  11940. }
  11941. if (!el) {
  11942. return false;
  11943. }
  11944. if (el.detach) {
  11945. args.splice(2, 1);
  11946. return el.detach.apply(el, args);
  11947. // The el argument can be an array of elements or element ids.
  11948. } else if (shouldIterate(el)) {
  11949. ok = true;
  11950. for (i=0, l=el.length; i<l; ++i) {
  11951. args[2] = el[i];
  11952. ok = ( Y.Event.detach.apply(Y.Event, args) && ok );
  11953. }
  11954. return ok;
  11955. }
  11956. if (!type || !fn || !fn.call) {
  11957. return Event.purgeElement(el, false, type);
  11958. }
  11959. id = 'event:' + Y.stamp(el) + type;
  11960. ce = _wrappers[id];
  11961. if (ce) {
  11962. return ce.detach(fn);
  11963. } else {
  11964. return false;
  11965. }
  11966. },
  11967. /**
  11968. * Finds the event in the window object, the caller's arguments, or
  11969. * in the arguments of another method in the callstack. This is
  11970. * executed automatically for events registered through the event
  11971. * manager, so the implementer should not normally need to execute
  11972. * this function at all.
  11973. * @method getEvent
  11974. * @param {Event} e the event parameter from the handler
  11975. * @param {HTMLElement} el the element the listener was attached to
  11976. * @return {Event} the event
  11977. * @static
  11978. */
  11979. getEvent: function(e, el, noFacade) {
  11980. var ev = e || win.event;
  11981. return (noFacade) ? ev :
  11982. new Y.DOMEventFacade(ev, el, _wrappers['event:' + Y.stamp(el) + e.type]);
  11983. },
  11984. /**
  11985. * Generates an unique ID for the element if it does not already
  11986. * have one.
  11987. * @method generateId
  11988. * @param el the element to create the id for
  11989. * @return {string} the resulting id of the element
  11990. * @static
  11991. */
  11992. generateId: function(el) {
  11993. return Y.DOM.generateID(el);
  11994. },
  11995. /**
  11996. * We want to be able to use getElementsByTagName as a collection
  11997. * to attach a group of events to. Unfortunately, different
  11998. * browsers return different types of collections. This function
  11999. * tests to determine if the object is array-like. It will also
  12000. * fail if the object is an array, but is empty.
  12001. * @method _isValidCollection
  12002. * @param o the object to test
  12003. * @return {boolean} true if the object is array-like and populated
  12004. * @deprecated was not meant to be used directly
  12005. * @static
  12006. * @private
  12007. */
  12008. _isValidCollection: shouldIterate,
  12009. /**
  12010. * hook up any deferred listeners
  12011. * @method _load
  12012. * @static
  12013. * @private
  12014. */
  12015. _load: function(e) {
  12016. if (!_loadComplete) {
  12017. // Y.log('Load Complete', 'info', 'event');
  12018. _loadComplete = true;
  12019. // Just in case DOMReady did not go off for some reason
  12020. // E._ready();
  12021. if (Y.fire) {
  12022. Y.fire(EVENT_READY);
  12023. }
  12024. // Available elements may not have been detected before the
  12025. // window load event fires. Try to find them now so that the
  12026. // the user is more likely to get the onAvailable notifications
  12027. // before the window load notification
  12028. Event._poll();
  12029. }
  12030. },
  12031. /**
  12032. * Polling function that runs before the onload event fires,
  12033. * attempting to attach To DoM Nodes as soon as they are
  12034. * available
  12035. * @method _poll
  12036. * @static
  12037. * @private
  12038. */
  12039. _poll: function() {
  12040. if (Event.locked) {
  12041. return;
  12042. }
  12043. if (Y.UA.ie && !YUI.Env.DOMReady) {
  12044. // Hold off if DOMReady has not fired and check current
  12045. // readyState to protect against the IE operation aborted
  12046. // issue.
  12047. Event.startInterval();
  12048. return;
  12049. }
  12050. Event.locked = true;
  12051. // Y.log.debug("poll");
  12052. // keep trying until after the page is loaded. We need to
  12053. // check the page load state prior to trying to bind the
  12054. // elements so that we can be certain all elements have been
  12055. // tested appropriately
  12056. var i, len, item, el, notAvail, executeItem,
  12057. tryAgain = !_loadComplete;
  12058. if (!tryAgain) {
  12059. tryAgain = (_retryCount > 0);
  12060. }
  12061. // onAvailable
  12062. notAvail = [];
  12063. executeItem = function (el, item) {
  12064. var context, ov = item.override;
  12065. if (item.compat) {
  12066. if (item.override) {
  12067. if (ov === true) {
  12068. context = item.obj;
  12069. } else {
  12070. context = ov;
  12071. }
  12072. } else {
  12073. context = el;
  12074. }
  12075. item.fn.call(context, item.obj);
  12076. } else {
  12077. context = item.obj || Y.one(el);
  12078. item.fn.apply(context, (Y.Lang.isArray(ov)) ? ov : []);
  12079. }
  12080. };
  12081. // onAvailable
  12082. for (i=0,len=_avail.length; i<len; ++i) {
  12083. item = _avail[i];
  12084. if (item && !item.checkReady) {
  12085. // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
  12086. el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
  12087. if (el) {
  12088. // Y.log('avail: ' + el);
  12089. executeItem(el, item);
  12090. _avail[i] = null;
  12091. } else {
  12092. // Y.log('NOT avail: ' + el);
  12093. notAvail.push(item);
  12094. }
  12095. }
  12096. }
  12097. // onContentReady
  12098. for (i=0,len=_avail.length; i<len; ++i) {
  12099. item = _avail[i];
  12100. if (item && item.checkReady) {
  12101. // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
  12102. el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
  12103. if (el) {
  12104. // The element is available, but not necessarily ready
  12105. // @todo should we test parentNode.nextSibling?
  12106. if (_loadComplete || (el.get && el.get('nextSibling')) || el.nextSibling) {
  12107. executeItem(el, item);
  12108. _avail[i] = null;
  12109. }
  12110. } else {
  12111. notAvail.push(item);
  12112. }
  12113. }
  12114. }
  12115. _retryCount = (notAvail.length === 0) ? 0 : _retryCount - 1;
  12116. if (tryAgain) {
  12117. // we may need to strip the nulled out items here
  12118. Event.startInterval();
  12119. } else {
  12120. clearInterval(Event._interval);
  12121. Event._interval = null;
  12122. }
  12123. Event.locked = false;
  12124. return;
  12125. },
  12126. /**
  12127. * Removes all listeners attached to the given element via addListener.
  12128. * Optionally, the node's children can also be purged.
  12129. * Optionally, you can specify a specific type of event to remove.
  12130. * @method purgeElement
  12131. * @param {HTMLElement} el the element to purge
  12132. * @param {boolean} recurse recursively purge this element's children
  12133. * as well. Use with caution.
  12134. * @param {string} type optional type of listener to purge. If
  12135. * left out, all listeners will be removed
  12136. * @static
  12137. */
  12138. purgeElement: function(el, recurse, type) {
  12139. // var oEl = (Y.Lang.isString(el)) ? Y.one(el) : el,
  12140. var oEl = (Y.Lang.isString(el)) ? Y.Selector.query(el, null, true) : el,
  12141. lis = Event.getListeners(oEl, type), i, len, children, child;
  12142. if (recurse && oEl) {
  12143. lis = lis || [];
  12144. children = Y.Selector.query('*', oEl);
  12145. i = 0;
  12146. len = children.length;
  12147. for (; i < len; ++i) {
  12148. child = Event.getListeners(children[i], type);
  12149. if (child) {
  12150. lis = lis.concat(child);
  12151. }
  12152. }
  12153. }
  12154. if (lis) {
  12155. for (i = 0, len = lis.length; i < len; ++i) {
  12156. lis[i].detachAll();
  12157. }
  12158. }
  12159. },
  12160. /**
  12161. * Removes all object references and the DOM proxy subscription for
  12162. * a given event for a DOM node.
  12163. *
  12164. * @method _clean
  12165. * @param wrapper {CustomEvent} Custom event proxy for the DOM
  12166. * subscription
  12167. * @private
  12168. * @static
  12169. * @since 3.4.0
  12170. */
  12171. _clean: function (wrapper) {
  12172. var key = wrapper.key,
  12173. domkey = wrapper.domkey;
  12174. remove(wrapper.el, wrapper.type, wrapper.fn, wrapper.capture);
  12175. delete _wrappers[key];
  12176. delete Y._yuievt.events[key];
  12177. if (_el_events[domkey]) {
  12178. delete _el_events[domkey][key];
  12179. if (!Y.Object.size(_el_events[domkey])) {
  12180. delete _el_events[domkey];
  12181. }
  12182. }
  12183. },
  12184. /**
  12185. * Returns all listeners attached to the given element via addListener.
  12186. * Optionally, you can specify a specific type of event to return.
  12187. * @method getListeners
  12188. * @param el {HTMLElement|string} the element or element id to inspect
  12189. * @param type {string} optional type of listener to return. If
  12190. * left out, all listeners will be returned
  12191. * @return {Y.Custom.Event} the custom event wrapper for the DOM event(s)
  12192. * @static
  12193. */
  12194. getListeners: function(el, type) {
  12195. var ek = Y.stamp(el, true), evts = _el_events[ek],
  12196. results=[] , key = (type) ? 'event:' + ek + type : null,
  12197. adapters = _eventenv.plugins;
  12198. if (!evts) {
  12199. return null;
  12200. }
  12201. if (key) {
  12202. // look for synthetic events
  12203. if (adapters[type] && adapters[type].eventDef) {
  12204. key += '_synth';
  12205. }
  12206. if (evts[key]) {
  12207. results.push(evts[key]);
  12208. }
  12209. // get native events as well
  12210. key += 'native';
  12211. if (evts[key]) {
  12212. results.push(evts[key]);
  12213. }
  12214. } else {
  12215. Y.each(evts, function(v, k) {
  12216. results.push(v);
  12217. });
  12218. }
  12219. return (results.length) ? results : null;
  12220. },
  12221. /**
  12222. * Removes all listeners registered by pe.event. Called
  12223. * automatically during the unload event.
  12224. * @method _unload
  12225. * @static
  12226. * @private
  12227. */
  12228. _unload: function(e) {
  12229. Y.each(_wrappers, function(v, k) {
  12230. if (v.type == 'unload') {
  12231. v.fire(e);
  12232. }
  12233. v.detachAll();
  12234. });
  12235. remove(win, "unload", onUnload);
  12236. },
  12237. /**
  12238. * Adds a DOM event directly without the caching, cleanup, context adj, etc
  12239. *
  12240. * @method nativeAdd
  12241. * @param {HTMLElement} el the element to bind the handler to
  12242. * @param {string} type the type of event handler
  12243. * @param {function} fn the callback to invoke
  12244. * @param {boolen} capture capture or bubble phase
  12245. * @static
  12246. * @private
  12247. */
  12248. nativeAdd: add,
  12249. /**
  12250. * Basic remove listener
  12251. *
  12252. * @method nativeRemove
  12253. * @param {HTMLElement} el the element to bind the handler to
  12254. * @param {string} type the type of event handler
  12255. * @param {function} fn the callback to invoke
  12256. * @param {boolen} capture capture or bubble phase
  12257. * @static
  12258. * @private
  12259. */
  12260. nativeRemove: remove
  12261. };
  12262. }();
  12263. Y.Event = Event;
  12264. if (config.injected || YUI.Env.windowLoaded) {
  12265. onLoad();
  12266. } else {
  12267. add(win, "load", onLoad);
  12268. }
  12269. // Process onAvailable/onContentReady items when when the DOM is ready in IE
  12270. if (Y.UA.ie) {
  12271. Y.on(EVENT_READY, Event._poll);
  12272. }
  12273. add(win, "unload", onUnload);
  12274. Event.Custom = Y.CustomEvent;
  12275. Event.Subscriber = Y.Subscriber;
  12276. Event.Target = Y.EventTarget;
  12277. Event.Handle = Y.EventHandle;
  12278. Event.Facade = Y.EventFacade;
  12279. Event._poll();
  12280. })();
  12281. /**
  12282. * DOM event listener abstraction layer
  12283. * @module event
  12284. * @submodule event-base
  12285. */
  12286. /**
  12287. * Executes the callback as soon as the specified element
  12288. * is detected in the DOM. This function expects a selector
  12289. * string for the element(s) to detect. If you already have
  12290. * an element reference, you don't need this event.
  12291. * @event available
  12292. * @param type {string} 'available'
  12293. * @param fn {function} the callback function to execute.
  12294. * @param el {string} an selector for the element(s) to attach
  12295. * @param context optional argument that specifies what 'this' refers to.
  12296. * @param args* 0..n additional arguments to pass on to the callback function.
  12297. * These arguments will be added after the event object.
  12298. * @return {EventHandle} the detach handle
  12299. * @for YUI
  12300. */
  12301. Y.Env.evt.plugins.available = {
  12302. on: function(type, fn, id, o) {
  12303. var a = arguments.length > 4 ? Y.Array(arguments, 4, true) : null;
  12304. return Y.Event.onAvailable.call(Y.Event, id, fn, o, a);
  12305. }
  12306. };
  12307. /**
  12308. * Executes the callback as soon as the specified element
  12309. * is detected in the DOM with a nextSibling property
  12310. * (indicating that the element's children are available).
  12311. * This function expects a selector
  12312. * string for the element(s) to detect. If you already have
  12313. * an element reference, you don't need this event.
  12314. * @event contentready
  12315. * @param type {string} 'contentready'
  12316. * @param fn {function} the callback function to execute.
  12317. * @param el {string} an selector for the element(s) to attach.
  12318. * @param context optional argument that specifies what 'this' refers to.
  12319. * @param args* 0..n additional arguments to pass on to the callback function.
  12320. * These arguments will be added after the event object.
  12321. * @return {EventHandle} the detach handle
  12322. * @for YUI
  12323. */
  12324. Y.Env.evt.plugins.contentready = {
  12325. on: function(type, fn, id, o) {
  12326. var a = arguments.length > 4 ? Y.Array(arguments, 4, true) : null;
  12327. return Y.Event.onContentReady.call(Y.Event, id, fn, o, a);
  12328. }
  12329. };
  12330. }, '3.4.0' ,{requires:['event-custom-base']});
  12331. YUI.add('pluginhost-base', function(Y) {
  12332. /**
  12333. * Provides the augmentable PluginHost interface, which can be added to any class.
  12334. * @module pluginhost
  12335. */
  12336. /**
  12337. * Provides the augmentable PluginHost interface, which can be added to any class.
  12338. * @module pluginhost-base
  12339. */
  12340. /**
  12341. * <p>
  12342. * An augmentable class, which provides the augmented class with the ability to host plugins.
  12343. * It adds <a href="#method_plug">plug</a> and <a href="#method_unplug">unplug</a> methods to the augmented class, which can
  12344. * be used to add or remove plugins from instances of the class.
  12345. * </p>
  12346. *
  12347. * <p>Plugins can also be added through the constructor configuration object passed to the host class' constructor using
  12348. * the "plugins" property. Supported values for the "plugins" property are those defined by the <a href="#method_plug">plug</a> method.
  12349. *
  12350. * For example the following code would add the AnimPlugin and IOPlugin to Overlay (the plugin host):
  12351. * <xmp>
  12352. * var o = new Overlay({plugins: [ AnimPlugin, {fn:IOPlugin, cfg:{section:"header"}}]});
  12353. * </xmp>
  12354. * </p>
  12355. * <p>
  12356. * Plug.Host's protected <a href="#method_initPlugins">_initPlugins</a> and <a href="#method_destroyPlugins">_destroyPlugins</a>
  12357. * methods should be invoked by the host class at the appropriate point in the host's lifecyle.
  12358. * </p>
  12359. *
  12360. * @class Plugin.Host
  12361. */
  12362. var L = Y.Lang;
  12363. function PluginHost() {
  12364. this._plugins = {};
  12365. }
  12366. PluginHost.prototype = {
  12367. /**
  12368. * Adds a plugin to the host object. This will instantiate the
  12369. * plugin and attach it to the configured namespace on the host object.
  12370. *
  12371. * @method plug
  12372. * @chainable
  12373. * @param P {Function | Object |Array} Accepts the plugin class, or an
  12374. * object with a "fn" property specifying the plugin class and
  12375. * a "cfg" property specifying the configuration for the Plugin.
  12376. * <p>
  12377. * Additionally an Array can also be passed in, with the above function or
  12378. * object values, allowing the user to add multiple plugins in a single call.
  12379. * </p>
  12380. * @param config (Optional) If the first argument is the plugin class, the second argument
  12381. * can be the configuration for the plugin.
  12382. * @return {Base} A reference to the host object
  12383. */
  12384. plug: function(Plugin, config) {
  12385. var i, ln, ns;
  12386. if (L.isArray(Plugin)) {
  12387. for (i = 0, ln = Plugin.length; i < ln; i++) {
  12388. this.plug(Plugin[i]);
  12389. }
  12390. } else {
  12391. if (Plugin && !L.isFunction(Plugin)) {
  12392. config = Plugin.cfg;
  12393. Plugin = Plugin.fn;
  12394. }
  12395. // Plugin should be fn by now
  12396. if (Plugin && Plugin.NS) {
  12397. ns = Plugin.NS;
  12398. config = config || {};
  12399. config.host = this;
  12400. if (this.hasPlugin(ns)) {
  12401. // Update config
  12402. this[ns].setAttrs(config);
  12403. } else {
  12404. // Create new instance
  12405. this[ns] = new Plugin(config);
  12406. this._plugins[ns] = Plugin;
  12407. }
  12408. }
  12409. else { Y.log("Attempt to plug in an invalid plugin. Host:" + this + ", Plugin:" + Plugin); }
  12410. }
  12411. return this;
  12412. },
  12413. /**
  12414. * Removes a plugin from the host object. This will destroy the
  12415. * plugin instance and delete the namepsace from the host object.
  12416. *
  12417. * @method unplug
  12418. * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
  12419. * all registered plugins are unplugged.
  12420. * @return {Base} A reference to the host object
  12421. * @chainable
  12422. */
  12423. unplug: function(plugin) {
  12424. var ns = plugin,
  12425. plugins = this._plugins;
  12426. if (plugin) {
  12427. if (L.isFunction(plugin)) {
  12428. ns = plugin.NS;
  12429. if (ns && (!plugins[ns] || plugins[ns] !== plugin)) {
  12430. ns = null;
  12431. }
  12432. }
  12433. if (ns) {
  12434. if (this[ns]) {
  12435. this[ns].destroy();
  12436. delete this[ns];
  12437. }
  12438. if (plugins[ns]) {
  12439. delete plugins[ns];
  12440. }
  12441. }
  12442. } else {
  12443. for (ns in this._plugins) {
  12444. if (this._plugins.hasOwnProperty(ns)) {
  12445. this.unplug(ns);
  12446. }
  12447. }
  12448. }
  12449. return this;
  12450. },
  12451. /**
  12452. * Determines if a plugin has plugged into this host.
  12453. *
  12454. * @method hasPlugin
  12455. * @param {String} ns The plugin's namespace
  12456. * @return {boolean} returns true, if the plugin has been plugged into this host, false otherwise.
  12457. */
  12458. hasPlugin : function(ns) {
  12459. return (this._plugins[ns] && this[ns]);
  12460. },
  12461. /**
  12462. * Initializes static plugins registered on the host (using the
  12463. * Base.plug static method) and any plugins passed to the
  12464. * instance through the "plugins" configuration property.
  12465. *
  12466. * @method _initPlugins
  12467. * @param {Config} config The configuration object with property name/value pairs.
  12468. * @private
  12469. */
  12470. _initPlugins: function(config) {
  12471. this._plugins = this._plugins || {};
  12472. if (this._initConfigPlugins) {
  12473. this._initConfigPlugins(config);
  12474. }
  12475. },
  12476. /**
  12477. * Unplugs and destroys all plugins on the host
  12478. * @method _destroyPlugins
  12479. * @private
  12480. */
  12481. _destroyPlugins: function() {
  12482. this.unplug();
  12483. }
  12484. };
  12485. Y.namespace("Plugin").Host = PluginHost;
  12486. }, '3.4.0' ,{requires:['yui-base']});
  12487. YUI.add('pluginhost-config', function(Y) {
  12488. /**
  12489. * Adds pluginhost constructor configuration and static configuration support
  12490. * @submodule pluginhost-config
  12491. */
  12492. var PluginHost = Y.Plugin.Host,
  12493. L = Y.Lang;
  12494. /**
  12495. * A protected initialization method, used by the host class to initialize
  12496. * plugin configurations passed the constructor, through the config object.
  12497. *
  12498. * Host objects should invoke this method at the appropriate time in their
  12499. * construction lifecycle.
  12500. *
  12501. * @method _initConfigPlugins
  12502. * @param {Object} config The configuration object passed to the constructor
  12503. * @protected
  12504. * @for Plugin.Host
  12505. */
  12506. PluginHost.prototype._initConfigPlugins = function(config) {
  12507. // Class Configuration
  12508. var classes = (this._getClasses) ? this._getClasses() : [this.constructor],
  12509. plug = [],
  12510. unplug = {},
  12511. constructor, i, classPlug, classUnplug, pluginClassName;
  12512. // TODO: Room for optimization. Can we apply statically/unplug in same pass?
  12513. for (i = classes.length - 1; i >= 0; i--) {
  12514. constructor = classes[i];
  12515. classUnplug = constructor._UNPLUG;
  12516. if (classUnplug) {
  12517. // subclasses over-write
  12518. Y.mix(unplug, classUnplug, true);
  12519. }
  12520. classPlug = constructor._PLUG;
  12521. if (classPlug) {
  12522. // subclasses over-write
  12523. Y.mix(plug, classPlug, true);
  12524. }
  12525. }
  12526. for (pluginClassName in plug) {
  12527. if (plug.hasOwnProperty(pluginClassName)) {
  12528. if (!unplug[pluginClassName]) {
  12529. this.plug(plug[pluginClassName]);
  12530. }
  12531. }
  12532. }
  12533. // User Configuration
  12534. if (config && config.plugins) {
  12535. this.plug(config.plugins);
  12536. }
  12537. };
  12538. /**
  12539. * Registers plugins to be instantiated at the class level (plugins
  12540. * which should be plugged into every instance of the class by default).
  12541. *
  12542. * @method Plugin.Host.plug
  12543. * @static
  12544. *
  12545. * @param {Function} hostClass The host class on which to register the plugins
  12546. * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
  12547. * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
  12548. */
  12549. PluginHost.plug = function(hostClass, plugin, config) {
  12550. // Cannot plug into Base, since Plugins derive from Base [ will cause infinite recurrsion ]
  12551. var p, i, l, name;
  12552. if (hostClass !== Y.Base) {
  12553. hostClass._PLUG = hostClass._PLUG || {};
  12554. if (!L.isArray(plugin)) {
  12555. if (config) {
  12556. plugin = {fn:plugin, cfg:config};
  12557. }
  12558. plugin = [plugin];
  12559. }
  12560. for (i = 0, l = plugin.length; i < l;i++) {
  12561. p = plugin[i];
  12562. name = p.NAME || p.fn.NAME;
  12563. hostClass._PLUG[name] = p;
  12564. }
  12565. }
  12566. };
  12567. /**
  12568. * Unregisters any class level plugins which have been registered by the host class, or any
  12569. * other class in the hierarchy.
  12570. *
  12571. * @method Plugin.Host.unplug
  12572. * @static
  12573. *
  12574. * @param {Function} hostClass The host class from which to unregister the plugins
  12575. * @param {Function | Array} plugin The plugin class, or an array of plugin classes
  12576. */
  12577. PluginHost.unplug = function(hostClass, plugin) {
  12578. var p, i, l, name;
  12579. if (hostClass !== Y.Base) {
  12580. hostClass._UNPLUG = hostClass._UNPLUG || {};
  12581. if (!L.isArray(plugin)) {
  12582. plugin = [plugin];
  12583. }
  12584. for (i = 0, l = plugin.length; i < l; i++) {
  12585. p = plugin[i];
  12586. name = p.NAME;
  12587. if (!hostClass._PLUG[name]) {
  12588. hostClass._UNPLUG[name] = p;
  12589. } else {
  12590. delete hostClass._PLUG[name];
  12591. }
  12592. }
  12593. }
  12594. };
  12595. }, '3.4.0' ,{requires:['pluginhost-base']});
  12596. YUI.add('event-delegate', function(Y) {
  12597. /**
  12598. * Adds event delegation support to the library.
  12599. *
  12600. * @module event
  12601. * @submodule event-delegate
  12602. */
  12603. var toArray = Y.Array,
  12604. YLang = Y.Lang,
  12605. isString = YLang.isString,
  12606. isObject = YLang.isObject,
  12607. isArray = YLang.isArray,
  12608. selectorTest = Y.Selector.test,
  12609. detachCategories = Y.Env.evt.handles;
  12610. /**
  12611. * <p>Sets up event delegation on a container element. The delegated event
  12612. * will use a supplied selector or filtering function to test if the event
  12613. * references at least one node that should trigger the subscription
  12614. * callback.</p>
  12615. *
  12616. * <p>Selector string filters will trigger the callback if the event originated
  12617. * from a node that matches it or is contained in a node that matches it.
  12618. * Function filters are called for each Node up the parent axis to the
  12619. * subscribing container node, and receive at each level the Node and the event
  12620. * object. The function should return true (or a truthy value) if that Node
  12621. * should trigger the subscription callback. Note, it is possible for filters
  12622. * to match multiple Nodes for a single event. In this case, the delegate
  12623. * callback will be executed for each matching Node.</p>
  12624. *
  12625. * <p>For each matching Node, the callback will be executed with its 'this'
  12626. * object set to the Node matched by the filter (unless a specific context was
  12627. * provided during subscription), and the provided event's
  12628. * <code>currentTarget</code> will also be set to the matching Node. The
  12629. * containing Node from which the subscription was originally made can be
  12630. * referenced as <code>e.container</code>.
  12631. *
  12632. * @method delegate
  12633. * @param type {String} the event type to delegate
  12634. * @param fn {Function} the callback function to execute. This function
  12635. * will be provided the event object for the delegated event.
  12636. * @param el {String|node} the element that is the delegation container
  12637. * @param spec {string|Function} a selector that must match the target of the
  12638. * event or a function to test target and its parents for a match
  12639. * @param context optional argument that specifies what 'this' refers to.
  12640. * @param args* 0..n additional arguments to pass on to the callback function.
  12641. * These arguments will be added after the event object.
  12642. * @return {EventHandle} the detach handle
  12643. * @for YUI
  12644. */
  12645. function delegate(type, fn, el, filter) {
  12646. var args = toArray(arguments, 0, true),
  12647. query = isString(el) ? el : null,
  12648. typeBits, synth, container, categories, cat, i, len, handles, handle;
  12649. // Support Y.delegate({ click: fnA, key: fnB }, context, filter, ...);
  12650. // and Y.delegate(['click', 'key'], fn, context, filter, ...);
  12651. if (isObject(type)) {
  12652. handles = [];
  12653. if (isArray(type)) {
  12654. for (i = 0, len = type.length; i < len; ++i) {
  12655. args[0] = type[i];
  12656. handles.push(Y.delegate.apply(Y, args));
  12657. }
  12658. } else {
  12659. // Y.delegate({'click', fn}, context, filter) =>
  12660. // Y.delegate('click', fn, context, filter)
  12661. args.unshift(null); // one arg becomes two; need to make space
  12662. for (i in type) {
  12663. if (type.hasOwnProperty(i)) {
  12664. args[0] = i;
  12665. args[1] = type[i];
  12666. handles.push(Y.delegate.apply(Y, args));
  12667. }
  12668. }
  12669. }
  12670. return new Y.EventHandle(handles);
  12671. }
  12672. typeBits = type.split(/\|/);
  12673. if (typeBits.length > 1) {
  12674. cat = typeBits.shift();
  12675. args[0] = type = typeBits.shift();
  12676. }
  12677. synth = Y.Node.DOM_EVENTS[type];
  12678. if (isObject(synth) && synth.delegate) {
  12679. handle = synth.delegate.apply(synth, arguments);
  12680. }
  12681. if (!handle) {
  12682. if (!type || !fn || !el || !filter) {
  12683. Y.log("delegate requires type, callback, parent, & filter", "warn");
  12684. return;
  12685. }
  12686. container = (query) ? Y.Selector.query(query, null, true) : el;
  12687. if (!container && isString(el)) {
  12688. handle = Y.on('available', function () {
  12689. Y.mix(handle, Y.delegate.apply(Y, args), true);
  12690. }, el);
  12691. }
  12692. if (!handle && container) {
  12693. args.splice(2, 2, container); // remove the filter
  12694. handle = Y.Event._attach(args, { facade: false });
  12695. handle.sub.filter = filter;
  12696. handle.sub._notify = delegate.notifySub;
  12697. }
  12698. }
  12699. if (handle && cat) {
  12700. categories = detachCategories[cat] || (detachCategories[cat] = {});
  12701. categories = categories[type] || (categories[type] = []);
  12702. categories.push(handle);
  12703. }
  12704. return handle;
  12705. }
  12706. /**
  12707. * Overrides the <code>_notify</code> method on the normal DOM subscription to
  12708. * inject the filtering logic and only proceed in the case of a match.
  12709. *
  12710. * @method delegate.notifySub
  12711. * @param thisObj {Object} default 'this' object for the callback
  12712. * @param args {Array} arguments passed to the event's <code>fire()</code>
  12713. * @param ce {CustomEvent} the custom event managing the DOM subscriptions for
  12714. * the subscribed event on the subscribing node.
  12715. * @return {Boolean} false if the event was stopped
  12716. * @private
  12717. * @static
  12718. * @since 3.2.0
  12719. */
  12720. delegate.notifySub = function (thisObj, args, ce) {
  12721. // Preserve args for other subscribers
  12722. args = args.slice();
  12723. if (this.args) {
  12724. args.push.apply(args, this.args);
  12725. }
  12726. // Only notify subs if the event occurred on a targeted element
  12727. var currentTarget = delegate._applyFilter(this.filter, args, ce),
  12728. //container = e.currentTarget,
  12729. e, i, len, ret;
  12730. if (currentTarget) {
  12731. // Support multiple matches up the the container subtree
  12732. currentTarget = toArray(currentTarget);
  12733. // The second arg is the currentTarget, but we'll be reusing this
  12734. // facade, replacing the currentTarget for each use, so it doesn't
  12735. // matter what element we seed it with.
  12736. e = args[0] = new Y.DOMEventFacade(args[0], ce.el, ce);
  12737. e.container = Y.one(ce.el);
  12738. for (i = 0, len = currentTarget.length; i < len && !e.stopped; ++i) {
  12739. e.currentTarget = Y.one(currentTarget[i]);
  12740. ret = this.fn.apply(this.context || e.currentTarget, args);
  12741. if (ret === false) { // stop further notifications
  12742. break;
  12743. }
  12744. }
  12745. return ret;
  12746. }
  12747. };
  12748. /**
  12749. * <p>Compiles a selector string into a filter function to identify whether
  12750. * Nodes along the parent axis of an event's target should trigger event
  12751. * notification.</p>
  12752. *
  12753. * <p>This function is memoized, so previously compiled filter functions are
  12754. * returned if the same selector string is provided.</p>
  12755. *
  12756. * <p>This function may be useful when defining synthetic events for delegate
  12757. * handling.</p>
  12758. *
  12759. * @method delegate.compileFilter
  12760. * @param selector {String} the selector string to base the filtration on
  12761. * @return {Function}
  12762. * @since 3.2.0
  12763. * @static
  12764. */
  12765. delegate.compileFilter = Y.cached(function (selector) {
  12766. return function (target, e) {
  12767. return selectorTest(target._node, selector, e.currentTarget._node);
  12768. };
  12769. });
  12770. /**
  12771. * Walks up the parent axis of an event's target, and tests each element
  12772. * against a supplied filter function. If any Nodes, including the container,
  12773. * satisfy the filter, the delegated callback will be triggered for each.
  12774. *
  12775. * @method delegate._applyFilter
  12776. * @param filter {Function} boolean function to test for inclusion in event
  12777. * notification
  12778. * @param args {Array} the arguments that would be passed to subscribers
  12779. * @param ce {CustomEvent} the DOM event wrapper
  12780. * @return {Node|Node[]|undefined} The Node or Nodes that satisfy the filter
  12781. * @protected
  12782. */
  12783. delegate._applyFilter = function (filter, args, ce) {
  12784. var e = args[0],
  12785. container = ce.el, // facadeless events in IE, have no e.currentTarget
  12786. target = e.target || e.srcElement,
  12787. match = [],
  12788. isContainer = false;
  12789. // Resolve text nodes to their containing element
  12790. if (target.nodeType === 3) {
  12791. target = target.parentNode;
  12792. }
  12793. // passing target as the first arg rather than leaving well enough alone
  12794. // making 'this' in the filter function refer to the target. This is to
  12795. // support bound filter functions.
  12796. args.unshift(target);
  12797. if (isString(filter)) {
  12798. while (target) {
  12799. isContainer = (target === container);
  12800. if (selectorTest(target, filter, (isContainer ?null: container))) {
  12801. match.push(target);
  12802. }
  12803. if (isContainer) {
  12804. break;
  12805. }
  12806. target = target.parentNode;
  12807. }
  12808. } else {
  12809. // filter functions are implementer code and should receive wrappers
  12810. args[0] = Y.one(target);
  12811. args[1] = new Y.DOMEventFacade(e, container, ce);
  12812. while (target) {
  12813. // filter(target, e, extra args...) - this === target
  12814. if (filter.apply(args[0], args)) {
  12815. match.push(target);
  12816. }
  12817. if (target === container) {
  12818. break;
  12819. }
  12820. target = target.parentNode;
  12821. args[0] = Y.one(target);
  12822. }
  12823. args[1] = e; // restore the raw DOM event
  12824. }
  12825. if (match.length <= 1) {
  12826. match = match[0]; // single match or undefined
  12827. }
  12828. // remove the target
  12829. args.shift();
  12830. return match;
  12831. };
  12832. /**
  12833. * Sets up event delegation on a container element. The delegated event
  12834. * will use a supplied filter to test if the callback should be executed.
  12835. * This filter can be either a selector string or a function that returns
  12836. * a Node to use as the currentTarget for the event.
  12837. *
  12838. * The event object for the delegated event is supplied to the callback
  12839. * function. It is modified slightly in order to support all properties
  12840. * that may be needed for event delegation. 'currentTarget' is set to
  12841. * the element that matched the selector string filter or the Node returned
  12842. * from the filter function. 'container' is set to the element that the
  12843. * listener is delegated from (this normally would be the 'currentTarget').
  12844. *
  12845. * Filter functions will be called with the arguments that would be passed to
  12846. * the callback function, including the event object as the first parameter.
  12847. * The function should return false (or a falsey value) if the success criteria
  12848. * aren't met, and the Node to use as the event's currentTarget and 'this'
  12849. * object if they are.
  12850. *
  12851. * @method delegate
  12852. * @param type {string} the event type to delegate
  12853. * @param fn {function} the callback function to execute. This function
  12854. * will be provided the event object for the delegated event.
  12855. * @param el {string|node} the element that is the delegation container
  12856. * @param filter {string|function} a selector that must match the target of the
  12857. * event or a function that returns a Node or false.
  12858. * @param context optional argument that specifies what 'this' refers to.
  12859. * @param args* 0..n additional arguments to pass on to the callback function.
  12860. * These arguments will be added after the event object.
  12861. * @return {EventHandle} the detach handle
  12862. * @for YUI
  12863. */
  12864. Y.delegate = Y.Event.delegate = delegate;
  12865. }, '3.4.0' ,{requires:['node-base']});
  12866. YUI.add('node-event-delegate', function(Y) {
  12867. /**
  12868. * Functionality to make the node a delegated event container
  12869. * @module node
  12870. * @submodule node-event-delegate
  12871. */
  12872. /**
  12873. * <p>Sets up a delegation listener for an event occurring inside the Node.
  12874. * The delegated event will be verified against a supplied selector or
  12875. * filtering function to test if the event references at least one node that
  12876. * should trigger the subscription callback.</p>
  12877. *
  12878. * <p>Selector string filters will trigger the callback if the event originated
  12879. * from a node that matches it or is contained in a node that matches it.
  12880. * Function filters are called for each Node up the parent axis to the
  12881. * subscribing container node, and receive at each level the Node and the event
  12882. * object. The function should return true (or a truthy value) if that Node
  12883. * should trigger the subscription callback. Note, it is possible for filters
  12884. * to match multiple Nodes for a single event. In this case, the delegate
  12885. * callback will be executed for each matching Node.</p>
  12886. *
  12887. * <p>For each matching Node, the callback will be executed with its 'this'
  12888. * object set to the Node matched by the filter (unless a specific context was
  12889. * provided during subscription), and the provided event's
  12890. * <code>currentTarget</code> will also be set to the matching Node. The
  12891. * containing Node from which the subscription was originally made can be
  12892. * referenced as <code>e.container</code>.
  12893. *
  12894. * @method delegate
  12895. * @param type {String} the event type to delegate
  12896. * @param fn {Function} the callback function to execute. This function
  12897. * will be provided the event object for the delegated event.
  12898. * @param spec {String|Function} a selector that must match the target of the
  12899. * event or a function to test target and its parents for a match
  12900. * @param context {Object} optional argument that specifies what 'this' refers to.
  12901. * @param args* {any} 0..n additional arguments to pass on to the callback function.
  12902. * These arguments will be added after the event object.
  12903. * @return {EventHandle} the detach handle
  12904. * @for Node
  12905. */
  12906. Y.Node.prototype.delegate = function(type) {
  12907. var args = Y.Array(arguments, 0, true),
  12908. index = (Y.Lang.isObject(type) && !Y.Lang.isArray(type)) ? 1 : 2;
  12909. args.splice(index, 0, this._node);
  12910. return Y.delegate.apply(Y, args);
  12911. };
  12912. }, '3.4.0' ,{requires:['node-base', 'event-delegate']});
  12913. YUI.add('node-pluginhost', function(Y) {
  12914. /**
  12915. * @module node
  12916. * @submodule node-pluginhost
  12917. */
  12918. /**
  12919. * Registers plugins to be instantiated at the class level (plugins
  12920. * which should be plugged into every instance of Node by default).
  12921. *
  12922. * @method plug
  12923. * @static
  12924. * @for Node
  12925. * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
  12926. * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
  12927. */
  12928. Y.Node.plug = function() {
  12929. var args = Y.Array(arguments);
  12930. args.unshift(Y.Node);
  12931. Y.Plugin.Host.plug.apply(Y.Base, args);
  12932. return Y.Node;
  12933. };
  12934. /**
  12935. * Unregisters any class level plugins which have been registered by the Node
  12936. *
  12937. * @method unplug
  12938. * @static
  12939. *
  12940. * @param {Function | Array} plugin The plugin class, or an array of plugin classes
  12941. */
  12942. Y.Node.unplug = function() {
  12943. var args = Y.Array(arguments);
  12944. args.unshift(Y.Node);
  12945. Y.Plugin.Host.unplug.apply(Y.Base, args);
  12946. return Y.Node;
  12947. };
  12948. Y.mix(Y.Node, Y.Plugin.Host, false, null, 1);
  12949. // allow batching of plug/unplug via NodeList
  12950. // doesn't use NodeList.importMethod because we need real Nodes (not tmpNode)
  12951. Y.NodeList.prototype.plug = function() {
  12952. var args = arguments;
  12953. Y.NodeList.each(this, function(node) {
  12954. Y.Node.prototype.plug.apply(Y.one(node), args);
  12955. });
  12956. };
  12957. Y.NodeList.prototype.unplug = function() {
  12958. var args = arguments;
  12959. Y.NodeList.each(this, function(node) {
  12960. Y.Node.prototype.unplug.apply(Y.one(node), args);
  12961. });
  12962. };
  12963. }, '3.4.0' ,{requires:['node-base', 'pluginhost']});
  12964. YUI.add('node-screen', function(Y) {
  12965. /**
  12966. * Extended Node interface for managing regions and screen positioning.
  12967. * Adds support for positioning elements and normalizes window size and scroll detection.
  12968. * @module node
  12969. * @submodule node-screen
  12970. */
  12971. // these are all "safe" returns, no wrapping required
  12972. Y.each([
  12973. /**
  12974. * Returns the inner width of the viewport (exludes scrollbar).
  12975. * @config winWidth
  12976. * @for Node
  12977. * @type {Int}
  12978. */
  12979. 'winWidth',
  12980. /**
  12981. * Returns the inner height of the viewport (exludes scrollbar).
  12982. * @config winHeight
  12983. * @type {Int}
  12984. */
  12985. 'winHeight',
  12986. /**
  12987. * Document width
  12988. * @config winHeight
  12989. * @type {Int}
  12990. */
  12991. 'docWidth',
  12992. /**
  12993. * Document height
  12994. * @config docHeight
  12995. * @type {Int}
  12996. */
  12997. 'docHeight',
  12998. /**
  12999. * Pixel distance the page has been scrolled horizontally
  13000. * @config docScrollX
  13001. * @type {Int}
  13002. */
  13003. 'docScrollX',
  13004. /**
  13005. * Pixel distance the page has been scrolled vertically
  13006. * @config docScrollY
  13007. * @type {Int}
  13008. */
  13009. 'docScrollY'
  13010. ],
  13011. function(name) {
  13012. Y.Node.ATTRS[name] = {
  13013. getter: function() {
  13014. var args = Array.prototype.slice.call(arguments);
  13015. args.unshift(Y.Node.getDOMNode(this));
  13016. return Y.DOM[name].apply(this, args);
  13017. }
  13018. };
  13019. }
  13020. );
  13021. Y.Node.ATTRS.scrollLeft = {
  13022. getter: function() {
  13023. var node = Y.Node.getDOMNode(this);
  13024. return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node);
  13025. },
  13026. setter: function(val) {
  13027. var node = Y.Node.getDOMNode(this);
  13028. if (node) {
  13029. if ('scrollLeft' in node) {
  13030. node.scrollLeft = val;
  13031. } else if (node.document || node.nodeType === 9) {
  13032. Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc
  13033. }
  13034. } else {
  13035. Y.log('unable to set scrollLeft for ' + node, 'error', 'Node');
  13036. }
  13037. }
  13038. };
  13039. Y.Node.ATTRS.scrollTop = {
  13040. getter: function() {
  13041. var node = Y.Node.getDOMNode(this);
  13042. return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node);
  13043. },
  13044. setter: function(val) {
  13045. var node = Y.Node.getDOMNode(this);
  13046. if (node) {
  13047. if ('scrollTop' in node) {
  13048. node.scrollTop = val;
  13049. } else if (node.document || node.nodeType === 9) {
  13050. Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc
  13051. }
  13052. } else {
  13053. Y.log('unable to set scrollTop for ' + node, 'error', 'Node');
  13054. }
  13055. }
  13056. };
  13057. Y.Node.importMethod(Y.DOM, [
  13058. /**
  13059. * Gets the current position of the node in page coordinates.
  13060. * @method getXY
  13061. * @for Node
  13062. * @return {Array} The XY position of the node
  13063. */
  13064. 'getXY',
  13065. /**
  13066. * Set the position of the node in page coordinates, regardless of how the node is positioned.
  13067. * @method setXY
  13068. * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
  13069. * @chainable
  13070. */
  13071. 'setXY',
  13072. /**
  13073. * Gets the current position of the node in page coordinates.
  13074. * @method getX
  13075. * @return {Int} The X position of the node
  13076. */
  13077. 'getX',
  13078. /**
  13079. * Set the position of the node in page coordinates, regardless of how the node is positioned.
  13080. * @method setX
  13081. * @param {Int} x X value for new position (coordinates are page-based)
  13082. * @chainable
  13083. */
  13084. 'setX',
  13085. /**
  13086. * Gets the current position of the node in page coordinates.
  13087. * @method getY
  13088. * @return {Int} The Y position of the node
  13089. */
  13090. 'getY',
  13091. /**
  13092. * Set the position of the node in page coordinates, regardless of how the node is positioned.
  13093. * @method setY
  13094. * @param {Int} y Y value for new position (coordinates are page-based)
  13095. * @chainable
  13096. */
  13097. 'setY',
  13098. /**
  13099. * Swaps the XY position of this node with another node.
  13100. * @method swapXY
  13101. * @param {Y.Node || HTMLElement} otherNode The node to swap with.
  13102. * @chainable
  13103. */
  13104. 'swapXY'
  13105. ]);
  13106. /**
  13107. * @module node
  13108. * @submodule node-screen
  13109. */
  13110. /**
  13111. * Returns a region object for the node
  13112. * @config region
  13113. * @for Node
  13114. * @type Node
  13115. */
  13116. Y.Node.ATTRS.region = {
  13117. getter: function() {
  13118. var node = this.getDOMNode(),
  13119. region;
  13120. if (node && !node.tagName) {
  13121. if (node.nodeType === 9) { // document
  13122. node = node.documentElement;
  13123. }
  13124. }
  13125. if (Y.DOM.isWindow(node)) {
  13126. region = Y.DOM.viewportRegion(node);
  13127. } else {
  13128. region = Y.DOM.region(node);
  13129. }
  13130. return region;
  13131. }
  13132. };
  13133. /**
  13134. * Returns a region object for the node's viewport
  13135. * @config viewportRegion
  13136. * @type Node
  13137. */
  13138. Y.Node.ATTRS.viewportRegion = {
  13139. getter: function() {
  13140. return Y.DOM.viewportRegion(Y.Node.getDOMNode(this));
  13141. }
  13142. };
  13143. Y.Node.importMethod(Y.DOM, 'inViewportRegion');
  13144. // these need special treatment to extract 2nd node arg
  13145. /**
  13146. * Compares the intersection of the node with another node or region
  13147. * @method intersect
  13148. * @for Node
  13149. * @param {Node|Object} node2 The node or region to compare with.
  13150. * @param {Object} altRegion An alternate region to use (rather than this node's).
  13151. * @return {Object} An object representing the intersection of the regions.
  13152. */
  13153. Y.Node.prototype.intersect = function(node2, altRegion) {
  13154. var node1 = Y.Node.getDOMNode(this);
  13155. if (Y.instanceOf(node2, Y.Node)) { // might be a region object
  13156. node2 = Y.Node.getDOMNode(node2);
  13157. }
  13158. return Y.DOM.intersect(node1, node2, altRegion);
  13159. };
  13160. /**
  13161. * Determines whether or not the node is within the giving region.
  13162. * @method inRegion
  13163. * @param {Node|Object} node2 The node or region to compare with.
  13164. * @param {Boolean} all Whether or not all of the node must be in the region.
  13165. * @param {Object} altRegion An alternate region to use (rather than this node's).
  13166. * @return {Object} An object representing the intersection of the regions.
  13167. */
  13168. Y.Node.prototype.inRegion = function(node2, all, altRegion) {
  13169. var node1 = Y.Node.getDOMNode(this);
  13170. if (Y.instanceOf(node2, Y.Node)) { // might be a region object
  13171. node2 = Y.Node.getDOMNode(node2);
  13172. }
  13173. return Y.DOM.inRegion(node1, node2, all, altRegion);
  13174. };
  13175. }, '3.4.0' ,{requires:['node-base', 'dom-screen']});
  13176. YUI.add('node-style', function(Y) {
  13177. (function(Y) {
  13178. /**
  13179. * Extended Node interface for managing node styles.
  13180. * @module node
  13181. * @submodule node-style
  13182. */
  13183. var methods = [
  13184. /**
  13185. * Returns the style's current value.
  13186. * @method getStyle
  13187. * @for Node
  13188. * @param {String} attr The style attribute to retrieve.
  13189. * @return {String} The current value of the style property for the element.
  13190. */
  13191. 'getStyle',
  13192. /**
  13193. * Returns the computed value for the given style property.
  13194. * @method getComputedStyle
  13195. * @param {String} attr The style attribute to retrieve.
  13196. * @return {String} The computed value of the style property for the element.
  13197. */
  13198. 'getComputedStyle',
  13199. /**
  13200. * Sets a style property of the node.
  13201. * @method setStyle
  13202. * @param {String} attr The style attribute to set.
  13203. * @param {String|Number} val The value.
  13204. * @chainable
  13205. */
  13206. 'setStyle',
  13207. /**
  13208. * Sets multiple style properties on the node.
  13209. * @method setStyles
  13210. * @param {Object} hash An object literal of property:value pairs.
  13211. * @chainable
  13212. */
  13213. 'setStyles'
  13214. ];
  13215. Y.Node.importMethod(Y.DOM, methods);
  13216. /**
  13217. * Returns an array of values for each node.
  13218. * @method getStyle
  13219. * @for NodeList
  13220. * @see Node.getStyle
  13221. * @param {String} attr The style attribute to retrieve.
  13222. * @return {Array} The current values of the style property for the element.
  13223. */
  13224. /**
  13225. * Returns an array of the computed value for each node.
  13226. * @method getComputedStyle
  13227. * @see Node.getComputedStyle
  13228. * @param {String} attr The style attribute to retrieve.
  13229. * @return {Array} The computed values for each node.
  13230. */
  13231. /**
  13232. * Sets a style property on each node.
  13233. * @method setStyle
  13234. * @see Node.setStyle
  13235. * @param {String} attr The style attribute to set.
  13236. * @param {String|Number} val The value.
  13237. * @chainable
  13238. */
  13239. /**
  13240. * Sets multiple style properties on each node.
  13241. * @method setStyles
  13242. * @see Node.setStyles
  13243. * @param {Object} hash An object literal of property:value pairs.
  13244. * @chainable
  13245. */
  13246. Y.NodeList.importMethod(Y.Node.prototype, methods);
  13247. })(Y);
  13248. }, '3.4.0' ,{requires:['dom-style', 'node-base']});
  13249. YUI.add('querystring-stringify-simple', function(Y) {
  13250. /*global Y */
  13251. /**
  13252. * <p>Provides Y.QueryString.stringify method for converting objects to Query Strings.
  13253. * This is a subset implementation of the full querystring-stringify.</p>
  13254. * <p>This module provides the bare minimum functionality (encoding a hash of simple values),
  13255. * without the additional support for nested data structures. Every key-value pair is
  13256. * encoded by encodeURIComponent.</p>
  13257. * <p>This module provides a minimalistic way for io to handle single-level objects
  13258. * as transaction data.</p>
  13259. *
  13260. * @module querystring
  13261. * @submodule querystring-stringify-simple
  13262. * @for QueryString
  13263. * @static
  13264. */
  13265. var QueryString = Y.namespace("QueryString"),
  13266. EUC = encodeURIComponent;
  13267. /**
  13268. * <p>Converts a simple object to a Query String representation.</p>
  13269. * <p>Nested objects, Arrays, and so on, are not supported.</p>
  13270. *
  13271. * @method stringify
  13272. * @for QueryString
  13273. * @public
  13274. * @submodule querystring-stringify-simple
  13275. * @param obj {Object} A single-level object to convert to a querystring.
  13276. * @param cfg {Object} (optional) Configuration object. In the simple
  13277. * module, only the arrayKey setting is
  13278. * supported. When set to true, the key of an
  13279. * array will have the '[]' notation appended
  13280. * to the key;.
  13281. * @static
  13282. */
  13283. QueryString.stringify = function (obj, c) {
  13284. var qs = [],
  13285. // Default behavior is false; standard key notation.
  13286. s = c && c.arrayKey ? true : false,
  13287. key, i, l;
  13288. for (key in obj) {
  13289. if (obj.hasOwnProperty(key)) {
  13290. if (Y.Lang.isArray(obj[key])) {
  13291. for (i = 0, l = obj[key].length; i < l; i++) {
  13292. qs.push(EUC(s ? key + '[]' : key) + '=' + EUC(obj[key][i]));
  13293. }
  13294. }
  13295. else {
  13296. qs.push(EUC(key) + '=' + EUC(obj[key]));
  13297. }
  13298. }
  13299. }
  13300. return qs.join('&');
  13301. };
  13302. }, '3.4.0' ,{requires:['yui-base']});
  13303. YUI.add('io-base', function(Y) {
  13304. /**
  13305. * Base IO functionality. Provides basic XHR transport support.
  13306. * @module io
  13307. * @submodule io-base
  13308. */
  13309. // Window reference
  13310. var L = Y.Lang,
  13311. // List of events that comprise the IO event lifecycle.
  13312. E = ['start', 'complete', 'end', 'success', 'failure'],
  13313. // Whitelist of used XHR response object properties.
  13314. P = ['status', 'statusText', 'responseText', 'responseXML'],
  13315. aH = 'getAllResponseHeaders',
  13316. oH = 'getResponseHeader',
  13317. w = Y.config.win,
  13318. xhr = w.XMLHttpRequest,
  13319. xdr = w.XDomainRequest,
  13320. _i = 0;
  13321. /**
  13322. * The io class is a utility that brokers HTTP requests through a simplified
  13323. * interface. Specifically, it allows JavaScript to make HTTP requests to
  13324. * a resource without a page reload. The underlying transport for making
  13325. * same-domain requests is the XMLHttpRequest object. YUI.io can also use
  13326. * Flash, if specified as a transport, for cross-domain requests.
  13327. *
  13328. * @class IO
  13329. * @constructor
  13330. * @param {object} c - Object of EventTarget's publish method configurations
  13331. * used to configure IO's events.
  13332. */
  13333. function IO (c) {
  13334. var io = this;
  13335. io._uid = 'io:' + _i++;
  13336. io._init(c);
  13337. Y.io._map[io._uid] = io;
  13338. }
  13339. IO.prototype = {
  13340. //--------------------------------------
  13341. // Properties
  13342. //--------------------------------------
  13343. /**
  13344. * @description A counter that increments for each transaction.
  13345. *
  13346. * @property _id
  13347. * @private
  13348. * @type int
  13349. */
  13350. _id: 0,
  13351. /**
  13352. * @description Object of IO HTTP headers sent with each transaction.
  13353. *
  13354. * @property _headers
  13355. * @private
  13356. * @type object
  13357. */
  13358. _headers: {
  13359. 'X-Requested-With' : 'XMLHttpRequest'
  13360. },
  13361. /**
  13362. * @description Object that stores timeout values for any transaction with
  13363. * a defined "timeout" configuration property.
  13364. *
  13365. * @property _timeout
  13366. * @private
  13367. * @type object
  13368. */
  13369. _timeout: {},
  13370. //--------------------------------------
  13371. // Methods
  13372. //--------------------------------------
  13373. _init: function(c) {
  13374. var io = this, i;
  13375. io.cfg = c || {};
  13376. Y.augment(io, Y.EventTarget);
  13377. for (i = 0; i < 5; i++) {
  13378. // Publish IO global events with configurations, if any.
  13379. // IO global events are set to broadcast by default.
  13380. // These events use the "io:" namespace.
  13381. io.publish('io:' + E[i], Y.merge({ broadcast: 1 }, c));
  13382. // Publish IO transaction events with configurations, if
  13383. // any. These events use the "io-trn:" namespace.
  13384. io.publish('io-trn:' + E[i], c);
  13385. }
  13386. },
  13387. /**
  13388. * @description Method that creates a unique transaction object for each
  13389. * request.
  13390. *
  13391. * @method _create
  13392. * @private
  13393. * @param {number} c - configuration object subset to determine if
  13394. * the transaction is an XDR or file upload,
  13395. * requiring an alternate transport.
  13396. * @param {number} i - transaction id
  13397. * @return object
  13398. */
  13399. _create: function(c, i) {
  13400. var io = this,
  13401. o = { id: L.isNumber(i) ? i : io._id++, uid: io._uid },
  13402. x = c.xdr,
  13403. u = x ? x.use : c.form && c.form.upload ? 'iframe' : 'xhr',
  13404. ie = (x && x.use === 'native' && xdr),
  13405. t = io._transport;
  13406. switch (u) {
  13407. case 'native':
  13408. case 'xhr':
  13409. o.c = ie ? new xdr() : xhr ? new xhr() : new ActiveXObject('Microsoft.XMLHTTP');
  13410. o.t = ie ? true : false;
  13411. break;
  13412. default:
  13413. o.c = t ? t[u] : {};
  13414. o.t = true;
  13415. }
  13416. return o;
  13417. },
  13418. _destroy: function(o) {
  13419. if (w) {
  13420. if (xhr && o.t === true) {
  13421. o.c.onreadystatechange = null;
  13422. }
  13423. else if (Y.UA.ie) {
  13424. // IE, when using XMLHttpRequest as an ActiveX Object, will throw
  13425. // a "Type Mismatch" error if the event handler is set to "null".
  13426. o.c.abort();
  13427. }
  13428. }
  13429. o.c = null;
  13430. o = null;
  13431. },
  13432. /**
  13433. * @description Method for creating and firing events.
  13434. *
  13435. * @method _evt
  13436. * @private
  13437. * @param {string} e - event to be published.
  13438. * @param {object} o - transaction object.
  13439. * @param {object} c - configuration data subset for event subscription.
  13440. *
  13441. * @return void
  13442. */
  13443. _evt: function(e, o, c) {
  13444. var io = this,
  13445. a = c['arguments'],
  13446. eF = io.cfg.emitFacade,
  13447. // Use old-style parameters or use an Event Facade
  13448. p = eF ? [{ id: o.id, data: o.c, cfg: c, arguments: a }] : [o.id],
  13449. // IO Global events namespace.
  13450. gE = "io:" + e,
  13451. // IO Transaction events namespace.
  13452. tE = "io-trn:" + e;
  13453. if (!eF) {
  13454. if (e === E[0] || e === E[2]) {
  13455. if (a) {
  13456. p.push(a);
  13457. }
  13458. }
  13459. else {
  13460. a ? p.push(o.c, a) : p.push(o.c);
  13461. }
  13462. }
  13463. p.unshift(gE);
  13464. io.fire.apply(io, p);
  13465. if (c.on) {
  13466. p[0] = tE;
  13467. io.once(tE, c.on[e], c.context || Y);
  13468. io.fire.apply(io, p);
  13469. }
  13470. },
  13471. /**
  13472. * @description Fires event "io:start" and creates, fires a
  13473. * transaction-specific start event, if config.on.start is
  13474. * defined.
  13475. *
  13476. * @method start
  13477. * @public
  13478. * @param {object} o - transaction object.
  13479. * @param {object} c - configuration object for the transaction.
  13480. *
  13481. * @return void
  13482. */
  13483. start: function(o, c) {
  13484. this._evt(E[0], o, c);
  13485. },
  13486. /**
  13487. * @description Fires event "io:complete" and creates, fires a
  13488. * transaction-specific "complete" event, if config.on.complete is
  13489. * defined.
  13490. *
  13491. * @method complete
  13492. * @public
  13493. * @param {object} o - transaction object.
  13494. * @param {object} c - configuration object for the transaction.
  13495. *
  13496. * @return void
  13497. */
  13498. complete: function(o, c) {
  13499. this._evt(E[1], o, c);
  13500. },
  13501. /**
  13502. * @description Fires event "io:end" and creates, fires a
  13503. * transaction-specific "end" event, if config.on.end is
  13504. * defined.
  13505. *
  13506. * @method end
  13507. * @public
  13508. * @param {object} o - transaction object.
  13509. * @param {object} c - configuration object for the transaction.
  13510. *
  13511. * @return void
  13512. */
  13513. end: function(o, c) {
  13514. this._evt(E[2], o, c);
  13515. this._destroy(o);
  13516. },
  13517. /**
  13518. * @description Fires event "io:success" and creates, fires a
  13519. * transaction-specific "success" event, if config.on.success is
  13520. * defined.
  13521. *
  13522. * @method success
  13523. * @public
  13524. * @param {object} o - transaction object.
  13525. * @param {object} c - configuration object for the transaction.
  13526. *
  13527. * @return void
  13528. */
  13529. success: function(o, c) {
  13530. this._evt(E[3], o, c);
  13531. this.end(o, c);
  13532. },
  13533. /**
  13534. * @description Fires event "io:failure" and creates, fires a
  13535. * transaction-specific "failure" event, if config.on.failure is
  13536. * defined.
  13537. *
  13538. * @method failure
  13539. * @public
  13540. * @param {object} o - transaction object.
  13541. * @param {object} c - configuration object for the transaction.
  13542. *
  13543. * @return void
  13544. */
  13545. failure: function(o, c) {
  13546. this._evt(E[4], o, c);
  13547. this.end(o, c);
  13548. },
  13549. /**
  13550. * @description Retry an XDR transaction, using the Flash tranport,
  13551. * if the native transport fails.
  13552. *
  13553. * @method _retry
  13554. * @private
  13555. * @param {object} o - Transaction object generated by _create().
  13556. * @param {string} uri - qualified path to transaction resource.
  13557. * @param {object} c - configuration object for the transaction.
  13558. *
  13559. * @return void
  13560. */
  13561. _retry: function(o, uri, c) {
  13562. this._destroy(o);
  13563. c.xdr.use = 'flash';
  13564. return this.send(uri, c, o.id);
  13565. },
  13566. /**
  13567. * @description Method that concatenates string data for HTTP GET transactions.
  13568. *
  13569. * @method _concat
  13570. * @private
  13571. * @param {string} s - URI or root data.
  13572. * @param {string} d - data to be concatenated onto URI.
  13573. * @return int
  13574. */
  13575. _concat: function(s, d) {
  13576. s += (s.indexOf('?') === -1 ? '?' : '&') + d;
  13577. return s;
  13578. },
  13579. /**
  13580. * @description Method that stores default client headers for all transactions.
  13581. * If a label is passed with no value argument, the header will be deleted.
  13582. *
  13583. * @method _setHeader
  13584. * @private
  13585. * @param {string} l - HTTP header
  13586. * @param {string} v - HTTP header value
  13587. * @return int
  13588. */
  13589. setHeader: function(l, v) {
  13590. if (v) {
  13591. this._headers[l] = v;
  13592. }
  13593. else {
  13594. delete this._headers[l];
  13595. }
  13596. },
  13597. /**
  13598. * @description Method that sets all HTTP headers to be sent in a transaction.
  13599. *
  13600. * @method _setHeaders
  13601. * @private
  13602. * @param {object} o - XHR instance for the specific transaction.
  13603. * @param {object} h - HTTP headers for the specific transaction, as defined
  13604. * in the configuration object passed to YUI.io().
  13605. * @return void
  13606. */
  13607. _setHeaders: function(o, h) {
  13608. h = Y.merge(this._headers, h);
  13609. Y.Object.each(h, function(v, p) {
  13610. if (v !== 'disable') {
  13611. o.setRequestHeader(p, h[p]);
  13612. }
  13613. });
  13614. },
  13615. /**
  13616. * @description Starts timeout count if the configuration object
  13617. * has a defined timeout property.
  13618. *
  13619. * @method _startTimeout
  13620. * @private
  13621. * @param {object} o - Transaction object generated by _create().
  13622. * @param {object} t - Timeout in milliseconds.
  13623. * @return void
  13624. */
  13625. _startTimeout: function(o, t) {
  13626. var io = this;
  13627. io._timeout[o.id] = w.setTimeout(function() { io._abort(o, 'timeout'); }, t);
  13628. },
  13629. /**
  13630. * @description Clears the timeout interval started by _startTimeout().
  13631. *
  13632. * @method _clearTimeout
  13633. * @private
  13634. * @param {number} id - Transaction id.
  13635. * @return void
  13636. */
  13637. _clearTimeout: function(id) {
  13638. w.clearTimeout(this._timeout[id]);
  13639. delete this._timeout[id];
  13640. },
  13641. /**
  13642. * @description Method that determines if a transaction response qualifies
  13643. * as success or failure, based on the response HTTP status code, and
  13644. * fires the appropriate success or failure events.
  13645. *
  13646. * @method _result
  13647. * @private
  13648. * @static
  13649. * @param {object} o - Transaction object generated by _create().
  13650. * @param {object} c - Configuration object passed to io().
  13651. * @return void
  13652. */
  13653. _result: function(o, c) {
  13654. var s = o.c.status;
  13655. // IE reports HTTP 204 as HTTP 1223.
  13656. if (s >= 200 && s < 300 || s === 1223) {
  13657. this.success(o, c);
  13658. }
  13659. else {
  13660. this.failure(o, c);
  13661. }
  13662. },
  13663. /**
  13664. * @description Event handler bound to onreadystatechange.
  13665. *
  13666. * @method _rS
  13667. * @private
  13668. * @param {object} o - Transaction object generated by _create().
  13669. * @param {object} c - Configuration object passed to YUI.io().
  13670. * @return void
  13671. */
  13672. _rS: function(o, c) {
  13673. var io = this;
  13674. if (o.c.readyState === 4) {
  13675. if (c.timeout) {
  13676. io._clearTimeout(o.id);
  13677. }
  13678. // Yield in the event of request timeout or abort.
  13679. w.setTimeout(function() { io.complete(o, c); io._result(o, c); }, 0);
  13680. }
  13681. },
  13682. /**
  13683. * @description Terminates a transaction due to an explicit abort or
  13684. * timeout.
  13685. *
  13686. * @method _abort
  13687. * @private
  13688. * @param {object} o - Transaction object generated by _create().
  13689. * @param {string} s - Identifies timed out or aborted transaction.
  13690. *
  13691. * @return void
  13692. */
  13693. _abort: function(o, s) {
  13694. if (o && o.c) {
  13695. o.e = s;
  13696. o.c.abort();
  13697. }
  13698. },
  13699. /**
  13700. * @description Method for requesting a transaction. send() is implemented as
  13701. * yui.io(). Each transaction may include a configuration object. Its
  13702. * properties are:
  13703. *
  13704. * method: HTTP method verb (e.g., GET or POST). If this property is not
  13705. * not defined, the default value will be GET.
  13706. *
  13707. * data: This is the name-value string that will be sent as the transaction
  13708. * data. If the request is HTTP GET, the data become part of
  13709. * querystring. If HTTP POST, the data are sent in the message body.
  13710. *
  13711. * xdr: Defines the transport to be used for cross-domain requests. By
  13712. * setting this property, the transaction will use the specified
  13713. * transport instead of XMLHttpRequest.
  13714. * The properties are:
  13715. * {
  13716. * use: Specify the transport to be used: 'flash' and 'native'
  13717. * dataType: Set the value to 'XML' if that is the expected
  13718. * response content type.
  13719. * }
  13720. *
  13721. *
  13722. * form: This is a defined object used to process HTML form as data. The
  13723. * properties are:
  13724. * {
  13725. * id: Node object or id of HTML form.
  13726. * useDisabled: Boolean value to allow disabled HTML form field
  13727. * values to be sent as part of the data.
  13728. * }
  13729. *
  13730. * on: This is a defined object used to create and handle specific
  13731. * events during a transaction lifecycle. These events will fire in
  13732. * addition to the global io events. The events are:
  13733. * start - This event is fired when a request is sent to a resource.
  13734. * complete - This event fires when the transaction is complete.
  13735. * success - This event fires when the response status resolves to
  13736. * HTTP 2xx.
  13737. * failure - This event fires when the response status resolves to
  13738. * HTTP 4xx, 5xx; and, for all transaction exceptions,
  13739. * including aborted transactions and transaction timeouts.
  13740. * end - This even is fired at the conclusion of the transaction
  13741. * lifecycle, after a success or failure resolution.
  13742. *
  13743. * The properties are:
  13744. * {
  13745. * start: function(id, arguments){},
  13746. * complete: function(id, responseobject, arguments){},
  13747. * success: function(id, responseobject, arguments){},
  13748. * failure: function(id, responseobject, arguments){},
  13749. * end: function(id, arguments){}
  13750. * }
  13751. * Each property can reference a function or be written as an
  13752. * inline function.
  13753. *
  13754. * sync: To enable synchronous transactions, set the configuration property
  13755. * "sync" to true. Synchronous requests are limited to same-domain
  13756. * requests only.
  13757. *
  13758. * context: Object reference for all defined transaction event handlers
  13759. * when it is implemented as a method of a base object. Defining
  13760. * "context" will set the reference of "this," used in the
  13761. * event handlers, to the context value. In the case where
  13762. * different event handlers all have different contexts,
  13763. * use Y.bind() to set the execution context, instead.
  13764. *
  13765. * headers: This is a defined object of client headers, as many as
  13766. * desired for this specific transaction. The object pattern is:
  13767. * { 'header': 'value' }.
  13768. *
  13769. * timeout: This value, defined as milliseconds, is a time threshold for the
  13770. * transaction. When this threshold is reached, and the transaction's
  13771. * Complete event has not yet fired, the transaction will be aborted.
  13772. *
  13773. * arguments: User-defined data passed to all registered event handlers.
  13774. * This value is available as the second argument in the "start"
  13775. * and "end" event handlers. It is the third argument in the
  13776. * "complete", "success", and "failure" event handlers.
  13777. *
  13778. * @method send
  13779. * @private
  13780. * @
  13781. * @param {string} uri - qualified path to transaction resource.
  13782. * @param {object} c - configuration object for the transaction.
  13783. * @param {number} i - transaction id, if already set.
  13784. * @return object
  13785. */
  13786. send: function(uri, c, i) {
  13787. var o, m, r, s, d, io = this,
  13788. u = uri;
  13789. c = c ? Y.Object(c) : {};
  13790. o = io._create(c, i);
  13791. m = c.method ? c.method.toUpperCase() : 'GET';
  13792. s = c.sync;
  13793. d = c.data;
  13794. // Serialize an object into a key-value string using
  13795. // querystring-stringify-simple.
  13796. if (L.isObject(d)) {
  13797. d = Y.QueryString.stringify(d);
  13798. }
  13799. if (c.form) {
  13800. if (c.form.upload) {
  13801. // This is a file upload transaction, calling
  13802. // upload() in io-upload-iframe.
  13803. return io.upload(o, uri, c);
  13804. }
  13805. else {
  13806. // Serialize HTML form data into a key-value string.
  13807. d = io._serialize(c.form, d);
  13808. }
  13809. }
  13810. if (d) {
  13811. switch (m) {
  13812. case 'GET':
  13813. case 'HEAD':
  13814. case 'DELETE':
  13815. u = io._concat(u, d);
  13816. d = '';
  13817. Y.log('HTTP' + m + ' with data. The querystring is: ' + u, 'info', 'io');
  13818. break;
  13819. case 'POST':
  13820. case 'PUT':
  13821. // If Content-Type is defined in the configuration object, or
  13822. // or as a default header, it will be used instead of
  13823. // 'application/x-www-form-urlencoded; charset=UTF-8'
  13824. c.headers = Y.merge({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, c.headers);
  13825. break;
  13826. }
  13827. }
  13828. if (o.t) {
  13829. // Cross-domain request or custom transport configured.
  13830. return io.xdr(u, o, c);
  13831. }
  13832. if (!s) {
  13833. o.c.onreadystatechange = function() { io._rS(o, c); };
  13834. }
  13835. try {
  13836. // Determine if request is to be set as
  13837. // synchronous or asynchronous.
  13838. o.c.open(m, u, s ? false : true, c.username || null, c.password || null);
  13839. io._setHeaders(o.c, c.headers || {});
  13840. io.start(o, c);
  13841. // Will work only in browsers that implement the
  13842. // Cross-Origin Resource Sharing draft.
  13843. if (c.xdr && c.xdr.credentials) {
  13844. if (!Y.UA.ie) {
  13845. o.c.withCredentials = true;
  13846. }
  13847. }
  13848. // Using "null" with HTTP POST will result in a request
  13849. // with no Content-Length header defined.
  13850. o.c.send(d);
  13851. if (s) {
  13852. // Create a response object for synchronous transactions,
  13853. // mixing id and arguments properties with the xhr
  13854. // properties whitelist.
  13855. r = Y.mix({ id: o.id, 'arguments': c['arguments'] }, o.c, false, P);
  13856. r[aH] = function() { return o.c[aH](); };
  13857. r[oH] = function(h) { return o.c[oH](h); };
  13858. io.complete(o, c);
  13859. io._result(o, c);
  13860. return r;
  13861. }
  13862. }
  13863. catch(e) {
  13864. if (o.t) {
  13865. // This exception is usually thrown by browsers
  13866. // that do not support XMLHttpRequest Level 2.
  13867. // Retry the request with the XDR transport set
  13868. // to 'flash'. If the Flash transport is not
  13869. // initialized or available, the transaction
  13870. // will resolve to a transport error.
  13871. return io._retry(o, uri, c);
  13872. }
  13873. else {
  13874. io.complete(o, c);
  13875. io._result(o, c);
  13876. }
  13877. }
  13878. // If config.timeout is defined, and the request is standard XHR,
  13879. // initialize timeout polling.
  13880. if (c.timeout) {
  13881. io._startTimeout(o, c.timeout);
  13882. Y.log('Configuration timeout set to: ' + c.timeout, 'info', 'io');
  13883. }
  13884. return {
  13885. id: o.id,
  13886. abort: function() {
  13887. return o.c ? io._abort(o, 'abort') : false;
  13888. },
  13889. isInProgress: function() {
  13890. return o.c ? o.c.readyState !== 4 && o.c.readyState !== 0 : false;
  13891. },
  13892. io: io
  13893. };
  13894. }
  13895. };
  13896. /**
  13897. * @description Method for requesting a transaction.
  13898. *
  13899. * @method io
  13900. * @public
  13901. * @static
  13902. * @param {string} u - qualified path to transaction resource.
  13903. * @param {object} c - configuration object for the transaction.
  13904. * @return object
  13905. */
  13906. Y.io = function(u, c) {
  13907. // Calling IO through the static interface will use and reuse
  13908. // an instance of IO.
  13909. var o = Y.io._map['io:0'] || new IO();
  13910. return o.send.apply(o, [u, c]);
  13911. };
  13912. Y.IO = IO;
  13913. // Map of all IO instances created.
  13914. Y.io._map = {};
  13915. }, '3.4.0' ,{requires:['event-custom-base', 'querystring-stringify-simple']});
  13916. YUI.add('json-parse', function(Y) {
  13917. /**
  13918. * <p>The JSON module adds support for serializing JavaScript objects into
  13919. * JSON strings and parsing JavaScript objects from strings in JSON format.</p>
  13920. *
  13921. * <p>The JSON namespace is added to your YUI instance including static methods
  13922. * Y.JSON.parse(..) and Y.JSON.stringify(..).</p>
  13923. *
  13924. * <p>The functionality and method signatures follow the ECMAScript 5
  13925. * specification. In browsers with native JSON support, the native
  13926. * implementation is used.</p>
  13927. *
  13928. * <p>The <code>json</code> module is a rollup of <code>json-parse</code> and
  13929. * <code>json-stringify</code>.</p>
  13930. *
  13931. * <p>As their names suggest, <code>json-parse</code> adds support for parsing
  13932. * JSON data (Y.JSON.parse) and <code>json-stringify</code> for serializing
  13933. * JavaScript data into JSON strings (Y.JSON.stringify). You may choose to
  13934. * include either of the submodules individually if you don't need the
  13935. * complementary functionality, or include the rollup for both.</p>
  13936. *
  13937. * @module json
  13938. * @class JSON
  13939. * @static
  13940. */
  13941. /**
  13942. * Provides Y.JSON.parse method to accept JSON strings and return native
  13943. * JavaScript objects.
  13944. *
  13945. * @module json
  13946. * @submodule json-parse
  13947. * @for JSON
  13948. * @static
  13949. */
  13950. // All internals kept private for security reasons
  13951. function fromGlobal(ref) {
  13952. return (Y.config.win || this || {})[ref];
  13953. }
  13954. /**
  13955. * Alias to native browser implementation of the JSON object if available.
  13956. *
  13957. * @property Native
  13958. * @type {Object}
  13959. * @private
  13960. */
  13961. var _JSON = fromGlobal('JSON'),
  13962. Native = (Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON),
  13963. useNative = !!Native,
  13964. /**
  13965. * Replace certain Unicode characters that JavaScript may handle incorrectly
  13966. * during eval--either by deleting them or treating them as line
  13967. * endings--with escape sequences.
  13968. * IMPORTANT NOTE: This regex will be used to modify the input if a match is
  13969. * found.
  13970. *
  13971. * @property _UNICODE_EXCEPTIONS
  13972. * @type {RegExp}
  13973. * @private
  13974. */
  13975. _UNICODE_EXCEPTIONS = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
  13976. /**
  13977. * First step in the safety evaluation. Regex used to replace all escape
  13978. * sequences (i.e. "\\", etc) with '@' characters (a non-JSON character).
  13979. *
  13980. * @property _ESCAPES
  13981. * @type {RegExp}
  13982. * @private
  13983. */
  13984. _ESCAPES = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
  13985. /**
  13986. * Second step in the safety evaluation. Regex used to replace all simple
  13987. * values with ']' characters.
  13988. *
  13989. * @property _VALUES
  13990. * @type {RegExp}
  13991. * @private
  13992. */
  13993. _VALUES = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
  13994. /**
  13995. * Third step in the safety evaluation. Regex used to remove all open
  13996. * square brackets following a colon, comma, or at the beginning of the
  13997. * string.
  13998. *
  13999. * @property _BRACKETS
  14000. * @type {RegExp}
  14001. * @private
  14002. */
  14003. _BRACKETS = /(?:^|:|,)(?:\s*\[)+/g,
  14004. /**
  14005. * Final step in the safety evaluation. Regex used to test the string left
  14006. * after all previous replacements for invalid characters.
  14007. *
  14008. * @property _UNSAFE
  14009. * @type {RegExp}
  14010. * @private
  14011. */
  14012. _UNSAFE = /[^\],:{}\s]/,
  14013. /**
  14014. * Replaces specific unicode characters with their appropriate \unnnn
  14015. * format. Some browsers ignore certain characters during eval.
  14016. *
  14017. * @method escapeException
  14018. * @param c {String} Unicode character
  14019. * @return {String} the \unnnn escapement of the character
  14020. * @private
  14021. */
  14022. _escapeException = function (c) {
  14023. return '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4);
  14024. },
  14025. /**
  14026. * Traverses nested objects, applying a reviver function to each (key,value)
  14027. * from the scope if the key:value's containing object. The value returned
  14028. * from the function will replace the original value in the key:value pair.
  14029. * If the value returned is undefined, the key will be omitted from the
  14030. * returned object.
  14031. *
  14032. * @method _revive
  14033. * @param data {MIXED} Any JavaScript data
  14034. * @param reviver {Function} filter or mutation function
  14035. * @return {MIXED} The results of the filtered data
  14036. * @private
  14037. */
  14038. _revive = function (data, reviver) {
  14039. var walk = function (o,key) {
  14040. var k,v,value = o[key];
  14041. if (value && typeof value === 'object') {
  14042. for (k in value) {
  14043. if (value.hasOwnProperty(k)) {
  14044. v = walk(value, k);
  14045. if (v === undefined) {
  14046. delete value[k];
  14047. } else {
  14048. value[k] = v;
  14049. }
  14050. }
  14051. }
  14052. }
  14053. return reviver.call(o,key,value);
  14054. };
  14055. return typeof reviver === 'function' ? walk({'':data},'') : data;
  14056. },
  14057. /**
  14058. * Parse a JSON string, returning the native JavaScript representation.
  14059. *
  14060. * @param s {string} JSON string data
  14061. * @param reviver {function} (optional) function(k,v) passed each key value
  14062. * pair of object literals, allowing pruning or altering values
  14063. * @return {MIXED} the native JavaScript representation of the JSON string
  14064. * @throws SyntaxError
  14065. * @method parse
  14066. * @static
  14067. */
  14068. // JavaScript implementation in lieu of native browser support. Based on
  14069. // the json2.js library from http://json.org
  14070. _parse = function (s,reviver) {
  14071. // Replace certain Unicode characters that are otherwise handled
  14072. // incorrectly by some browser implementations.
  14073. // NOTE: This modifies the input if such characters are found!
  14074. s = s.replace(_UNICODE_EXCEPTIONS, _escapeException);
  14075. // Test for any remaining invalid characters
  14076. if (!_UNSAFE.test(s.replace(_ESCAPES,'@').
  14077. replace(_VALUES,']').
  14078. replace(_BRACKETS,''))) {
  14079. // Eval the text into a JavaScript data structure, apply any
  14080. // reviver function, and return
  14081. return _revive( eval('(' + s + ')'), reviver );
  14082. }
  14083. throw new SyntaxError('JSON.parse');
  14084. };
  14085. Y.namespace('JSON').parse = function (s,reviver) {
  14086. if (typeof s !== 'string') {
  14087. s += '';
  14088. }
  14089. return Native && Y.JSON.useNativeParse ?
  14090. Native.parse(s,reviver) : _parse(s,reviver);
  14091. };
  14092. function workingNative( k, v ) {
  14093. return k === "ok" ? true : v;
  14094. }
  14095. // Double check basic functionality. This is mainly to catch early broken
  14096. // implementations of the JSON API in Firefox 3.1 beta1 and beta2
  14097. if ( Native ) {
  14098. try {
  14099. useNative = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
  14100. }
  14101. catch ( e ) {
  14102. useNative = false;
  14103. }
  14104. }
  14105. /**
  14106. * Leverage native JSON parse if the browser has a native implementation.
  14107. * In general, this is a good idea. See the Known Issues section in the
  14108. * JSON user guide for caveats. The default value is true for browsers with
  14109. * native JSON support.
  14110. *
  14111. * @property useNativeParse
  14112. * @type Boolean
  14113. * @default true
  14114. * @static
  14115. */
  14116. Y.JSON.useNativeParse = useNative;
  14117. }, '3.4.0' );
  14118. YUI.add('transition', function(Y) {
  14119. /**
  14120. * Provides the transition method for Node.
  14121. * Transition has no API of its own, but adds the transition method to Node.
  14122. *
  14123. * @module transition
  14124. * @requires node-style
  14125. */
  14126. var CAMEL_VENDOR_PREFIX = '',
  14127. VENDOR_PREFIX = '',
  14128. DOCUMENT = Y.config.doc,
  14129. DOCUMENT_ELEMENT = 'documentElement',
  14130. TRANSITION = 'transition',
  14131. TRANSITION_CAMEL = 'Transition',
  14132. TRANSITION_PROPERTY_CAMEL,
  14133. TRANSITION_PROPERTY,
  14134. TRANSITION_DURATION,
  14135. TRANSITION_TIMING_FUNCTION,
  14136. TRANSITION_DELAY,
  14137. TRANSITION_END,
  14138. ON_TRANSITION_END,
  14139. TRANSFORM_CAMEL,
  14140. EMPTY_OBJ = {},
  14141. VENDORS = [
  14142. 'Webkit',
  14143. 'Moz'
  14144. ],
  14145. VENDOR_TRANSITION_END = {
  14146. Webkit: 'webkitTransitionEnd'
  14147. },
  14148. /**
  14149. * A class for constructing transition instances.
  14150. * Adds the "transition" method to Node.
  14151. * @class Transition
  14152. * @constructor
  14153. */
  14154. Transition = function() {
  14155. this.init.apply(this, arguments);
  14156. };
  14157. Transition._toCamel = function(property) {
  14158. property = property.replace(/-([a-z])/gi, function(m0, m1) {
  14159. return m1.toUpperCase();
  14160. });
  14161. return property;
  14162. };
  14163. Transition._toHyphen = function(property) {
  14164. property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) {
  14165. var str = ((m1) ? '-' + m1.toLowerCase() : '') + m2;
  14166. if (m3) {
  14167. str += '-' + m3.toLowerCase();
  14168. }
  14169. return str;
  14170. });
  14171. return property;
  14172. };
  14173. Transition.SHOW_TRANSITION = 'fadeIn';
  14174. Transition.HIDE_TRANSITION = 'fadeOut';
  14175. Transition.useNative = false;
  14176. Y.Array.each(VENDORS, function(val) { // then vendor specific
  14177. var property = val + TRANSITION_CAMEL;
  14178. if (property in DOCUMENT[DOCUMENT_ELEMENT].style) {
  14179. CAMEL_VENDOR_PREFIX = val;
  14180. VENDOR_PREFIX = Transition._toHyphen(val) + '-';
  14181. Transition.useNative = true;
  14182. Transition.supported = true; // TODO: remove
  14183. Transition._VENDOR_PREFIX = val;
  14184. }
  14185. });
  14186. TRANSITION_CAMEL = CAMEL_VENDOR_PREFIX + TRANSITION_CAMEL;
  14187. TRANSITION_PROPERTY_CAMEL = CAMEL_VENDOR_PREFIX + 'TransitionProperty';
  14188. TRANSITION_PROPERTY = VENDOR_PREFIX + 'transition-property';
  14189. TRANSITION_DURATION = VENDOR_PREFIX + 'transition-duration';
  14190. TRANSITION_TIMING_FUNCTION = VENDOR_PREFIX + 'transition-timing-function';
  14191. TRANSITION_DELAY = VENDOR_PREFIX + 'transition-delay';
  14192. TRANSITION_END = 'transitionend';
  14193. ON_TRANSITION_END = 'on' + CAMEL_VENDOR_PREFIX.toLowerCase() + 'transitionend';
  14194. TRANSITION_END = VENDOR_TRANSITION_END[CAMEL_VENDOR_PREFIX] || TRANSITION_END;
  14195. TRANSFORM_CAMEL = CAMEL_VENDOR_PREFIX + 'Transform';
  14196. Transition.fx = {};
  14197. Transition.toggles = {};
  14198. Transition._hasEnd = {};
  14199. Transition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i;
  14200. Y.Node.DOM_EVENTS[TRANSITION_END] = 1;
  14201. Transition.NAME = 'transition';
  14202. Transition.DEFAULT_EASING = 'ease';
  14203. Transition.DEFAULT_DURATION = 0.5;
  14204. Transition.DEFAULT_DELAY = 0;
  14205. Transition._nodeAttrs = {};
  14206. Transition.prototype = {
  14207. constructor: Transition,
  14208. init: function(node, config) {
  14209. var anim = this;
  14210. anim._node = node;
  14211. if (!anim._running && config) {
  14212. anim._config = config;
  14213. node._transition = anim; // cache for reuse
  14214. anim._duration = ('duration' in config) ?
  14215. config.duration: anim.constructor.DEFAULT_DURATION;
  14216. anim._delay = ('delay' in config) ?
  14217. config.delay: anim.constructor.DEFAULT_DELAY;
  14218. anim._easing = config.easing || anim.constructor.DEFAULT_EASING;
  14219. anim._count = 0; // track number of animated properties
  14220. anim._running = false;
  14221. }
  14222. return anim;
  14223. },
  14224. addProperty: function(prop, config) {
  14225. var anim = this,
  14226. node = this._node,
  14227. uid = Y.stamp(node),
  14228. nodeInstance = Y.one(node),
  14229. attrs = Transition._nodeAttrs[uid],
  14230. computed,
  14231. compareVal,
  14232. dur,
  14233. attr,
  14234. val;
  14235. if (!attrs) {
  14236. attrs = Transition._nodeAttrs[uid] = {};
  14237. }
  14238. attr = attrs[prop];
  14239. // might just be a value
  14240. if (config && config.value !== undefined) {
  14241. val = config.value;
  14242. } else if (config !== undefined) {
  14243. val = config;
  14244. config = EMPTY_OBJ;
  14245. }
  14246. if (typeof val === 'function') {
  14247. val = val.call(nodeInstance, nodeInstance);
  14248. }
  14249. if (attr && attr.transition) {
  14250. // take control if another transition owns this property
  14251. if (attr.transition !== anim) {
  14252. attr.transition._count--; // remapping attr to this transition
  14253. }
  14254. }
  14255. anim._count++; // properties per transition
  14256. // make 0 async and fire events
  14257. dur = ((typeof config.duration != 'undefined') ? config.duration :
  14258. anim._duration) || 0.0001;
  14259. attrs[prop] = {
  14260. value: val,
  14261. duration: dur,
  14262. delay: (typeof config.delay != 'undefined') ? config.delay :
  14263. anim._delay,
  14264. easing: config.easing || anim._easing,
  14265. transition: anim
  14266. };
  14267. // native end event doesnt fire when setting to same value
  14268. // supplementing with timer
  14269. // val may be a string or number (height: 0, etc), but computedStyle is always string
  14270. computed = Y.DOM.getComputedStyle(node, prop);
  14271. compareVal = (typeof val === 'string') ? computed : parseFloat(computed);
  14272. if (Transition.useNative && compareVal === val) {
  14273. setTimeout(function() {
  14274. anim._onNativeEnd.call(node, {
  14275. propertyName: prop,
  14276. elapsedTime: dur
  14277. });
  14278. }, dur * 1000);
  14279. }
  14280. },
  14281. removeProperty: function(prop) {
  14282. var anim = this,
  14283. attrs = Transition._nodeAttrs[Y.stamp(anim._node)];
  14284. if (attrs && attrs[prop]) {
  14285. delete attrs[prop];
  14286. anim._count--;
  14287. }
  14288. },
  14289. initAttrs: function(config) {
  14290. var attr,
  14291. node = this._node;
  14292. if (config.transform && !config[TRANSFORM_CAMEL]) {
  14293. config[TRANSFORM_CAMEL] = config.transform;
  14294. delete config.transform; // TODO: copy
  14295. }
  14296. for (attr in config) {
  14297. if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) {
  14298. this.addProperty(attr, config[attr]);
  14299. // when size is auto or % webkit starts from zero instead of computed
  14300. // (https://bugs.webkit.org/show_bug.cgi?id=16020)
  14301. // TODO: selective set
  14302. if (node.style[attr] === '') {
  14303. Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr));
  14304. }
  14305. }
  14306. }
  14307. },
  14308. /**
  14309. * Starts or an animation.
  14310. * @method run
  14311. * @chainable
  14312. * @private
  14313. */
  14314. run: function(callback) {
  14315. var anim = this,
  14316. node = anim._node,
  14317. config = anim._config,
  14318. data = {
  14319. type: 'transition:start',
  14320. config: config
  14321. };
  14322. if (!anim._running) {
  14323. anim._running = true;
  14324. //anim._node.fire('transition:start', data);
  14325. if (config.on && config.on.start) {
  14326. config.on.start.call(Y.one(node), data);
  14327. }
  14328. anim.initAttrs(anim._config);
  14329. anim._callback = callback;
  14330. anim._start();
  14331. }
  14332. return anim;
  14333. },
  14334. _start: function() {
  14335. this._runNative();
  14336. },
  14337. _prepDur: function(dur) {
  14338. dur = parseFloat(dur);
  14339. return dur + 's';
  14340. },
  14341. _runNative: function(time) {
  14342. var anim = this,
  14343. node = anim._node,
  14344. uid = Y.stamp(node),
  14345. style = node.style,
  14346. computed = getComputedStyle(node),
  14347. attrs = Transition._nodeAttrs[uid],
  14348. cssText = '',
  14349. cssTransition = computed[Transition._toCamel(TRANSITION_PROPERTY)],
  14350. transitionText = TRANSITION_PROPERTY + ': ',
  14351. duration = TRANSITION_DURATION + ': ',
  14352. easing = TRANSITION_TIMING_FUNCTION + ': ',
  14353. delay = TRANSITION_DELAY + ': ',
  14354. hyphy,
  14355. attr,
  14356. name;
  14357. // preserve existing transitions
  14358. if (cssTransition !== 'all') {
  14359. transitionText += cssTransition + ',';
  14360. duration += computed[Transition._toCamel(TRANSITION_DURATION)] + ',';
  14361. easing += computed[Transition._toCamel(TRANSITION_TIMING_FUNCTION)] + ',';
  14362. delay += computed[Transition._toCamel(TRANSITION_DELAY)] + ',';
  14363. }
  14364. // run transitions mapped to this instance
  14365. for (name in attrs) {
  14366. hyphy = Transition._toHyphen(name);
  14367. attr = attrs[name];
  14368. if ((attr = attrs[name]) && attr.transition === anim) {
  14369. if (name in node.style) { // only native styles allowed
  14370. duration += anim._prepDur(attr.duration) + ',';
  14371. delay += anim._prepDur(attr.delay) + ',';
  14372. easing += (attr.easing) + ',';
  14373. transitionText += hyphy + ',';
  14374. cssText += hyphy + ': ' + attr.value + '; ';
  14375. } else {
  14376. this.removeProperty(name);
  14377. }
  14378. }
  14379. }
  14380. transitionText = transitionText.replace(/,$/, ';');
  14381. duration = duration.replace(/,$/, ';');
  14382. easing = easing.replace(/,$/, ';');
  14383. delay = delay.replace(/,$/, ';');
  14384. // only one native end event per node
  14385. if (!Transition._hasEnd[uid]) {
  14386. //anim._detach = Y.on(TRANSITION_END, anim._onNativeEnd, node);
  14387. //node[ON_TRANSITION_END] = anim._onNativeEnd;
  14388. node.addEventListener(TRANSITION_END, anim._onNativeEnd, '');
  14389. Transition._hasEnd[uid] = true;
  14390. }
  14391. //setTimeout(function() { // allow updates to apply (size fix, onstart, etc)
  14392. style.cssText += transitionText + duration + easing + delay + cssText;
  14393. //}, 1);
  14394. },
  14395. _end: function(elapsed) {
  14396. var anim = this,
  14397. node = anim._node,
  14398. callback = anim._callback,
  14399. config = anim._config,
  14400. data = {
  14401. type: 'transition:end',
  14402. config: config,
  14403. elapsedTime: elapsed
  14404. },
  14405. nodeInstance = Y.one(node);
  14406. anim._running = false;
  14407. anim._callback = null;
  14408. if (node) {
  14409. if (config.on && config.on.end) {
  14410. setTimeout(function() { // IE: allow previous update to finish
  14411. config.on.end.call(nodeInstance, data);
  14412. // nested to ensure proper fire order
  14413. if (callback) {
  14414. callback.call(nodeInstance, data);
  14415. }
  14416. }, 1);
  14417. } else if (callback) {
  14418. setTimeout(function() { // IE: allow previous update to finish
  14419. callback.call(nodeInstance, data);
  14420. }, 1);
  14421. }
  14422. //node.fire('transition:end', data);
  14423. }
  14424. },
  14425. _endNative: function(name) {
  14426. var node = this._node,
  14427. value = node.ownerDocument.defaultView.getComputedStyle(node, '')[Transition._toCamel(TRANSITION_PROPERTY)];
  14428. if (typeof value === 'string') {
  14429. value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ',');
  14430. value = value.replace(/^,|,$/, '');
  14431. node.style[TRANSITION_CAMEL] = value;
  14432. }
  14433. },
  14434. _onNativeEnd: function(e) {
  14435. var node = this,
  14436. uid = Y.stamp(node),
  14437. event = e,//e._event,
  14438. name = Transition._toCamel(event.propertyName),
  14439. elapsed = event.elapsedTime,
  14440. attrs = Transition._nodeAttrs[uid],
  14441. attr = attrs[name],
  14442. anim = (attr) ? attr.transition : null,
  14443. data,
  14444. config;
  14445. if (anim) {
  14446. anim.removeProperty(name);
  14447. anim._endNative(name);
  14448. config = anim._config[name];
  14449. data = {
  14450. type: 'propertyEnd',
  14451. propertyName: name,
  14452. elapsedTime: elapsed,
  14453. config: config
  14454. };
  14455. if (config && config.on && config.on.end) {
  14456. config.on.end.call(Y.one(node), data);
  14457. }
  14458. //node.fire('transition:propertyEnd', data);
  14459. if (anim._count <= 0) { // after propertyEnd fires
  14460. anim._end(elapsed);
  14461. }
  14462. }
  14463. },
  14464. destroy: function() {
  14465. var anim = this,
  14466. node = anim._node;
  14467. /*
  14468. if (anim._detach) {
  14469. anim._detach.detach();
  14470. }
  14471. */
  14472. //anim._node[ON_TRANSITION_END] = null;
  14473. if (node) {
  14474. node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false);
  14475. anim._node = null;
  14476. }
  14477. }
  14478. };
  14479. Y.Transition = Transition;
  14480. Y.TransitionNative = Transition; // TODO: remove
  14481. /**
  14482. * Animate one or more css properties to a given value. Requires the "transition" module.
  14483. * <pre>example usage:
  14484. * Y.one('#demo').transition({
  14485. * duration: 1, // in seconds, default is 0.5
  14486. * easing: 'ease-out', // default is 'ease'
  14487. * delay: '1', // delay start for 1 second, default is 0
  14488. *
  14489. * height: '10px',
  14490. * width: '10px',
  14491. *
  14492. * opacity: { // per property
  14493. * value: 0,
  14494. * duration: 2,
  14495. * delay: 2,
  14496. * easing: 'ease-in'
  14497. * }
  14498. * });
  14499. * </pre>
  14500. * @for Node
  14501. * @method transition
  14502. * @param {Object} config An object containing one or more style properties, a duration and an easing.
  14503. * @param {Function} callback A function to run after the transition has completed.
  14504. * @chainable
  14505. */
  14506. Y.Node.prototype.transition = function(name, config, callback) {
  14507. var
  14508. transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)],
  14509. anim = (transitionAttrs) ? transitionAttrs.transition || null : null,
  14510. fxConfig,
  14511. prop;
  14512. if (typeof name === 'string') { // named effect, pull config from registry
  14513. if (typeof config === 'function') {
  14514. callback = config;
  14515. config = null;
  14516. }
  14517. fxConfig = Transition.fx[name];
  14518. if (config && typeof config !== 'boolean') {
  14519. config = Y.clone(config);
  14520. for (prop in fxConfig) {
  14521. if (fxConfig.hasOwnProperty(prop)) {
  14522. if (! (prop in config)) {
  14523. config[prop] = fxConfig[prop];
  14524. }
  14525. }
  14526. }
  14527. } else {
  14528. config = fxConfig;
  14529. }
  14530. } else { // name is a config, config is a callback or undefined
  14531. callback = config;
  14532. config = name;
  14533. }
  14534. if (anim && !anim._running) {
  14535. anim.init(this, config);
  14536. } else {
  14537. anim = new Transition(this._node, config);
  14538. }
  14539. anim.run(callback);
  14540. return this;
  14541. };
  14542. Y.Node.prototype.show = function(name, config, callback) {
  14543. this._show(); // show prior to transition
  14544. if (name && Y.Transition) {
  14545. if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
  14546. if (typeof config === 'function') {
  14547. callback = config;
  14548. config = name;
  14549. }
  14550. name = Transition.SHOW_TRANSITION;
  14551. }
  14552. this.transition(name, config, callback);
  14553. }
  14554. else if (name && !Y.Transition) { Y.log('unable to transition show; missing transition module', 'warn', 'node'); }
  14555. return this;
  14556. };
  14557. var _wrapCallBack = function(anim, fn, callback) {
  14558. return function() {
  14559. if (fn) {
  14560. fn.call(anim);
  14561. }
  14562. if (callback) {
  14563. callback.apply(anim._node, arguments);
  14564. }
  14565. };
  14566. };
  14567. Y.Node.prototype.hide = function(name, config, callback) {
  14568. if (name && Y.Transition) {
  14569. if (typeof config === 'function') {
  14570. callback = config;
  14571. config = null;
  14572. }
  14573. callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback
  14574. if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
  14575. if (typeof config === 'function') {
  14576. callback = config;
  14577. config = name;
  14578. }
  14579. name = Transition.HIDE_TRANSITION;
  14580. }
  14581. this.transition(name, config, callback);
  14582. } else if (name && !Y.Transition) { Y.log('unable to transition hide; missing transition module', 'warn', 'node'); // end if on nex
  14583. } else {
  14584. this._hide();
  14585. }
  14586. return this;
  14587. };
  14588. /**
  14589. * Animate one or more css properties to a given value. Requires the "transition" module.
  14590. * <pre>example usage:
  14591. * Y.all('.demo').transition({
  14592. * duration: 1, // in seconds, default is 0.5
  14593. * easing: 'ease-out', // default is 'ease'
  14594. * delay: '1', // delay start for 1 second, default is 0
  14595. *
  14596. * height: '10px',
  14597. * width: '10px',
  14598. *
  14599. * opacity: { // per property
  14600. * value: 0,
  14601. * duration: 2,
  14602. * delay: 2,
  14603. * easing: 'ease-in'
  14604. * }
  14605. * });
  14606. * </pre>
  14607. * @for NodeList
  14608. * @method transition
  14609. * @param {Object} config An object containing one or more style properties, a duration and an easing.
  14610. * @param {Function} callback A function to run after the transition has completed. The callback fires
  14611. * once per item in the NodeList.
  14612. * @chainable
  14613. */
  14614. Y.NodeList.prototype.transition = function(config, callback) {
  14615. var nodes = this._nodes,
  14616. i = 0,
  14617. node;
  14618. while ((node = nodes[i++])) {
  14619. Y.one(node).transition(config, callback);
  14620. }
  14621. return this;
  14622. };
  14623. Y.Node.prototype.toggleView = function(name, on, callback) {
  14624. this._toggles = this._toggles || [];
  14625. callback = arguments[arguments.length - 1];
  14626. if (typeof name == 'boolean') { // no transition, just toggle
  14627. on = name;
  14628. name = null;
  14629. }
  14630. name = name || Y.Transition.DEFAULT_TOGGLE;
  14631. if (typeof on == 'undefined' && name in this._toggles) { // reverse current toggle
  14632. on = ! this._toggles[name];
  14633. }
  14634. on = (on) ? 1 : 0;
  14635. if (on) {
  14636. this._show();
  14637. } else {
  14638. callback = _wrapCallBack(this, this._hide, callback);
  14639. }
  14640. this._toggles[name] = on;
  14641. this.transition(Y.Transition.toggles[name][on], callback);
  14642. return this;
  14643. };
  14644. Y.NodeList.prototype.toggleView = function(name, on, callback) {
  14645. var nodes = this._nodes,
  14646. i = 0,
  14647. node;
  14648. while ((node = nodes[i++])) {
  14649. Y.one(node).toggleView(name, on, callback);
  14650. }
  14651. return this;
  14652. };
  14653. Y.mix(Transition.fx, {
  14654. fadeOut: {
  14655. opacity: 0,
  14656. duration: 0.5,
  14657. easing: 'ease-out'
  14658. },
  14659. fadeIn: {
  14660. opacity: 1,
  14661. duration: 0.5,
  14662. easing: 'ease-in'
  14663. },
  14664. sizeOut: {
  14665. height: 0,
  14666. width: 0,
  14667. duration: 0.75,
  14668. easing: 'ease-out'
  14669. },
  14670. sizeIn: {
  14671. height: function(node) {
  14672. return node.get('scrollHeight') + 'px';
  14673. },
  14674. width: function(node) {
  14675. return node.get('scrollWidth') + 'px';
  14676. },
  14677. duration: 0.5,
  14678. easing: 'ease-in',
  14679. on: {
  14680. start: function() {
  14681. var overflow = this.getStyle('overflow');
  14682. if (overflow !== 'hidden') { // enable scrollHeight/Width
  14683. this.setStyle('overflow', 'hidden');
  14684. this._transitionOverflow = overflow;
  14685. }
  14686. },
  14687. end: function() {
  14688. if (this._transitionOverflow) { // revert overridden value
  14689. this.setStyle('overflow', this._transitionOverflow);
  14690. delete this._transitionOverflow;
  14691. }
  14692. }
  14693. }
  14694. }
  14695. });
  14696. Y.mix(Transition.toggles, {
  14697. size: ['sizeOut', 'sizeIn'],
  14698. fade: ['fadeOut', 'fadeIn']
  14699. });
  14700. Transition.DEFAULT_TOGGLE = 'fade';
  14701. }, '3.4.0' ,{requires:['node-style']});
  14702. YUI.add('selector-css2', function(Y) {
  14703. /**
  14704. * The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements.
  14705. * @module dom
  14706. * @submodule selector-css2
  14707. * @for Selector
  14708. */
  14709. /**
  14710. * Provides helper methods for collecting and filtering DOM elements.
  14711. */
  14712. var PARENT_NODE = 'parentNode',
  14713. TAG_NAME = 'tagName',
  14714. ATTRIBUTES = 'attributes',
  14715. COMBINATOR = 'combinator',
  14716. PSEUDOS = 'pseudos',
  14717. Selector = Y.Selector,
  14718. SelectorCSS2 = {
  14719. _reRegExpTokens: /([\^\$\?\[\]\*\+\-\.\(\)\|\\])/, // TODO: move?
  14720. SORT_RESULTS: true,
  14721. _children: function(node, tag) {
  14722. var ret = node.children,
  14723. i,
  14724. children = [],
  14725. childNodes,
  14726. child;
  14727. if (node.children && tag && node.children.tags) {
  14728. children = node.children.tags(tag);
  14729. } else if ((!ret && node[TAG_NAME]) || (ret && tag)) { // only HTMLElements have children
  14730. childNodes = ret || node.childNodes;
  14731. ret = [];
  14732. for (i = 0; (child = childNodes[i++]);) {
  14733. if (child.tagName) {
  14734. if (!tag || tag === child.tagName) {
  14735. ret.push(child);
  14736. }
  14737. }
  14738. }
  14739. }
  14740. return ret || [];
  14741. },
  14742. _re: {
  14743. attr: /(\[[^\]]*\])/g,
  14744. esc: /\\[:\[\]\(\)#\.\'\>+~"]/gi,
  14745. pseudos: /(\([^\)]*\))/g
  14746. },
  14747. /**
  14748. * Mapping of shorthand tokens to corresponding attribute selector
  14749. * @property shorthand
  14750. * @type object
  14751. */
  14752. shorthand: {
  14753. '\\#(-?[_a-z0-9]+[-\\w\\uE000]*)': '[id=$1]',
  14754. '\\.(-?[_a-z]+[-\\w\\uE000]*)': '[className~=$1]'
  14755. },
  14756. /**
  14757. * List of operators and corresponding boolean functions.
  14758. * These functions are passed the attribute and the current node's value of the attribute.
  14759. * @property operators
  14760. * @type object
  14761. */
  14762. operators: {
  14763. '': function(node, attr) { return Y.DOM.getAttribute(node, attr) !== ''; }, // Just test for existence of attribute
  14764. //'': '.+',
  14765. //'=': '^{val}$', // equality
  14766. '~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited
  14767. '|=': '^{val}-?' // optional hyphen-delimited
  14768. },
  14769. pseudos: {
  14770. 'first-child': function(node) {
  14771. return Y.Selector._children(node[PARENT_NODE])[0] === node;
  14772. }
  14773. },
  14774. _bruteQuery: function(selector, root, firstOnly) {
  14775. var ret = [],
  14776. nodes = [],
  14777. tokens = Selector._tokenize(selector),
  14778. token = tokens[tokens.length - 1],
  14779. rootDoc = Y.DOM._getDoc(root),
  14780. child,
  14781. id,
  14782. className,
  14783. tagName;
  14784. // if we have an initial ID, set to root when in document
  14785. /*
  14786. if (tokens[0] && rootDoc === root &&
  14787. (id = tokens[0].id) &&
  14788. rootDoc.getElementById(id)) {
  14789. root = rootDoc.getElementById(id);
  14790. }
  14791. */
  14792. if (token) {
  14793. // prefilter nodes
  14794. id = token.id;
  14795. className = token.className;
  14796. tagName = token.tagName || '*';
  14797. if (root.getElementsByTagName) { // non-IE lacks DOM api on doc frags
  14798. // try ID first, unless no root.all && root not in document
  14799. // (root.all works off document, but not getElementById)
  14800. // TODO: move to allById?
  14801. if (id && (root.all || (root.nodeType === 9 || Y.DOM.inDoc(root)))) {
  14802. nodes = Y.DOM.allById(id, root);
  14803. // try className
  14804. } else if (className) {
  14805. nodes = root.getElementsByClassName(className);
  14806. } else { // default to tagName
  14807. nodes = root.getElementsByTagName(tagName);
  14808. }
  14809. } else { // brute getElementsByTagName('*')
  14810. child = root.firstChild;
  14811. while (child) {
  14812. if (child.tagName) { // only collect HTMLElements
  14813. nodes.push(child);
  14814. }
  14815. child = child.nextSilbing || child.firstChild;
  14816. }
  14817. }
  14818. if (nodes.length) {
  14819. ret = Selector._filterNodes(nodes, tokens, firstOnly);
  14820. }
  14821. }
  14822. return ret;
  14823. },
  14824. _filterNodes: function(nodes, tokens, firstOnly) {
  14825. var i = 0,
  14826. j,
  14827. len = tokens.length,
  14828. n = len - 1,
  14829. result = [],
  14830. node = nodes[0],
  14831. tmpNode = node,
  14832. getters = Y.Selector.getters,
  14833. operator,
  14834. combinator,
  14835. token,
  14836. path,
  14837. pass,
  14838. //FUNCTION = 'function',
  14839. value,
  14840. tests,
  14841. test;
  14842. //do {
  14843. for (i = 0; (tmpNode = node = nodes[i++]);) {
  14844. n = len - 1;
  14845. path = null;
  14846. testLoop:
  14847. while (tmpNode && tmpNode.tagName) {
  14848. token = tokens[n];
  14849. tests = token.tests;
  14850. j = tests.length;
  14851. if (j && !pass) {
  14852. while ((test = tests[--j])) {
  14853. operator = test[1];
  14854. if (getters[test[0]]) {
  14855. value = getters[test[0]](tmpNode, test[0]);
  14856. } else {
  14857. value = tmpNode[test[0]];
  14858. // use getAttribute for non-standard attributes
  14859. if (value === undefined && tmpNode.getAttribute) {
  14860. value = tmpNode.getAttribute(test[0]);
  14861. }
  14862. }
  14863. if ((operator === '=' && value !== test[2]) || // fast path for equality
  14864. (typeof operator !== 'string' && // protect against String.test monkey-patch (Moo)
  14865. operator.test && !operator.test(value)) || // regex test
  14866. (!operator.test && // protect against RegExp as function (webkit)
  14867. typeof operator === 'function' && !operator(tmpNode, test[0], test[2]))) { // function test
  14868. // skip non element nodes or non-matching tags
  14869. if ((tmpNode = tmpNode[path])) {
  14870. while (tmpNode &&
  14871. (!tmpNode.tagName ||
  14872. (token.tagName && token.tagName !== tmpNode.tagName))
  14873. ) {
  14874. tmpNode = tmpNode[path];
  14875. }
  14876. }
  14877. continue testLoop;
  14878. }
  14879. }
  14880. }
  14881. n--; // move to next token
  14882. // now that we've passed the test, move up the tree by combinator
  14883. if (!pass && (combinator = token.combinator)) {
  14884. path = combinator.axis;
  14885. tmpNode = tmpNode[path];
  14886. // skip non element nodes
  14887. while (tmpNode && !tmpNode.tagName) {
  14888. tmpNode = tmpNode[path];
  14889. }
  14890. if (combinator.direct) { // one pass only
  14891. path = null;
  14892. }
  14893. } else { // success if we made it this far
  14894. result.push(node);
  14895. if (firstOnly) {
  14896. return result;
  14897. }
  14898. break;
  14899. }
  14900. }
  14901. }// while (tmpNode = node = nodes[++i]);
  14902. node = tmpNode = null;
  14903. return result;
  14904. },
  14905. combinators: {
  14906. ' ': {
  14907. axis: 'parentNode'
  14908. },
  14909. '>': {
  14910. axis: 'parentNode',
  14911. direct: true
  14912. },
  14913. '+': {
  14914. axis: 'previousSibling',
  14915. direct: true
  14916. }
  14917. },
  14918. _parsers: [
  14919. {
  14920. name: ATTRIBUTES,
  14921. re: /^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,
  14922. fn: function(match, token) {
  14923. var operator = match[2] || '',
  14924. operators = Selector.operators,
  14925. escVal = (match[3]) ? match[3].replace(/\\/g, '') : '',
  14926. test;
  14927. // add prefiltering for ID and CLASS
  14928. if ((match[1] === 'id' && operator === '=') ||
  14929. (match[1] === 'className' &&
  14930. Y.config.doc.documentElement.getElementsByClassName &&
  14931. (operator === '~=' || operator === '='))) {
  14932. token.prefilter = match[1];
  14933. match[3] = escVal;
  14934. // escape all but ID for prefilter, which may run through QSA (via Dom.allById)
  14935. token[match[1]] = (match[1] === 'id') ? match[3] : escVal;
  14936. }
  14937. // add tests
  14938. if (operator in operators) {
  14939. test = operators[operator];
  14940. if (typeof test === 'string') {
  14941. match[3] = escVal.replace(Selector._reRegExpTokens, '\\$1');
  14942. test = new RegExp(test.replace('{val}', match[3]));
  14943. }
  14944. match[2] = test;
  14945. }
  14946. if (!token.last || token.prefilter !== match[1]) {
  14947. return match.slice(1);
  14948. }
  14949. }
  14950. },
  14951. {
  14952. name: TAG_NAME,
  14953. re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
  14954. fn: function(match, token) {
  14955. var tag = match[1].toUpperCase();
  14956. token.tagName = tag;
  14957. if (tag !== '*' && (!token.last || token.prefilter)) {
  14958. return [TAG_NAME, '=', tag];
  14959. }
  14960. if (!token.prefilter) {
  14961. token.prefilter = 'tagName';
  14962. }
  14963. }
  14964. },
  14965. {
  14966. name: COMBINATOR,
  14967. re: /^\s*([>+~]|\s)\s*/,
  14968. fn: function(match, token) {
  14969. }
  14970. },
  14971. {
  14972. name: PSEUDOS,
  14973. re: /^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,
  14974. fn: function(match, token) {
  14975. var test = Selector[PSEUDOS][match[1]];
  14976. if (test) { // reorder match array and unescape special chars for tests
  14977. if (match[2]) {
  14978. match[2] = match[2].replace(/\\/g, '');
  14979. }
  14980. return [match[2], test];
  14981. } else { // selector token not supported (possibly missing CSS3 module)
  14982. return false;
  14983. }
  14984. }
  14985. }
  14986. ],
  14987. _getToken: function(token) {
  14988. return {
  14989. tagName: null,
  14990. id: null,
  14991. className: null,
  14992. attributes: {},
  14993. combinator: null,
  14994. tests: []
  14995. };
  14996. },
  14997. /**
  14998. Break selector into token units per simple selector.
  14999. Combinator is attached to the previous token.
  15000. */
  15001. _tokenize: function(selector) {
  15002. selector = selector || '';
  15003. selector = Selector._replaceShorthand(Y.Lang.trim(selector));
  15004. var token = Selector._getToken(), // one token per simple selector (left selector holds combinator)
  15005. query = selector, // original query for debug report
  15006. tokens = [], // array of tokens
  15007. found = false, // whether or not any matches were found this pass
  15008. match, // the regex match
  15009. test,
  15010. i, parser;
  15011. /*
  15012. Search for selector patterns, store, and strip them from the selector string
  15013. until no patterns match (invalid selector) or we run out of chars.
  15014. Multiple attributes and pseudos are allowed, in any order.
  15015. for example:
  15016. 'form:first-child[type=button]:not(button)[lang|=en]'
  15017. */
  15018. outer:
  15019. do {
  15020. found = false; // reset after full pass
  15021. for (i = 0; (parser = Selector._parsers[i++]);) {
  15022. if ( (match = parser.re.exec(selector)) ) { // note assignment
  15023. if (parser.name !== COMBINATOR ) {
  15024. token.selector = selector;
  15025. }
  15026. selector = selector.replace(match[0], ''); // strip current match from selector
  15027. if (!selector.length) {
  15028. token.last = true;
  15029. }
  15030. if (Selector._attrFilters[match[1]]) { // convert class to className, etc.
  15031. match[1] = Selector._attrFilters[match[1]];
  15032. }
  15033. test = parser.fn(match, token);
  15034. if (test === false) { // selector not supported
  15035. found = false;
  15036. break outer;
  15037. } else if (test) {
  15038. token.tests.push(test);
  15039. }
  15040. if (!selector.length || parser.name === COMBINATOR) {
  15041. tokens.push(token);
  15042. token = Selector._getToken(token);
  15043. if (parser.name === COMBINATOR) {
  15044. token.combinator = Y.Selector.combinators[match[1]];
  15045. }
  15046. }
  15047. found = true;
  15048. }
  15049. }
  15050. } while (found && selector.length);
  15051. if (!found || selector.length) { // not fully parsed
  15052. Y.log('query: ' + query + ' contains unsupported token in: ' + selector, 'warn', 'Selector');
  15053. tokens = [];
  15054. }
  15055. return tokens;
  15056. },
  15057. _replaceShorthand: function(selector) {
  15058. var shorthand = Selector.shorthand,
  15059. esc = selector.match(Selector._re.esc), // pull escaped colon, brackets, etc.
  15060. attrs,
  15061. pseudos,
  15062. re, i, len;
  15063. if (esc) {
  15064. selector = selector.replace(Selector._re.esc, '\uE000');
  15065. }
  15066. attrs = selector.match(Selector._re.attr);
  15067. pseudos = selector.match(Selector._re.pseudos);
  15068. if (attrs) {
  15069. selector = selector.replace(Selector._re.attr, '\uE001');
  15070. }
  15071. if (pseudos) {
  15072. selector = selector.replace(Selector._re.pseudos, '\uE002');
  15073. }
  15074. for (re in shorthand) {
  15075. if (shorthand.hasOwnProperty(re)) {
  15076. selector = selector.replace(new RegExp(re, 'gi'), shorthand[re]);
  15077. }
  15078. }
  15079. if (attrs) {
  15080. for (i = 0, len = attrs.length; i < len; ++i) {
  15081. selector = selector.replace(/\uE001/, attrs[i]);
  15082. }
  15083. }
  15084. if (pseudos) {
  15085. for (i = 0, len = pseudos.length; i < len; ++i) {
  15086. selector = selector.replace(/\uE002/, pseudos[i]);
  15087. }
  15088. }
  15089. selector = selector.replace(/\[/g, '\uE003');
  15090. selector = selector.replace(/\]/g, '\uE004');
  15091. selector = selector.replace(/\(/g, '\uE005');
  15092. selector = selector.replace(/\)/g, '\uE006');
  15093. if (esc) {
  15094. for (i = 0, len = esc.length; i < len; ++i) {
  15095. selector = selector.replace('\uE000', esc[i]);
  15096. }
  15097. }
  15098. return selector;
  15099. },
  15100. _attrFilters: {
  15101. 'class': 'className',
  15102. 'for': 'htmlFor'
  15103. },
  15104. getters: {
  15105. href: function(node, attr) {
  15106. return Y.DOM.getAttribute(node, attr);
  15107. }
  15108. }
  15109. };
  15110. Y.mix(Y.Selector, SelectorCSS2, true);
  15111. Y.Selector.getters.src = Y.Selector.getters.rel = Y.Selector.getters.href;
  15112. // IE wants class with native queries
  15113. if (Y.Selector.useNative && Y.config.doc.querySelector) {
  15114. Y.Selector.shorthand['\\.(-?[_a-z]+[-\\w]*)'] = '[class~=$1]';
  15115. }
  15116. }, '3.4.0' ,{requires:['selector-native']});
  15117. YUI.add('selector-css3', function(Y) {
  15118. /**
  15119. * The selector css3 module provides support for css3 selectors.
  15120. * @module dom
  15121. * @submodule selector-css3
  15122. * @for Selector
  15123. */
  15124. /*
  15125. an+b = get every _a_th node starting at the _b_th
  15126. 0n+b = no repeat ("0" and "n" may both be omitted (together) , e.g. "0n+1" or "1", not "0+1"), return only the _b_th element
  15127. 1n+b = get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
  15128. an+0 = get every _a_th element, "0" may be omitted
  15129. */
  15130. Y.Selector._reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;
  15131. Y.Selector._getNth = function(node, expr, tag, reverse) {
  15132. Y.Selector._reNth.test(expr);
  15133. var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
  15134. n = RegExp.$2, // "n"
  15135. oddeven = RegExp.$3, // "odd" or "even"
  15136. b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
  15137. result = [],
  15138. siblings = Y.Selector._children(node.parentNode, tag),
  15139. op;
  15140. if (oddeven) {
  15141. a = 2; // always every other
  15142. op = '+';
  15143. n = 'n';
  15144. b = (oddeven === 'odd') ? 1 : 0;
  15145. } else if ( isNaN(a) ) {
  15146. a = (n) ? 1 : 0; // start from the first or no repeat
  15147. }
  15148. if (a === 0) { // just the first
  15149. if (reverse) {
  15150. b = siblings.length - b + 1;
  15151. }
  15152. if (siblings[b - 1] === node) {
  15153. return true;
  15154. } else {
  15155. return false;
  15156. }
  15157. } else if (a < 0) {
  15158. reverse = !!reverse;
  15159. a = Math.abs(a);
  15160. }
  15161. if (!reverse) {
  15162. for (var i = b - 1, len = siblings.length; i < len; i += a) {
  15163. if ( i >= 0 && siblings[i] === node ) {
  15164. return true;
  15165. }
  15166. }
  15167. } else {
  15168. for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
  15169. if ( i < len && siblings[i] === node ) {
  15170. return true;
  15171. }
  15172. }
  15173. }
  15174. return false;
  15175. };
  15176. Y.mix(Y.Selector.pseudos, {
  15177. 'root': function(node) {
  15178. return node === node.ownerDocument.documentElement;
  15179. },
  15180. 'nth-child': function(node, expr) {
  15181. return Y.Selector._getNth(node, expr);
  15182. },
  15183. 'nth-last-child': function(node, expr) {
  15184. return Y.Selector._getNth(node, expr, null, true);
  15185. },
  15186. 'nth-of-type': function(node, expr) {
  15187. return Y.Selector._getNth(node, expr, node.tagName);
  15188. },
  15189. 'nth-last-of-type': function(node, expr) {
  15190. return Y.Selector._getNth(node, expr, node.tagName, true);
  15191. },
  15192. 'last-child': function(node) {
  15193. var children = Y.Selector._children(node.parentNode);
  15194. return children[children.length - 1] === node;
  15195. },
  15196. 'first-of-type': function(node) {
  15197. return Y.Selector._children(node.parentNode, node.tagName)[0] === node;
  15198. },
  15199. 'last-of-type': function(node) {
  15200. var children = Y.Selector._children(node.parentNode, node.tagName);
  15201. return children[children.length - 1] === node;
  15202. },
  15203. 'only-child': function(node) {
  15204. var children = Y.Selector._children(node.parentNode);
  15205. return children.length === 1 && children[0] === node;
  15206. },
  15207. 'only-of-type': function(node) {
  15208. var children = Y.Selector._children(node.parentNode, node.tagName);
  15209. return children.length === 1 && children[0] === node;
  15210. },
  15211. 'empty': function(node) {
  15212. return node.childNodes.length === 0;
  15213. },
  15214. 'not': function(node, expr) {
  15215. return !Y.Selector.test(node, expr);
  15216. },
  15217. 'contains': function(node, expr) {
  15218. var text = node.innerText || node.textContent || '';
  15219. return text.indexOf(expr) > -1;
  15220. },
  15221. 'checked': function(node) {
  15222. return (node.checked === true || node.selected === true);
  15223. },
  15224. enabled: function(node) {
  15225. return (node.disabled !== undefined && !node.disabled);
  15226. },
  15227. disabled: function(node) {
  15228. return (node.disabled);
  15229. }
  15230. });
  15231. Y.mix(Y.Selector.operators, {
  15232. '^=': '^{val}', // Match starts with value
  15233. '$=': '{val}$', // Match ends with value
  15234. '*=': '{val}' // Match contains value as substring
  15235. });
  15236. Y.Selector.combinators['~'] = {
  15237. axis: 'previousSibling'
  15238. };
  15239. }, '3.4.0' ,{requires:['selector-native', 'selector-css2']});
  15240. YUI.add('yui-log', function(Y) {
  15241. /**
  15242. * Provides console log capability and exposes a custom event for
  15243. * console implementations. This module is a `core` YUI module, <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
  15244. *
  15245. * @module yui
  15246. * @submodule yui-log
  15247. */
  15248. var INSTANCE = Y,
  15249. LOGEVENT = 'yui:log',
  15250. UNDEFINED = 'undefined',
  15251. LEVELS = { debug: 1,
  15252. info: 1,
  15253. warn: 1,
  15254. error: 1 };
  15255. /**
  15256. * If the 'debug' config is true, a 'yui:log' event will be
  15257. * dispatched, which the Console widget and anything else
  15258. * can consume. If the 'useBrowserConsole' config is true, it will
  15259. * write to the browser console if available. YUI-specific log
  15260. * messages will only be present in the -debug versions of the
  15261. * JS files. The build system is supposed to remove log statements
  15262. * from the raw and minified versions of the files.
  15263. *
  15264. * @method log
  15265. * @for YUI
  15266. * @param {String} msg The message to log.
  15267. * @param {String} cat The log category for the message. Default
  15268. * categories are "info", "warn", "error", time".
  15269. * Custom categories can be used as well. (opt).
  15270. * @param {String} src The source of the the message (opt).
  15271. * @param {boolean} silent If true, the log event won't fire.
  15272. * @return {YUI} YUI instance.
  15273. */
  15274. INSTANCE.log = function(msg, cat, src, silent) {
  15275. var bail, excl, incl, m, f,
  15276. Y = INSTANCE,
  15277. c = Y.config,
  15278. publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
  15279. // suppress log message if the config is off or the event stack
  15280. // or the event call stack contains a consumer of the yui:log event
  15281. if (c.debug) {
  15282. // apply source filters
  15283. if (src) {
  15284. excl = c.logExclude;
  15285. incl = c.logInclude;
  15286. if (incl && !(src in incl)) {
  15287. bail = 1;
  15288. } else if (incl && (src in incl)) {
  15289. bail = !incl[src];
  15290. } else if (excl && (src in excl)) {
  15291. bail = excl[src];
  15292. }
  15293. }
  15294. if (!bail) {
  15295. if (c.useBrowserConsole) {
  15296. m = (src) ? src + ': ' + msg : msg;
  15297. if (Y.Lang.isFunction(c.logFn)) {
  15298. c.logFn.call(Y, msg, cat, src);
  15299. } else if (typeof console != UNDEFINED && console.log) {
  15300. f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
  15301. console[f](m);
  15302. } else if (typeof opera != UNDEFINED) {
  15303. opera.postError(m);
  15304. }
  15305. }
  15306. if (publisher && !silent) {
  15307. if (publisher == Y && (!publisher.getEvent(LOGEVENT))) {
  15308. publisher.publish(LOGEVENT, {
  15309. broadcast: 2
  15310. });
  15311. }
  15312. publisher.fire(LOGEVENT, {
  15313. msg: msg,
  15314. cat: cat,
  15315. src: src
  15316. });
  15317. }
  15318. }
  15319. }
  15320. return Y;
  15321. };
  15322. /**
  15323. * Write a system message. This message will be preserved in the
  15324. * minified and raw versions of the YUI files, unlike log statements.
  15325. * @method message
  15326. * @for YUI
  15327. * @param {String} msg The message to log.
  15328. * @param {String} cat The log category for the message. Default
  15329. * categories are "info", "warn", "error", time".
  15330. * Custom categories can be used as well. (opt).
  15331. * @param {String} src The source of the the message (opt).
  15332. * @param {boolean} silent If true, the log event won't fire.
  15333. * @return {YUI} YUI instance.
  15334. */
  15335. INSTANCE.message = function() {
  15336. return INSTANCE.log.apply(INSTANCE, arguments);
  15337. };
  15338. }, '3.4.0' ,{requires:['yui-base']});
  15339. YUI.add('dump', function(Y) {
  15340. /**
  15341. * Returns a simple string representation of the object or array.
  15342. * Other types of objects will be returned unprocessed. Arrays
  15343. * are expected to be indexed. Use object notation for
  15344. * associative arrays.
  15345. *
  15346. * If included, the dump method is added to the YUI instance.
  15347. *
  15348. * @module dump
  15349. */
  15350. var L = Y.Lang,
  15351. OBJ = '{...}',
  15352. FUN = 'f(){...}',
  15353. COMMA = ', ',
  15354. ARROW = ' => ',
  15355. /**
  15356. * Returns a simple string representation of the object or array.
  15357. * Other types of objects will be returned unprocessed. Arrays
  15358. * are expected to be indexed.
  15359. *
  15360. * @method dump
  15361. * @param {Object} o The object to dump.
  15362. * @param {Number} d How deep to recurse child objects, default 3.
  15363. * @return {String} the dump result.
  15364. * @for YUI
  15365. */
  15366. dump = function(o, d) {
  15367. var i, len, s = [], type = L.type(o);
  15368. // Cast non-objects to string
  15369. // Skip dates because the std toString is what we want
  15370. // Skip HTMLElement-like objects because trying to dump
  15371. // an element will cause an unhandled exception in FF 2.x
  15372. if (!L.isObject(o)) {
  15373. return o + '';
  15374. } else if (type == 'date') {
  15375. return o;
  15376. } else if (o.nodeType && o.tagName) {
  15377. return o.tagName + '#' + o.id;
  15378. } else if (o.document && o.navigator) {
  15379. return 'window';
  15380. } else if (o.location && o.body) {
  15381. return 'document';
  15382. } else if (type == 'function') {
  15383. return FUN;
  15384. }
  15385. // dig into child objects the depth specifed. Default 3
  15386. d = (L.isNumber(d)) ? d : 3;
  15387. // arrays [1, 2, 3]
  15388. if (type == 'array') {
  15389. s.push('[');
  15390. for (i = 0, len = o.length; i < len; i = i + 1) {
  15391. if (L.isObject(o[i])) {
  15392. s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
  15393. } else {
  15394. s.push(o[i]);
  15395. }
  15396. s.push(COMMA);
  15397. }
  15398. if (s.length > 1) {
  15399. s.pop();
  15400. }
  15401. s.push(']');
  15402. // regexp /foo/
  15403. } else if (type == 'regexp') {
  15404. s.push(o.toString());
  15405. // objects {k1 => v1, k2 => v2}
  15406. } else {
  15407. s.push('{');
  15408. for (i in o) {
  15409. if (o.hasOwnProperty(i)) {
  15410. try {
  15411. s.push(i + ARROW);
  15412. if (L.isObject(o[i])) {
  15413. s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
  15414. } else {
  15415. s.push(o[i]);
  15416. }
  15417. s.push(COMMA);
  15418. } catch (e) {
  15419. s.push('Error: ' + e.message);
  15420. }
  15421. }
  15422. }
  15423. if (s.length > 1) {
  15424. s.pop();
  15425. }
  15426. s.push('}');
  15427. }
  15428. return s.join('');
  15429. };
  15430. Y.dump = dump;
  15431. L.dump = dump;
  15432. }, '3.4.0' );
  15433. YUI.add('transition-timer', function(Y) {
  15434. /*
  15435. * The Transition Utility provides an API for creating advanced transitions.
  15436. * @module transition
  15437. */
  15438. /*
  15439. * Provides the base Transition class, for animating numeric properties.
  15440. *
  15441. * @module transition
  15442. * @submodule transition-timer
  15443. */
  15444. var Transition = Y.Transition;
  15445. Y.mix(Transition.prototype, {
  15446. _start: function() {
  15447. if (Transition.useNative) {
  15448. this._runNative();
  15449. } else {
  15450. this._runTimer();
  15451. }
  15452. },
  15453. _runTimer: function() {
  15454. var anim = this;
  15455. anim._initAttrs();
  15456. Transition._running[Y.stamp(anim)] = anim;
  15457. anim._startTime = new Date();
  15458. Transition._startTimer();
  15459. },
  15460. _endTimer: function() {
  15461. var anim = this;
  15462. delete Transition._running[Y.stamp(anim)];
  15463. anim._startTime = null;
  15464. },
  15465. _runFrame: function() {
  15466. var t = new Date() - this._startTime;
  15467. this._runAttrs(t);
  15468. },
  15469. _runAttrs: function(time) {
  15470. var anim = this,
  15471. node = anim._node,
  15472. config = anim._config,
  15473. uid = Y.stamp(node),
  15474. attrs = Transition._nodeAttrs[uid],
  15475. customAttr = Transition.behaviors,
  15476. done = false,
  15477. allDone = false,
  15478. data,
  15479. name,
  15480. attribute,
  15481. setter,
  15482. elapsed,
  15483. delay,
  15484. d,
  15485. t,
  15486. i;
  15487. for (name in attrs) {
  15488. if ((attribute = attrs[name]) && attribute.transition === anim) {
  15489. d = attribute.duration;
  15490. delay = attribute.delay;
  15491. elapsed = (time - delay) / 1000;
  15492. t = time;
  15493. data = {
  15494. type: 'propertyEnd',
  15495. propertyName: name,
  15496. config: config,
  15497. elapsedTime: elapsed
  15498. };
  15499. setter = (i in customAttr && 'set' in customAttr[i]) ?
  15500. customAttr[i].set : Transition.DEFAULT_SETTER;
  15501. done = (t >= d);
  15502. if (t > d) {
  15503. t = d;
  15504. }
  15505. if (!delay || time >= delay) {
  15506. setter(anim, name, attribute.from, attribute.to, t - delay, d - delay,
  15507. attribute.easing, attribute.unit);
  15508. if (done) {
  15509. delete attrs[name];
  15510. anim._count--;
  15511. if (config[name] && config[name].on && config[name].on.end) {
  15512. config[name].on.end.call(Y.one(node), data);
  15513. }
  15514. //node.fire('transition:propertyEnd', data);
  15515. if (!allDone && anim._count <= 0) {
  15516. allDone = true;
  15517. anim._end(elapsed);
  15518. anim._endTimer();
  15519. }
  15520. }
  15521. }
  15522. }
  15523. }
  15524. },
  15525. _initAttrs: function() {
  15526. var anim = this,
  15527. customAttr = Transition.behaviors,
  15528. uid = Y.stamp(anim._node),
  15529. attrs = Transition._nodeAttrs[uid],
  15530. attribute,
  15531. duration,
  15532. delay,
  15533. easing,
  15534. val,
  15535. name,
  15536. mTo,
  15537. mFrom,
  15538. unit, begin, end;
  15539. for (name in attrs) {
  15540. if ((attribute = attrs[name]) && attribute.transition === anim) {
  15541. duration = attribute.duration * 1000;
  15542. delay = attribute.delay * 1000;
  15543. easing = attribute.easing;
  15544. val = attribute.value;
  15545. // only allow supported properties
  15546. if (name in anim._node.style || name in Y.DOM.CUSTOM_STYLES) {
  15547. begin = (name in customAttr && 'get' in customAttr[name]) ?
  15548. customAttr[name].get(anim, name) : Transition.DEFAULT_GETTER(anim, name);
  15549. mFrom = Transition.RE_UNITS.exec(begin);
  15550. mTo = Transition.RE_UNITS.exec(val);
  15551. begin = mFrom ? mFrom[1] : begin;
  15552. end = mTo ? mTo[1] : val;
  15553. unit = mTo ? mTo[2] : mFrom ? mFrom[2] : ''; // one might be zero TODO: mixed units
  15554. if (!unit && Transition.RE_DEFAULT_UNIT.test(name)) {
  15555. unit = Transition.DEFAULT_UNIT;
  15556. }
  15557. if (typeof easing === 'string') {
  15558. if (easing.indexOf('cubic-bezier') > -1) {
  15559. easing = easing.substring(13, easing.length - 1).split(',');
  15560. } else if (Transition.easings[easing]) {
  15561. easing = Transition.easings[easing];
  15562. }
  15563. }
  15564. attribute.from = Number(begin);
  15565. attribute.to = Number(end);
  15566. attribute.unit = unit;
  15567. attribute.easing = easing;
  15568. attribute.duration = duration + delay;
  15569. attribute.delay = delay;
  15570. } else {
  15571. delete attrs[name];
  15572. anim._count--;
  15573. }
  15574. }
  15575. }
  15576. },
  15577. destroy: function() {
  15578. this.detachAll();
  15579. this._node = null;
  15580. }
  15581. }, true);
  15582. Y.mix(Y.Transition, {
  15583. _runtimeAttrs: {},
  15584. /*
  15585. * Regex of properties that should use the default unit.
  15586. *
  15587. * @property RE_DEFAULT_UNIT
  15588. * @static
  15589. */
  15590. RE_DEFAULT_UNIT: /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,
  15591. /*
  15592. * The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
  15593. *
  15594. * @property DEFAULT_UNIT
  15595. * @static
  15596. */
  15597. DEFAULT_UNIT: 'px',
  15598. /*
  15599. * Time in milliseconds passed to setInterval for frame processing
  15600. *
  15601. * @property intervalTime
  15602. * @default 20
  15603. * @static
  15604. */
  15605. intervalTime: 20,
  15606. /*
  15607. * Bucket for custom getters and setters
  15608. *
  15609. * @property behaviors
  15610. * @static
  15611. */
  15612. behaviors: {
  15613. left: {
  15614. get: function(anim, attr) {
  15615. return Y.DOM._getAttrOffset(anim._node, attr);
  15616. }
  15617. }
  15618. },
  15619. /*
  15620. * The default setter to use when setting object properties.
  15621. *
  15622. * @property DEFAULT_SETTER
  15623. * @static
  15624. */
  15625. DEFAULT_SETTER: function(anim, att, from, to, elapsed, duration, fn, unit) {
  15626. from = Number(from);
  15627. to = Number(to);
  15628. var node = anim._node,
  15629. val = Transition.cubicBezier(fn, elapsed / duration);
  15630. val = from + val[0] * (to - from);
  15631. if (node) {
  15632. if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
  15633. unit = unit || '';
  15634. Y.DOM.setStyle(node, att, val + unit);
  15635. }
  15636. } else {
  15637. anim._end();
  15638. }
  15639. },
  15640. /*
  15641. * The default getter to use when getting object properties.
  15642. *
  15643. * @property DEFAULT_GETTER
  15644. * @static
  15645. */
  15646. DEFAULT_GETTER: function(anim, att) {
  15647. var node = anim._node,
  15648. val = '';
  15649. if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
  15650. val = Y.DOM.getComputedStyle(node, att);
  15651. }
  15652. return val;
  15653. },
  15654. _startTimer: function() {
  15655. if (!Transition._timer) {
  15656. Transition._timer = setInterval(Transition._runFrame, Transition.intervalTime);
  15657. }
  15658. },
  15659. _stopTimer: function() {
  15660. clearInterval(Transition._timer);
  15661. Transition._timer = null;
  15662. },
  15663. /*
  15664. * Called per Interval to handle each animation frame.
  15665. * @method _runFrame
  15666. * @private
  15667. * @static
  15668. */
  15669. _runFrame: function() {
  15670. var done = true,
  15671. anim;
  15672. for (anim in Transition._running) {
  15673. if (Transition._running[anim]._runFrame) {
  15674. done = false;
  15675. Transition._running[anim]._runFrame();
  15676. }
  15677. }
  15678. if (done) {
  15679. Transition._stopTimer();
  15680. }
  15681. },
  15682. cubicBezier: function(p, t) {
  15683. var x0 = 0,
  15684. y0 = 0,
  15685. x1 = p[0],
  15686. y1 = p[1],
  15687. x2 = p[2],
  15688. y2 = p[3],
  15689. x3 = 1,
  15690. y3 = 0,
  15691. A = x3 - 3 * x2 + 3 * x1 - x0,
  15692. B = 3 * x2 - 6 * x1 + 3 * x0,
  15693. C = 3 * x1 - 3 * x0,
  15694. D = x0,
  15695. E = y3 - 3 * y2 + 3 * y1 - y0,
  15696. F = 3 * y2 - 6 * y1 + 3 * y0,
  15697. G = 3 * y1 - 3 * y0,
  15698. H = y0,
  15699. x = (((A*t) + B)*t + C)*t + D,
  15700. y = (((E*t) + F)*t + G)*t + H;
  15701. return [x, y];
  15702. },
  15703. easings: {
  15704. ease: [0.25, 0, 1, 0.25],
  15705. linear: [0, 0, 1, 1],
  15706. 'ease-in': [0.42, 0, 1, 1],
  15707. 'ease-out': [0, 0, 0.58, 1],
  15708. 'ease-in-out': [0.42, 0, 0.58, 1]
  15709. },
  15710. _running: {},
  15711. _timer: null,
  15712. RE_UNITS: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/
  15713. }, true);
  15714. Transition.behaviors.top = Transition.behaviors.bottom = Transition.behaviors.right = Transition.behaviors.left;
  15715. Y.Transition = Transition;
  15716. }, '3.4.0' ,{requires:['transition']});
  15717. YUI.add('simpleyui', function(Y) {
  15718. // empty
  15719. }, '3.4.0' ,{use:['yui','oop','dom','event-custom-base','event-base','pluginhost','node','event-delegate','io-base','json-parse','transition','selector-css3','dom-style-ie','querystring-stringify-simple']});
  15720. var Y = YUI().use('*');