12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053 |
- /*
- Copyright (c) 2009, Yahoo! Inc. All rights reserved.
- Code licensed under the BSD License:
- http://developer.yahoo.net/yui/license.txt
- version: 2.8.0r4
- */
- (function () {
- /**
- * Config is a utility used within an Object to allow the implementer to
- * maintain a list of local configuration properties and listen for changes
- * to those properties dynamically using CustomEvent. The initial values are
- * also maintained so that the configuration can be reset at any given point
- * to its initial state.
- * @namespace YAHOO.util
- * @class Config
- * @constructor
- * @param {Object} owner The owner Object to which this Config Object belongs
- */
- YAHOO.util.Config = function (owner) {
- if (owner) {
- this.init(owner);
- }
- };
- var Lang = YAHOO.lang,
- CustomEvent = YAHOO.util.CustomEvent,
- Config = YAHOO.util.Config;
- /**
- * Constant representing the CustomEvent type for the config changed event.
- * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT
- * @private
- * @static
- * @final
- */
- Config.CONFIG_CHANGED_EVENT = "configChanged";
-
- /**
- * Constant representing the boolean type string
- * @property YAHOO.util.Config.BOOLEAN_TYPE
- * @private
- * @static
- * @final
- */
- Config.BOOLEAN_TYPE = "boolean";
-
- Config.prototype = {
-
- /**
- * Object reference to the owner of this Config Object
- * @property owner
- * @type Object
- */
- owner: null,
-
- /**
- * Boolean flag that specifies whether a queue is currently
- * being executed
- * @property queueInProgress
- * @type Boolean
- */
- queueInProgress: false,
-
- /**
- * Maintains the local collection of configuration property objects and
- * their specified values
- * @property config
- * @private
- * @type Object
- */
- config: null,
-
- /**
- * Maintains the local collection of configuration property objects as
- * they were initially applied.
- * This object is used when resetting a property.
- * @property initialConfig
- * @private
- * @type Object
- */
- initialConfig: null,
-
- /**
- * Maintains the local, normalized CustomEvent queue
- * @property eventQueue
- * @private
- * @type Object
- */
- eventQueue: null,
-
- /**
- * Custom Event, notifying subscribers when Config properties are set
- * (setProperty is called without the silent flag
- * @event configChangedEvent
- */
- configChangedEvent: null,
-
- /**
- * Initializes the configuration Object and all of its local members.
- * @method init
- * @param {Object} owner The owner Object to which this Config
- * Object belongs
- */
- init: function (owner) {
-
- this.owner = owner;
-
- this.configChangedEvent =
- this.createEvent(Config.CONFIG_CHANGED_EVENT);
-
- this.configChangedEvent.signature = CustomEvent.LIST;
- this.queueInProgress = false;
- this.config = {};
- this.initialConfig = {};
- this.eventQueue = [];
-
- },
-
- /**
- * Validates that the value passed in is a Boolean.
- * @method checkBoolean
- * @param {Object} val The value to validate
- * @return {Boolean} true, if the value is valid
- */
- checkBoolean: function (val) {
- return (typeof val == Config.BOOLEAN_TYPE);
- },
-
- /**
- * Validates that the value passed in is a number.
- * @method checkNumber
- * @param {Object} val The value to validate
- * @return {Boolean} true, if the value is valid
- */
- checkNumber: function (val) {
- return (!isNaN(val));
- },
-
- /**
- * Fires a configuration property event using the specified value.
- * @method fireEvent
- * @private
- * @param {String} key The configuration property's name
- * @param {value} Object The value of the correct type for the property
- */
- fireEvent: function ( key, value ) {
- var property = this.config[key];
-
- if (property && property.event) {
- property.event.fire(value);
- }
- },
-
- /**
- * Adds a property to the Config Object's private config hash.
- * @method addProperty
- * @param {String} key The configuration property's name
- * @param {Object} propertyObject The Object containing all of this
- * property's arguments
- */
- addProperty: function ( key, propertyObject ) {
- key = key.toLowerCase();
-
- this.config[key] = propertyObject;
-
- propertyObject.event = this.createEvent(key, { scope: this.owner });
- propertyObject.event.signature = CustomEvent.LIST;
-
-
- propertyObject.key = key;
-
- if (propertyObject.handler) {
- propertyObject.event.subscribe(propertyObject.handler,
- this.owner);
- }
-
- this.setProperty(key, propertyObject.value, true);
-
- if (! propertyObject.suppressEvent) {
- this.queueProperty(key, propertyObject.value);
- }
-
- },
-
- /**
- * Returns a key-value configuration map of the values currently set in
- * the Config Object.
- * @method getConfig
- * @return {Object} The current config, represented in a key-value map
- */
- getConfig: function () {
-
- var cfg = {},
- currCfg = this.config,
- prop,
- property;
-
- for (prop in currCfg) {
- if (Lang.hasOwnProperty(currCfg, prop)) {
- property = currCfg[prop];
- if (property && property.event) {
- cfg[prop] = property.value;
- }
- }
- }
- return cfg;
- },
-
- /**
- * Returns the value of specified property.
- * @method getProperty
- * @param {String} key The name of the property
- * @return {Object} The value of the specified property
- */
- getProperty: function (key) {
- var property = this.config[key.toLowerCase()];
- if (property && property.event) {
- return property.value;
- } else {
- return undefined;
- }
- },
-
- /**
- * Resets the specified property's value to its initial value.
- * @method resetProperty
- * @param {String} key The name of the property
- * @return {Boolean} True is the property was reset, false if not
- */
- resetProperty: function (key) {
-
- key = key.toLowerCase();
-
- var property = this.config[key];
-
- if (property && property.event) {
-
- if (this.initialConfig[key] &&
- !Lang.isUndefined(this.initialConfig[key])) {
-
- this.setProperty(key, this.initialConfig[key]);
- return true;
-
- }
-
- } else {
-
- return false;
- }
-
- },
-
- /**
- * Sets the value of a property. If the silent property is passed as
- * true, the property's event will not be fired.
- * @method setProperty
- * @param {String} key The name of the property
- * @param {String} value The value to set the property to
- * @param {Boolean} silent Whether the value should be set silently,
- * without firing the property event.
- * @return {Boolean} True, if the set was successful, false if it failed.
- */
- setProperty: function (key, value, silent) {
-
- var property;
-
- key = key.toLowerCase();
-
- if (this.queueInProgress && ! silent) {
- // Currently running through a queue...
- this.queueProperty(key,value);
- return true;
-
- } else {
- property = this.config[key];
- if (property && property.event) {
- if (property.validator && !property.validator(value)) {
- return false;
- } else {
- property.value = value;
- if (! silent) {
- this.fireEvent(key, value);
- this.configChangedEvent.fire([key, value]);
- }
- return true;
- }
- } else {
- return false;
- }
- }
- },
-
- /**
- * Sets the value of a property and queues its event to execute. If the
- * event is already scheduled to execute, it is
- * moved from its current position to the end of the queue.
- * @method queueProperty
- * @param {String} key The name of the property
- * @param {String} value The value to set the property to
- * @return {Boolean} true, if the set was successful, false if
- * it failed.
- */
- queueProperty: function (key, value) {
-
- key = key.toLowerCase();
-
- var property = this.config[key],
- foundDuplicate = false,
- iLen,
- queueItem,
- queueItemKey,
- queueItemValue,
- sLen,
- supercedesCheck,
- qLen,
- queueItemCheck,
- queueItemCheckKey,
- queueItemCheckValue,
- i,
- s,
- q;
-
- if (property && property.event) {
-
- if (!Lang.isUndefined(value) && property.validator &&
- !property.validator(value)) { // validator
- return false;
- } else {
-
- if (!Lang.isUndefined(value)) {
- property.value = value;
- } else {
- value = property.value;
- }
-
- foundDuplicate = false;
- iLen = this.eventQueue.length;
-
- for (i = 0; i < iLen; i++) {
- queueItem = this.eventQueue[i];
-
- if (queueItem) {
- queueItemKey = queueItem[0];
- queueItemValue = queueItem[1];
- if (queueItemKey == key) {
-
- /*
- found a dupe... push to end of queue, null
- current item, and break
- */
-
- this.eventQueue[i] = null;
-
- this.eventQueue.push(
- [key, (!Lang.isUndefined(value) ?
- value : queueItemValue)]);
-
- foundDuplicate = true;
- break;
- }
- }
- }
-
- // this is a refire, or a new property in the queue
-
- if (! foundDuplicate && !Lang.isUndefined(value)) {
- this.eventQueue.push([key, value]);
- }
- }
-
- if (property.supercedes) {
- sLen = property.supercedes.length;
- for (s = 0; s < sLen; s++) {
- supercedesCheck = property.supercedes[s];
- qLen = this.eventQueue.length;
- for (q = 0; q < qLen; q++) {
- queueItemCheck = this.eventQueue[q];
- if (queueItemCheck) {
- queueItemCheckKey = queueItemCheck[0];
- queueItemCheckValue = queueItemCheck[1];
- if (queueItemCheckKey ==
- supercedesCheck.toLowerCase() ) {
- this.eventQueue.push([queueItemCheckKey,
- queueItemCheckValue]);
- this.eventQueue[q] = null;
- break;
- }
- }
- }
- }
- }
- return true;
- } else {
- return false;
- }
- },
-
- /**
- * Fires the event for a property using the property's current value.
- * @method refireEvent
- * @param {String} key The name of the property
- */
- refireEvent: function (key) {
-
- key = key.toLowerCase();
-
- var property = this.config[key];
-
- if (property && property.event &&
-
- !Lang.isUndefined(property.value)) {
-
- if (this.queueInProgress) {
-
- this.queueProperty(key);
-
- } else {
-
- this.fireEvent(key, property.value);
-
- }
-
- }
- },
-
- /**
- * Applies a key-value Object literal to the configuration, replacing
- * any existing values, and queueing the property events.
- * Although the values will be set, fireQueue() must be called for their
- * associated events to execute.
- * @method applyConfig
- * @param {Object} userConfig The configuration Object literal
- * @param {Boolean} init When set to true, the initialConfig will
- * be set to the userConfig passed in, so that calling a reset will
- * reset the properties to the passed values.
- */
- applyConfig: function (userConfig, init) {
-
- var sKey,
- oConfig;
- if (init) {
- oConfig = {};
- for (sKey in userConfig) {
- if (Lang.hasOwnProperty(userConfig, sKey)) {
- oConfig[sKey.toLowerCase()] = userConfig[sKey];
- }
- }
- this.initialConfig = oConfig;
- }
- for (sKey in userConfig) {
- if (Lang.hasOwnProperty(userConfig, sKey)) {
- this.queueProperty(sKey, userConfig[sKey]);
- }
- }
- },
-
- /**
- * Refires the events for all configuration properties using their
- * current values.
- * @method refresh
- */
- refresh: function () {
- var prop;
- for (prop in this.config) {
- if (Lang.hasOwnProperty(this.config, prop)) {
- this.refireEvent(prop);
- }
- }
- },
-
- /**
- * Fires the normalized list of queued property change events
- * @method fireQueue
- */
- fireQueue: function () {
-
- var i,
- queueItem,
- key,
- value,
- property;
-
- this.queueInProgress = true;
- for (i = 0;i < this.eventQueue.length; i++) {
- queueItem = this.eventQueue[i];
- if (queueItem) {
-
- key = queueItem[0];
- value = queueItem[1];
- property = this.config[key];
- property.value = value;
- // Clear out queue entry, to avoid it being
- // re-added to the queue by any queueProperty/supercedes
- // calls which are invoked during fireEvent
- this.eventQueue[i] = null;
- this.fireEvent(key,value);
- }
- }
-
- this.queueInProgress = false;
- this.eventQueue = [];
- },
-
- /**
- * Subscribes an external handler to the change event for any
- * given property.
- * @method subscribeToConfigEvent
- * @param {String} key The property name
- * @param {Function} handler The handler function to use subscribe to
- * the property's event
- * @param {Object} obj The Object to use for scoping the event handler
- * (see CustomEvent documentation)
- * @param {Boolean} overrideContext Optional. If true, will override
- * "this" within the handler to map to the scope Object passed into the
- * method.
- * @return {Boolean} True, if the subscription was successful,
- * otherwise false.
- */
- subscribeToConfigEvent: function (key, handler, obj, overrideContext) {
-
- var property = this.config[key.toLowerCase()];
-
- if (property && property.event) {
- if (!Config.alreadySubscribed(property.event, handler, obj)) {
- property.event.subscribe(handler, obj, overrideContext);
- }
- return true;
- } else {
- return false;
- }
-
- },
-
- /**
- * Unsubscribes an external handler from the change event for any
- * given property.
- * @method unsubscribeFromConfigEvent
- * @param {String} key The property name
- * @param {Function} handler The handler function to use subscribe to
- * the property's event
- * @param {Object} obj The Object to use for scoping the event
- * handler (see CustomEvent documentation)
- * @return {Boolean} True, if the unsubscription was successful,
- * otherwise false.
- */
- unsubscribeFromConfigEvent: function (key, handler, obj) {
- var property = this.config[key.toLowerCase()];
- if (property && property.event) {
- return property.event.unsubscribe(handler, obj);
- } else {
- return false;
- }
- },
-
- /**
- * Returns a string representation of the Config object
- * @method toString
- * @return {String} The Config object in string format.
- */
- toString: function () {
- var output = "Config";
- if (this.owner) {
- output += " [" + this.owner.toString() + "]";
- }
- return output;
- },
-
- /**
- * Returns a string representation of the Config object's current
- * CustomEvent queue
- * @method outputEventQueue
- * @return {String} The string list of CustomEvents currently queued
- * for execution
- */
- outputEventQueue: function () {
- var output = "",
- queueItem,
- q,
- nQueue = this.eventQueue.length;
-
- for (q = 0; q < nQueue; q++) {
- queueItem = this.eventQueue[q];
- if (queueItem) {
- output += queueItem[0] + "=" + queueItem[1] + ", ";
- }
- }
- return output;
- },
- /**
- * Sets all properties to null, unsubscribes all listeners from each
- * property's change event and all listeners from the configChangedEvent.
- * @method destroy
- */
- destroy: function () {
- var oConfig = this.config,
- sProperty,
- oProperty;
- for (sProperty in oConfig) {
-
- if (Lang.hasOwnProperty(oConfig, sProperty)) {
- oProperty = oConfig[sProperty];
- oProperty.event.unsubscribeAll();
- oProperty.event = null;
- }
-
- }
-
- this.configChangedEvent.unsubscribeAll();
-
- this.configChangedEvent = null;
- this.owner = null;
- this.config = null;
- this.initialConfig = null;
- this.eventQueue = null;
-
- }
- };
-
-
-
- /**
- * Checks to determine if a particular function/Object pair are already
- * subscribed to the specified CustomEvent
- * @method YAHOO.util.Config.alreadySubscribed
- * @static
- * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check
- * the subscriptions
- * @param {Function} fn The function to look for in the subscribers list
- * @param {Object} obj The execution scope Object for the subscription
- * @return {Boolean} true, if the function/Object pair is already subscribed
- * to the CustomEvent passed in
- */
- Config.alreadySubscribed = function (evt, fn, obj) {
-
- var nSubscribers = evt.subscribers.length,
- subsc,
- i;
- if (nSubscribers > 0) {
- i = nSubscribers - 1;
- do {
- subsc = evt.subscribers[i];
- if (subsc && subsc.obj == obj && subsc.fn == fn) {
- return true;
- }
- }
- while (i--);
- }
- return false;
- };
- YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider);
- }());
- (function () {
- /**
- * The Container family of components is designed to enable developers to
- * create different kinds of content-containing modules on the web. Module
- * and Overlay are the most basic containers, and they can be used directly
- * or extended to build custom containers. Also part of the Container family
- * are four UI controls that extend Module and Overlay: Tooltip, Panel,
- * Dialog, and SimpleDialog.
- * @module container
- * @title Container
- * @requires yahoo, dom, event
- * @optional dragdrop, animation, button
- */
-
- /**
- * Module is a JavaScript representation of the Standard Module Format.
- * Standard Module Format is a simple standard for markup containers where
- * child nodes representing the header, body, and footer of the content are
- * denoted using the CSS classes "hd", "bd", and "ft" respectively.
- * Module is the base class for all other classes in the YUI
- * Container package.
- * @namespace YAHOO.widget
- * @class Module
- * @constructor
- * @param {String} el The element ID representing the Module <em>OR</em>
- * @param {HTMLElement} el The element representing the Module
- * @param {Object} userConfig The configuration Object literal containing
- * the configuration that should be set for this module. See configuration
- * documentation for more details.
- */
- YAHOO.widget.Module = function (el, userConfig) {
- if (el) {
- this.init(el, userConfig);
- } else {
- }
- };
- var Dom = YAHOO.util.Dom,
- Config = YAHOO.util.Config,
- Event = YAHOO.util.Event,
- CustomEvent = YAHOO.util.CustomEvent,
- Module = YAHOO.widget.Module,
- UA = YAHOO.env.ua,
- m_oModuleTemplate,
- m_oHeaderTemplate,
- m_oBodyTemplate,
- m_oFooterTemplate,
- /**
- * Constant representing the name of the Module's events
- * @property EVENT_TYPES
- * @private
- * @final
- * @type Object
- */
- EVENT_TYPES = {
- "BEFORE_INIT": "beforeInit",
- "INIT": "init",
- "APPEND": "append",
- "BEFORE_RENDER": "beforeRender",
- "RENDER": "render",
- "CHANGE_HEADER": "changeHeader",
- "CHANGE_BODY": "changeBody",
- "CHANGE_FOOTER": "changeFooter",
- "CHANGE_CONTENT": "changeContent",
- "DESTROY": "destroy",
- "BEFORE_SHOW": "beforeShow",
- "SHOW": "show",
- "BEFORE_HIDE": "beforeHide",
- "HIDE": "hide"
- },
-
- /**
- * Constant representing the Module's configuration properties
- * @property DEFAULT_CONFIG
- * @private
- * @final
- * @type Object
- */
- DEFAULT_CONFIG = {
-
- "VISIBLE": {
- key: "visible",
- value: true,
- validator: YAHOO.lang.isBoolean
- },
- "EFFECT": {
- key: "effect",
- suppressEvent: true,
- supercedes: ["visible"]
- },
- "MONITOR_RESIZE": {
- key: "monitorresize",
- value: true
- },
- "APPEND_TO_DOCUMENT_BODY": {
- key: "appendtodocumentbody",
- value: false
- }
- };
- /**
- * Constant representing the prefix path to use for non-secure images
- * @property YAHOO.widget.Module.IMG_ROOT
- * @static
- * @final
- * @type String
- */
- Module.IMG_ROOT = null;
-
- /**
- * Constant representing the prefix path to use for securely served images
- * @property YAHOO.widget.Module.IMG_ROOT_SSL
- * @static
- * @final
- * @type String
- */
- Module.IMG_ROOT_SSL = null;
-
- /**
- * Constant for the default CSS class name that represents a Module
- * @property YAHOO.widget.Module.CSS_MODULE
- * @static
- * @final
- * @type String
- */
- Module.CSS_MODULE = "yui-module";
-
- /**
- * Constant representing the module header
- * @property YAHOO.widget.Module.CSS_HEADER
- * @static
- * @final
- * @type String
- */
- Module.CSS_HEADER = "hd";
- /**
- * Constant representing the module body
- * @property YAHOO.widget.Module.CSS_BODY
- * @static
- * @final
- * @type String
- */
- Module.CSS_BODY = "bd";
-
- /**
- * Constant representing the module footer
- * @property YAHOO.widget.Module.CSS_FOOTER
- * @static
- * @final
- * @type String
- */
- Module.CSS_FOOTER = "ft";
-
- /**
- * Constant representing the url for the "src" attribute of the iframe
- * used to monitor changes to the browser's base font size
- * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL
- * @static
- * @final
- * @type String
- */
- Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;";
- /**
- * Constant representing the buffer amount (in pixels) to use when positioning
- * the text resize monitor offscreen. The resize monitor is positioned
- * offscreen by an amount eqaul to its offsetHeight + the buffer value.
- *
- * @property YAHOO.widget.Module.RESIZE_MONITOR_BUFFER
- * @static
- * @type Number
- */
- // Set to 1, to work around pixel offset in IE8, which increases when zoom is used
- Module.RESIZE_MONITOR_BUFFER = 1;
- /**
- * Singleton CustomEvent fired when the font size is changed in the browser.
- * Opera's "zoom" functionality currently does not support text
- * size detection.
- * @event YAHOO.widget.Module.textResizeEvent
- */
- Module.textResizeEvent = new CustomEvent("textResize");
- /**
- * Helper utility method, which forces a document level
- * redraw for Opera, which can help remove repaint
- * irregularities after applying DOM changes.
- *
- * @method YAHOO.widget.Module.forceDocumentRedraw
- * @static
- */
- Module.forceDocumentRedraw = function() {
- var docEl = document.documentElement;
- if (docEl) {
- docEl.className += " ";
- docEl.className = YAHOO.lang.trim(docEl.className);
- }
- };
- function createModuleTemplate() {
- if (!m_oModuleTemplate) {
- m_oModuleTemplate = document.createElement("div");
-
- m_oModuleTemplate.innerHTML = ("<div class=\"" +
- Module.CSS_HEADER + "\"></div>" + "<div class=\"" +
- Module.CSS_BODY + "\"></div><div class=\"" +
- Module.CSS_FOOTER + "\"></div>");
- m_oHeaderTemplate = m_oModuleTemplate.firstChild;
- m_oBodyTemplate = m_oHeaderTemplate.nextSibling;
- m_oFooterTemplate = m_oBodyTemplate.nextSibling;
- }
- return m_oModuleTemplate;
- }
- function createHeader() {
- if (!m_oHeaderTemplate) {
- createModuleTemplate();
- }
- return (m_oHeaderTemplate.cloneNode(false));
- }
- function createBody() {
- if (!m_oBodyTemplate) {
- createModuleTemplate();
- }
- return (m_oBodyTemplate.cloneNode(false));
- }
- function createFooter() {
- if (!m_oFooterTemplate) {
- createModuleTemplate();
- }
- return (m_oFooterTemplate.cloneNode(false));
- }
- Module.prototype = {
- /**
- * The class's constructor function
- * @property contructor
- * @type Function
- */
- constructor: Module,
-
- /**
- * The main module element that contains the header, body, and footer
- * @property element
- * @type HTMLElement
- */
- element: null,
- /**
- * The header element, denoted with CSS class "hd"
- * @property header
- * @type HTMLElement
- */
- header: null,
- /**
- * The body element, denoted with CSS class "bd"
- * @property body
- * @type HTMLElement
- */
- body: null,
- /**
- * The footer element, denoted with CSS class "ft"
- * @property footer
- * @type HTMLElement
- */
- footer: null,
- /**
- * The id of the element
- * @property id
- * @type String
- */
- id: null,
- /**
- * A string representing the root path for all images created by
- * a Module instance.
- * @deprecated It is recommend that any images for a Module be applied
- * via CSS using the "background-image" property.
- * @property imageRoot
- * @type String
- */
- imageRoot: Module.IMG_ROOT,
- /**
- * Initializes the custom events for Module which are fired
- * automatically at appropriate times by the Module class.
- * @method initEvents
- */
- initEvents: function () {
- var SIGNATURE = CustomEvent.LIST;
- /**
- * CustomEvent fired prior to class initalization.
- * @event beforeInitEvent
- * @param {class} classRef class reference of the initializing
- * class, such as this.beforeInitEvent.fire(Module)
- */
- this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT);
- this.beforeInitEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired after class initalization.
- * @event initEvent
- * @param {class} classRef class reference of the initializing
- * class, such as this.beforeInitEvent.fire(Module)
- */
- this.initEvent = this.createEvent(EVENT_TYPES.INIT);
- this.initEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired when the Module is appended to the DOM
- * @event appendEvent
- */
- this.appendEvent = this.createEvent(EVENT_TYPES.APPEND);
- this.appendEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired before the Module is rendered
- * @event beforeRenderEvent
- */
- this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER);
- this.beforeRenderEvent.signature = SIGNATURE;
-
- /**
- * CustomEvent fired after the Module is rendered
- * @event renderEvent
- */
- this.renderEvent = this.createEvent(EVENT_TYPES.RENDER);
- this.renderEvent.signature = SIGNATURE;
-
- /**
- * CustomEvent fired when the header content of the Module
- * is modified
- * @event changeHeaderEvent
- * @param {String/HTMLElement} content String/element representing
- * the new header content
- */
- this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER);
- this.changeHeaderEvent.signature = SIGNATURE;
-
- /**
- * CustomEvent fired when the body content of the Module is modified
- * @event changeBodyEvent
- * @param {String/HTMLElement} content String/element representing
- * the new body content
- */
- this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY);
- this.changeBodyEvent.signature = SIGNATURE;
-
- /**
- * CustomEvent fired when the footer content of the Module
- * is modified
- * @event changeFooterEvent
- * @param {String/HTMLElement} content String/element representing
- * the new footer content
- */
- this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER);
- this.changeFooterEvent.signature = SIGNATURE;
-
- /**
- * CustomEvent fired when the content of the Module is modified
- * @event changeContentEvent
- */
- this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT);
- this.changeContentEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired when the Module is destroyed
- * @event destroyEvent
- */
- this.destroyEvent = this.createEvent(EVENT_TYPES.DESTROY);
- this.destroyEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired before the Module is shown
- * @event beforeShowEvent
- */
- this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW);
- this.beforeShowEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired after the Module is shown
- * @event showEvent
- */
- this.showEvent = this.createEvent(EVENT_TYPES.SHOW);
- this.showEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired before the Module is hidden
- * @event beforeHideEvent
- */
- this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE);
- this.beforeHideEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired after the Module is hidden
- * @event hideEvent
- */
- this.hideEvent = this.createEvent(EVENT_TYPES.HIDE);
- this.hideEvent.signature = SIGNATURE;
- },
- /**
- * String representing the current user-agent platform
- * @property platform
- * @type String
- */
- platform: function () {
- var ua = navigator.userAgent.toLowerCase();
- if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
- return "windows";
- } else if (ua.indexOf("macintosh") != -1) {
- return "mac";
- } else {
- return false;
- }
- }(),
-
- /**
- * String representing the user-agent of the browser
- * @deprecated Use YAHOO.env.ua
- * @property browser
- * @type String
- */
- browser: function () {
- var ua = navigator.userAgent.toLowerCase();
- /*
- Check Opera first in case of spoof and check Safari before
- Gecko since Safari's user agent string includes "like Gecko"
- */
- if (ua.indexOf('opera') != -1) {
- return 'opera';
- } else if (ua.indexOf('msie 7') != -1) {
- return 'ie7';
- } else if (ua.indexOf('msie') != -1) {
- return 'ie';
- } else if (ua.indexOf('safari') != -1) {
- return 'safari';
- } else if (ua.indexOf('gecko') != -1) {
- return 'gecko';
- } else {
- return false;
- }
- }(),
-
- /**
- * Boolean representing whether or not the current browsing context is
- * secure (https)
- * @property isSecure
- * @type Boolean
- */
- isSecure: function () {
- if (window.location.href.toLowerCase().indexOf("https") === 0) {
- return true;
- } else {
- return false;
- }
- }(),
-
- /**
- * Initializes the custom events for Module which are fired
- * automatically at appropriate times by the Module class.
- */
- initDefaultConfig: function () {
- // Add properties //
- /**
- * Specifies whether the Module is visible on the page.
- * @config visible
- * @type Boolean
- * @default true
- */
- this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, {
- handler: this.configVisible,
- value: DEFAULT_CONFIG.VISIBLE.value,
- validator: DEFAULT_CONFIG.VISIBLE.validator
- });
- /**
- * <p>
- * Object or array of objects representing the ContainerEffect
- * classes that are active for animating the container.
- * </p>
- * <p>
- * <strong>NOTE:</strong> Although this configuration
- * property is introduced at the Module level, an out of the box
- * implementation is not shipped for the Module class so setting
- * the proroperty on the Module class has no effect. The Overlay
- * class is the first class to provide out of the box ContainerEffect
- * support.
- * </p>
- * @config effect
- * @type Object
- * @default null
- */
- this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, {
- suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent,
- supercedes: DEFAULT_CONFIG.EFFECT.supercedes
- });
- /**
- * Specifies whether to create a special proxy iframe to monitor
- * for user font resizing in the document
- * @config monitorresize
- * @type Boolean
- * @default true
- */
- this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, {
- handler: this.configMonitorResize,
- value: DEFAULT_CONFIG.MONITOR_RESIZE.value
- });
- /**
- * Specifies if the module should be rendered as the first child
- * of document.body or appended as the last child when render is called
- * with document.body as the "appendToNode".
- * <p>
- * Appending to the body while the DOM is still being constructed can
- * lead to Operation Aborted errors in IE hence this flag is set to
- * false by default.
- * </p>
- *
- * @config appendtodocumentbody
- * @type Boolean
- * @default false
- */
- this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, {
- value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value
- });
- },
- /**
- * The Module class's initialization method, which is executed for
- * Module and all of its subclasses. This method is automatically
- * called by the constructor, and sets up all DOM references for
- * pre-existing markup, and creates required markup if it is not
- * already present.
- * <p>
- * If the element passed in does not have an id, one will be generated
- * for it.
- * </p>
- * @method init
- * @param {String} el The element ID representing the Module <em>OR</em>
- * @param {HTMLElement} el The element representing the Module
- * @param {Object} userConfig The configuration Object literal
- * containing the configuration that should be set for this module.
- * See configuration documentation for more details.
- */
- init: function (el, userConfig) {
- var elId, child;
- this.initEvents();
- this.beforeInitEvent.fire(Module);
- /**
- * The Module's Config object used for monitoring
- * configuration properties.
- * @property cfg
- * @type YAHOO.util.Config
- */
- this.cfg = new Config(this);
- if (this.isSecure) {
- this.imageRoot = Module.IMG_ROOT_SSL;
- }
- if (typeof el == "string") {
- elId = el;
- el = document.getElementById(el);
- if (! el) {
- el = (createModuleTemplate()).cloneNode(false);
- el.id = elId;
- }
- }
- this.id = Dom.generateId(el);
- this.element = el;
- child = this.element.firstChild;
- if (child) {
- var fndHd = false, fndBd = false, fndFt = false;
- do {
- // We're looking for elements
- if (1 == child.nodeType) {
- if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) {
- this.header = child;
- fndHd = true;
- } else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) {
- this.body = child;
- fndBd = true;
- } else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){
- this.footer = child;
- fndFt = true;
- }
- }
- } while ((child = child.nextSibling));
- }
- this.initDefaultConfig();
- Dom.addClass(this.element, Module.CSS_MODULE);
- if (userConfig) {
- this.cfg.applyConfig(userConfig, true);
- }
- /*
- Subscribe to the fireQueue() method of Config so that any
- queued configuration changes are excecuted upon render of
- the Module
- */
- if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
- this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
- }
- this.initEvent.fire(Module);
- },
- /**
- * Initialize an empty IFRAME that is placed out of the visible area
- * that can be used to detect text resize.
- * @method initResizeMonitor
- */
- initResizeMonitor: function () {
- var isGeckoWin = (UA.gecko && this.platform == "windows");
- if (isGeckoWin) {
- // Help prevent spinning loading icon which
- // started with FireFox 2.0.0.8/Win
- var self = this;
- setTimeout(function(){self._initResizeMonitor();}, 0);
- } else {
- this._initResizeMonitor();
- }
- },
- /**
- * Create and initialize the text resize monitoring iframe.
- *
- * @protected
- * @method _initResizeMonitor
- */
- _initResizeMonitor : function() {
- var oDoc,
- oIFrame,
- sHTML;
- function fireTextResize() {
- Module.textResizeEvent.fire();
- }
- if (!UA.opera) {
- oIFrame = Dom.get("_yuiResizeMonitor");
- var supportsCWResize = this._supportsCWResize();
- if (!oIFrame) {
- oIFrame = document.createElement("iframe");
- if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && UA.ie) {
- oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL;
- }
- if (!supportsCWResize) {
- // Can't monitor on contentWindow, so fire from inside iframe
- sHTML = ["<html><head><script ",
- "type=\"text/javascript\">",
- "window.onresize=function(){window.parent.",
- "YAHOO.widget.Module.textResizeEvent.",
- "fire();};<",
- "\/script></head>",
- "<body></body></html>"].join('');
- oIFrame.src = "data:text/html;charset=utf-8," + encodeURIComponent(sHTML);
- }
- oIFrame.id = "_yuiResizeMonitor";
- oIFrame.title = "Text Resize Monitor";
- /*
- Need to set "position" property before inserting the
- iframe into the document or Safari's status bar will
- forever indicate the iframe is loading
- (See YUILibrary bug #1723064)
- */
- oIFrame.style.position = "absolute";
- oIFrame.style.visibility = "hidden";
- var db = document.body,
- fc = db.firstChild;
- if (fc) {
- db.insertBefore(oIFrame, fc);
- } else {
- db.appendChild(oIFrame);
- }
- // Setting the background color fixes an issue with IE6/IE7, where
- // elements in the DOM, with -ve margin-top which positioned them
- // offscreen (so they would be overlapped by the iframe and its -ve top
- // setting), would have their -ve margin-top ignored, when the iframe
- // was added.
- oIFrame.style.backgroundColor = "transparent";
- oIFrame.style.borderWidth = "0";
- oIFrame.style.width = "2em";
- oIFrame.style.height = "2em";
- oIFrame.style.left = "0";
- oIFrame.style.top = (-1 * (oIFrame.offsetHeight + Module.RESIZE_MONITOR_BUFFER)) + "px";
- oIFrame.style.visibility = "visible";
- /*
- Don't open/close the document for Gecko like we used to, since it
- leads to duplicate cookies. (See YUILibrary bug #1721755)
- */
- if (UA.webkit) {
- oDoc = oIFrame.contentWindow.document;
- oDoc.open();
- oDoc.close();
- }
- }
- if (oIFrame && oIFrame.contentWindow) {
- Module.textResizeEvent.subscribe(this.onDomResize, this, true);
- if (!Module.textResizeInitialized) {
- if (supportsCWResize) {
- if (!Event.on(oIFrame.contentWindow, "resize", fireTextResize)) {
- /*
- This will fail in IE if document.domain has
- changed, so we must change the listener to
- use the oIFrame element instead
- */
- Event.on(oIFrame, "resize", fireTextResize);
- }
- }
- Module.textResizeInitialized = true;
- }
- this.resizeMonitor = oIFrame;
- }
- }
- },
- /**
- * Text resize monitor helper method.
- * Determines if the browser supports resize events on iframe content windows.
- *
- * @private
- * @method _supportsCWResize
- */
- _supportsCWResize : function() {
- /*
- Gecko 1.8.0 (FF1.5), 1.8.1.0-5 (FF2) won't fire resize on contentWindow.
- Gecko 1.8.1.6+ (FF2.0.0.6+) and all other browsers will fire resize on contentWindow.
- We don't want to start sniffing for patch versions, so fire textResize the same
- way on all FF2 flavors
- */
- var bSupported = true;
- if (UA.gecko && UA.gecko <= 1.8) {
- bSupported = false;
- }
- return bSupported;
- },
- /**
- * Event handler fired when the resize monitor element is resized.
- * @method onDomResize
- * @param {DOMEvent} e The DOM resize event
- * @param {Object} obj The scope object passed to the handler
- */
- onDomResize: function (e, obj) {
- var nTop = -1 * (this.resizeMonitor.offsetHeight + Module.RESIZE_MONITOR_BUFFER);
- this.resizeMonitor.style.top = nTop + "px";
- this.resizeMonitor.style.left = "0";
- },
- /**
- * Sets the Module's header content to the string specified, or appends
- * the passed element to the header. If no header is present, one will
- * be automatically created. An empty string can be passed to the method
- * to clear the contents of the header.
- *
- * @method setHeader
- * @param {String} headerContent The string used to set the header.
- * As a convenience, non HTMLElement objects can also be passed into
- * the method, and will be treated as strings, with the header innerHTML
- * set to their default toString implementations.
- * <em>OR</em>
- * @param {HTMLElement} headerContent The HTMLElement to append to
- * <em>OR</em>
- * @param {DocumentFragment} headerContent The document fragment
- * containing elements which are to be added to the header
- */
- setHeader: function (headerContent) {
- var oHeader = this.header || (this.header = createHeader());
- if (headerContent.nodeName) {
- oHeader.innerHTML = "";
- oHeader.appendChild(headerContent);
- } else {
- oHeader.innerHTML = headerContent;
- }
- if (this._rendered) {
- this._renderHeader();
- }
- this.changeHeaderEvent.fire(headerContent);
- this.changeContentEvent.fire();
- },
- /**
- * Appends the passed element to the header. If no header is present,
- * one will be automatically created.
- * @method appendToHeader
- * @param {HTMLElement | DocumentFragment} element The element to
- * append to the header. In the case of a document fragment, the
- * children of the fragment will be appended to the header.
- */
- appendToHeader: function (element) {
- var oHeader = this.header || (this.header = createHeader());
- oHeader.appendChild(element);
- this.changeHeaderEvent.fire(element);
- this.changeContentEvent.fire();
- },
- /**
- * Sets the Module's body content to the HTML specified.
- *
- * If no body is present, one will be automatically created.
- *
- * An empty string can be passed to the method to clear the contents of the body.
- * @method setBody
- * @param {String} bodyContent The HTML used to set the body.
- * As a convenience, non HTMLElement objects can also be passed into
- * the method, and will be treated as strings, with the body innerHTML
- * set to their default toString implementations.
- * <em>OR</em>
- * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only
- * child of the body element.
- * <em>OR</em>
- * @param {DocumentFragment} bodyContent The document fragment
- * containing elements which are to be added to the body
- */
- setBody: function (bodyContent) {
- var oBody = this.body || (this.body = createBody());
- if (bodyContent.nodeName) {
- oBody.innerHTML = "";
- oBody.appendChild(bodyContent);
- } else {
- oBody.innerHTML = bodyContent;
- }
- if (this._rendered) {
- this._renderBody();
- }
- this.changeBodyEvent.fire(bodyContent);
- this.changeContentEvent.fire();
- },
- /**
- * Appends the passed element to the body. If no body is present, one
- * will be automatically created.
- * @method appendToBody
- * @param {HTMLElement | DocumentFragment} element The element to
- * append to the body. In the case of a document fragment, the
- * children of the fragment will be appended to the body.
- *
- */
- appendToBody: function (element) {
- var oBody = this.body || (this.body = createBody());
-
- oBody.appendChild(element);
- this.changeBodyEvent.fire(element);
- this.changeContentEvent.fire();
- },
-
- /**
- * Sets the Module's footer content to the HTML specified, or appends
- * the passed element to the footer. If no footer is present, one will
- * be automatically created. An empty string can be passed to the method
- * to clear the contents of the footer.
- * @method setFooter
- * @param {String} footerContent The HTML used to set the footer
- * As a convenience, non HTMLElement objects can also be passed into
- * the method, and will be treated as strings, with the footer innerHTML
- * set to their default toString implementations.
- * <em>OR</em>
- * @param {HTMLElement} footerContent The HTMLElement to append to
- * the footer
- * <em>OR</em>
- * @param {DocumentFragment} footerContent The document fragment containing
- * elements which are to be added to the footer
- */
- setFooter: function (footerContent) {
- var oFooter = this.footer || (this.footer = createFooter());
- if (footerContent.nodeName) {
- oFooter.innerHTML = "";
- oFooter.appendChild(footerContent);
- } else {
- oFooter.innerHTML = footerContent;
- }
- if (this._rendered) {
- this._renderFooter();
- }
- this.changeFooterEvent.fire(footerContent);
- this.changeContentEvent.fire();
- },
- /**
- * Appends the passed element to the footer. If no footer is present,
- * one will be automatically created.
- * @method appendToFooter
- * @param {HTMLElement | DocumentFragment} element The element to
- * append to the footer. In the case of a document fragment, the
- * children of the fragment will be appended to the footer
- */
- appendToFooter: function (element) {
- var oFooter = this.footer || (this.footer = createFooter());
- oFooter.appendChild(element);
- this.changeFooterEvent.fire(element);
- this.changeContentEvent.fire();
- },
- /**
- * Renders the Module by inserting the elements that are not already
- * in the main Module into their correct places. Optionally appends
- * the Module to the specified node prior to the render's execution.
- * <p>
- * For Modules without existing markup, the appendToNode argument
- * is REQUIRED. If this argument is ommitted and the current element is
- * not present in the document, the function will return false,
- * indicating that the render was a failure.
- * </p>
- * <p>
- * NOTE: As of 2.3.1, if the appendToNode is the document's body element
- * then the module is rendered as the first child of the body element,
- * and not appended to it, to avoid Operation Aborted errors in IE when
- * rendering the module before window's load event is fired. You can
- * use the appendtodocumentbody configuration property to change this
- * to append to document.body if required.
- * </p>
- * @method render
- * @param {String} appendToNode The element id to which the Module
- * should be appended to prior to rendering <em>OR</em>
- * @param {HTMLElement} appendToNode The element to which the Module
- * should be appended to prior to rendering
- * @param {HTMLElement} moduleElement OPTIONAL. The element that
- * represents the actual Standard Module container.
- * @return {Boolean} Success or failure of the render
- */
- render: function (appendToNode, moduleElement) {
- var me = this;
- function appendTo(parentNode) {
- if (typeof parentNode == "string") {
- parentNode = document.getElementById(parentNode);
- }
- if (parentNode) {
- me._addToParent(parentNode, me.element);
- me.appendEvent.fire();
- }
- }
- this.beforeRenderEvent.fire();
- if (! moduleElement) {
- moduleElement = this.element;
- }
- if (appendToNode) {
- appendTo(appendToNode);
- } else {
- // No node was passed in. If the element is not already in the Dom, this fails
- if (! Dom.inDocument(this.element)) {
- return false;
- }
- }
- this._renderHeader(moduleElement);
- this._renderBody(moduleElement);
- this._renderFooter(moduleElement);
- this._rendered = true;
- this.renderEvent.fire();
- return true;
- },
- /**
- * Renders the currently set header into it's proper position under the
- * module element. If the module element is not provided, "this.element"
- * is used.
- *
- * @method _renderHeader
- * @protected
- * @param {HTMLElement} moduleElement Optional. A reference to the module element
- */
- _renderHeader: function(moduleElement){
- moduleElement = moduleElement || this.element;
- // Need to get everything into the DOM if it isn't already
- if (this.header && !Dom.inDocument(this.header)) {
- // There is a header, but it's not in the DOM yet. Need to add it.
- var firstChild = moduleElement.firstChild;
- if (firstChild) {
- moduleElement.insertBefore(this.header, firstChild);
- } else {
- moduleElement.appendChild(this.header);
- }
- }
- },
- /**
- * Renders the currently set body into it's proper position under the
- * module element. If the module element is not provided, "this.element"
- * is used.
- *
- * @method _renderBody
- * @protected
- * @param {HTMLElement} moduleElement Optional. A reference to the module element.
- */
- _renderBody: function(moduleElement){
- moduleElement = moduleElement || this.element;
- if (this.body && !Dom.inDocument(this.body)) {
- // There is a body, but it's not in the DOM yet. Need to add it.
- if (this.footer && Dom.isAncestor(moduleElement, this.footer)) {
- moduleElement.insertBefore(this.body, this.footer);
- } else {
- moduleElement.appendChild(this.body);
- }
- }
- },
- /**
- * Renders the currently set footer into it's proper position under the
- * module element. If the module element is not provided, "this.element"
- * is used.
- *
- * @method _renderFooter
- * @protected
- * @param {HTMLElement} moduleElement Optional. A reference to the module element
- */
- _renderFooter: function(moduleElement){
- moduleElement = moduleElement || this.element;
- if (this.footer && !Dom.inDocument(this.footer)) {
- // There is a footer, but it's not in the DOM yet. Need to add it.
- moduleElement.appendChild(this.footer);
- }
- },
- /**
- * Removes the Module element from the DOM and sets all child elements
- * to null.
- * @method destroy
- */
- destroy: function () {
- var parent;
- if (this.element) {
- Event.purgeElement(this.element, true);
- parent = this.element.parentNode;
- }
- if (parent) {
- parent.removeChild(this.element);
- }
-
- this.element = null;
- this.header = null;
- this.body = null;
- this.footer = null;
- Module.textResizeEvent.unsubscribe(this.onDomResize, this);
- this.cfg.destroy();
- this.cfg = null;
- this.destroyEvent.fire();
- },
- /**
- * Shows the Module element by setting the visible configuration
- * property to true. Also fires two events: beforeShowEvent prior to
- * the visibility change, and showEvent after.
- * @method show
- */
- show: function () {
- this.cfg.setProperty("visible", true);
- },
- /**
- * Hides the Module element by setting the visible configuration
- * property to false. Also fires two events: beforeHideEvent prior to
- * the visibility change, and hideEvent after.
- * @method hide
- */
- hide: function () {
- this.cfg.setProperty("visible", false);
- },
-
- // BUILT-IN EVENT HANDLERS FOR MODULE //
- /**
- * Default event handler for changing the visibility property of a
- * Module. By default, this is achieved by switching the "display" style
- * between "block" and "none".
- * This method is responsible for firing showEvent and hideEvent.
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- * @method configVisible
- */
- configVisible: function (type, args, obj) {
- var visible = args[0];
- if (visible) {
- this.beforeShowEvent.fire();
- Dom.setStyle(this.element, "display", "block");
- this.showEvent.fire();
- } else {
- this.beforeHideEvent.fire();
- Dom.setStyle(this.element, "display", "none");
- this.hideEvent.fire();
- }
- },
- /**
- * Default event handler for the "monitorresize" configuration property
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- * @method configMonitorResize
- */
- configMonitorResize: function (type, args, obj) {
- var monitor = args[0];
- if (monitor) {
- this.initResizeMonitor();
- } else {
- Module.textResizeEvent.unsubscribe(this.onDomResize, this, true);
- this.resizeMonitor = null;
- }
- },
- /**
- * This method is a protected helper, used when constructing the DOM structure for the module
- * to account for situations which may cause Operation Aborted errors in IE. It should not
- * be used for general DOM construction.
- * <p>
- * If the parentNode is not document.body, the element is appended as the last element.
- * </p>
- * <p>
- * If the parentNode is document.body the element is added as the first child to help
- * prevent Operation Aborted errors in IE.
- * </p>
- *
- * @param {parentNode} The HTML element to which the element will be added
- * @param {element} The HTML element to be added to parentNode's children
- * @method _addToParent
- * @protected
- */
- _addToParent: function(parentNode, element) {
- if (!this.cfg.getProperty("appendtodocumentbody") && parentNode === document.body && parentNode.firstChild) {
- parentNode.insertBefore(element, parentNode.firstChild);
- } else {
- parentNode.appendChild(element);
- }
- },
- /**
- * Returns a String representation of the Object.
- * @method toString
- * @return {String} The string representation of the Module
- */
- toString: function () {
- return "Module " + this.id;
- }
- };
- YAHOO.lang.augmentProto(Module, YAHOO.util.EventProvider);
- }());
- (function () {
- /**
- * Overlay is a Module that is absolutely positioned above the page flow. It
- * has convenience methods for positioning and sizing, as well as options for
- * controlling zIndex and constraining the Overlay's position to the current
- * visible viewport. Overlay also contains a dynamicly generated IFRAME which
- * is placed beneath it for Internet Explorer 6 and 5.x so that it will be
- * properly rendered above SELECT elements.
- * @namespace YAHOO.widget
- * @class Overlay
- * @extends YAHOO.widget.Module
- * @param {String} el The element ID representing the Overlay <em>OR</em>
- * @param {HTMLElement} el The element representing the Overlay
- * @param {Object} userConfig The configuration object literal containing
- * the configuration that should be set for this Overlay. See configuration
- * documentation for more details.
- * @constructor
- */
- YAHOO.widget.Overlay = function (el, userConfig) {
- YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
- };
- var Lang = YAHOO.lang,
- CustomEvent = YAHOO.util.CustomEvent,
- Module = YAHOO.widget.Module,
- Event = YAHOO.util.Event,
- Dom = YAHOO.util.Dom,
- Config = YAHOO.util.Config,
- UA = YAHOO.env.ua,
- Overlay = YAHOO.widget.Overlay,
- _SUBSCRIBE = "subscribe",
- _UNSUBSCRIBE = "unsubscribe",
- _CONTAINED = "contained",
- m_oIFrameTemplate,
- /**
- * Constant representing the name of the Overlay's events
- * @property EVENT_TYPES
- * @private
- * @final
- * @type Object
- */
- EVENT_TYPES = {
- "BEFORE_MOVE": "beforeMove",
- "MOVE": "move"
- },
- /**
- * Constant representing the Overlay's configuration properties
- * @property DEFAULT_CONFIG
- * @private
- * @final
- * @type Object
- */
- DEFAULT_CONFIG = {
- "X": {
- key: "x",
- validator: Lang.isNumber,
- suppressEvent: true,
- supercedes: ["iframe"]
- },
- "Y": {
- key: "y",
- validator: Lang.isNumber,
- suppressEvent: true,
- supercedes: ["iframe"]
- },
- "XY": {
- key: "xy",
- suppressEvent: true,
- supercedes: ["iframe"]
- },
- "CONTEXT": {
- key: "context",
- suppressEvent: true,
- supercedes: ["iframe"]
- },
- "FIXED_CENTER": {
- key: "fixedcenter",
- value: false,
- supercedes: ["iframe", "visible"]
- },
- "WIDTH": {
- key: "width",
- suppressEvent: true,
- supercedes: ["context", "fixedcenter", "iframe"]
- },
- "HEIGHT": {
- key: "height",
- suppressEvent: true,
- supercedes: ["context", "fixedcenter", "iframe"]
- },
- "AUTO_FILL_HEIGHT" : {
- key: "autofillheight",
- supercedes: ["height"],
- value:"body"
- },
- "ZINDEX": {
- key: "zindex",
- value: null
- },
- "CONSTRAIN_TO_VIEWPORT": {
- key: "constraintoviewport",
- value: false,
- validator: Lang.isBoolean,
- supercedes: ["iframe", "x", "y", "xy"]
- },
- "IFRAME": {
- key: "iframe",
- value: (UA.ie == 6 ? true : false),
- validator: Lang.isBoolean,
- supercedes: ["zindex"]
- },
- "PREVENT_CONTEXT_OVERLAP": {
- key: "preventcontextoverlap",
- value: false,
- validator: Lang.isBoolean,
- supercedes: ["constraintoviewport"]
- }
- };
- /**
- * The URL that will be placed in the iframe
- * @property YAHOO.widget.Overlay.IFRAME_SRC
- * @static
- * @final
- * @type String
- */
- Overlay.IFRAME_SRC = "javascript:false;";
- /**
- * Number representing how much the iframe shim should be offset from each
- * side of an Overlay instance, in pixels.
- * @property YAHOO.widget.Overlay.IFRAME_SRC
- * @default 3
- * @static
- * @final
- * @type Number
- */
- Overlay.IFRAME_OFFSET = 3;
- /**
- * Number representing the minimum distance an Overlay instance should be
- * positioned relative to the boundaries of the browser's viewport, in pixels.
- * @property YAHOO.widget.Overlay.VIEWPORT_OFFSET
- * @default 10
- * @static
- * @final
- * @type Number
- */
- Overlay.VIEWPORT_OFFSET = 10;
- /**
- * Constant representing the top left corner of an element, used for
- * configuring the context element alignment
- * @property YAHOO.widget.Overlay.TOP_LEFT
- * @static
- * @final
- * @type String
- */
- Overlay.TOP_LEFT = "tl";
- /**
- * Constant representing the top right corner of an element, used for
- * configuring the context element alignment
- * @property YAHOO.widget.Overlay.TOP_RIGHT
- * @static
- * @final
- * @type String
- */
- Overlay.TOP_RIGHT = "tr";
- /**
- * Constant representing the top bottom left corner of an element, used for
- * configuring the context element alignment
- * @property YAHOO.widget.Overlay.BOTTOM_LEFT
- * @static
- * @final
- * @type String
- */
- Overlay.BOTTOM_LEFT = "bl";
- /**
- * Constant representing the bottom right corner of an element, used for
- * configuring the context element alignment
- * @property YAHOO.widget.Overlay.BOTTOM_RIGHT
- * @static
- * @final
- * @type String
- */
- Overlay.BOTTOM_RIGHT = "br";
- Overlay.PREVENT_OVERLAP_X = {
- "tltr": true,
- "blbr": true,
- "brbl": true,
- "trtl": true
- };
-
- Overlay.PREVENT_OVERLAP_Y = {
- "trbr": true,
- "tlbl": true,
- "bltl": true,
- "brtr": true
- };
- /**
- * Constant representing the default CSS class used for an Overlay
- * @property YAHOO.widget.Overlay.CSS_OVERLAY
- * @static
- * @final
- * @type String
- */
- Overlay.CSS_OVERLAY = "yui-overlay";
- /**
- * Constant representing the default hidden CSS class used for an Overlay. This class is
- * applied to the overlay's outer DIV whenever it's hidden.
- *
- * @property YAHOO.widget.Overlay.CSS_HIDDEN
- * @static
- * @final
- * @type String
- */
- Overlay.CSS_HIDDEN = "yui-overlay-hidden";
- /**
- * Constant representing the default CSS class used for an Overlay iframe shim.
- *
- * @property YAHOO.widget.Overlay.CSS_IFRAME
- * @static
- * @final
- * @type String
- */
- Overlay.CSS_IFRAME = "yui-overlay-iframe";
- /**
- * Constant representing the names of the standard module elements
- * used in the overlay.
- * @property YAHOO.widget.Overlay.STD_MOD_RE
- * @static
- * @final
- * @type RegExp
- */
- Overlay.STD_MOD_RE = /^\s*?(body|footer|header)\s*?$/i;
- /**
- * A singleton CustomEvent used for reacting to the DOM event for
- * window scroll
- * @event YAHOO.widget.Overlay.windowScrollEvent
- */
- Overlay.windowScrollEvent = new CustomEvent("windowScroll");
- /**
- * A singleton CustomEvent used for reacting to the DOM event for
- * window resize
- * @event YAHOO.widget.Overlay.windowResizeEvent
- */
- Overlay.windowResizeEvent = new CustomEvent("windowResize");
- /**
- * The DOM event handler used to fire the CustomEvent for window scroll
- * @method YAHOO.widget.Overlay.windowScrollHandler
- * @static
- * @param {DOMEvent} e The DOM scroll event
- */
- Overlay.windowScrollHandler = function (e) {
- var t = Event.getTarget(e);
- // - Webkit (Safari 2/3) and Opera 9.2x bubble scroll events from elements to window
- // - FF2/3 and IE6/7, Opera 9.5x don't bubble scroll events from elements to window
- // - IE doesn't recognize scroll registered on the document.
- //
- // Also, when document view is scrolled, IE doesn't provide a target,
- // rest of the browsers set target to window.document, apart from opera
- // which sets target to window.
- if (!t || t === window || t === window.document) {
- if (UA.ie) {
- if (! window.scrollEnd) {
- window.scrollEnd = -1;
- }
- clearTimeout(window.scrollEnd);
-
- window.scrollEnd = setTimeout(function () {
- Overlay.windowScrollEvent.fire();
- }, 1);
-
- } else {
- Overlay.windowScrollEvent.fire();
- }
- }
- };
- /**
- * The DOM event handler used to fire the CustomEvent for window resize
- * @method YAHOO.widget.Overlay.windowResizeHandler
- * @static
- * @param {DOMEvent} e The DOM resize event
- */
- Overlay.windowResizeHandler = function (e) {
- if (UA.ie) {
- if (! window.resizeEnd) {
- window.resizeEnd = -1;
- }
- clearTimeout(window.resizeEnd);
- window.resizeEnd = setTimeout(function () {
- Overlay.windowResizeEvent.fire();
- }, 100);
- } else {
- Overlay.windowResizeEvent.fire();
- }
- };
- /**
- * A boolean that indicated whether the window resize and scroll events have
- * already been subscribed to.
- * @property YAHOO.widget.Overlay._initialized
- * @private
- * @type Boolean
- */
- Overlay._initialized = null;
- if (Overlay._initialized === null) {
- Event.on(window, "scroll", Overlay.windowScrollHandler);
- Event.on(window, "resize", Overlay.windowResizeHandler);
- Overlay._initialized = true;
- }
- /**
- * Internal map of special event types, which are provided
- * by the instance. It maps the event type to the custom event
- * instance. Contains entries for the "windowScroll", "windowResize" and
- * "textResize" static container events.
- *
- * @property YAHOO.widget.Overlay._TRIGGER_MAP
- * @type Object
- * @static
- * @private
- */
- Overlay._TRIGGER_MAP = {
- "windowScroll" : Overlay.windowScrollEvent,
- "windowResize" : Overlay.windowResizeEvent,
- "textResize" : Module.textResizeEvent
- };
- YAHOO.extend(Overlay, Module, {
- /**
- * <p>
- * Array of default event types which will trigger
- * context alignment for the Overlay class.
- * </p>
- * <p>The array is empty by default for Overlay,
- * but maybe populated in future releases, so classes extending
- * Overlay which need to define their own set of CONTEXT_TRIGGERS
- * should concatenate their super class's prototype.CONTEXT_TRIGGERS
- * value with their own array of values.
- * </p>
- * <p>
- * E.g.:
- * <code>CustomOverlay.prototype.CONTEXT_TRIGGERS = YAHOO.widget.Overlay.prototype.CONTEXT_TRIGGERS.concat(["windowScroll"]);</code>
- * </p>
- *
- * @property CONTEXT_TRIGGERS
- * @type Array
- * @final
- */
- CONTEXT_TRIGGERS : [],
- /**
- * The Overlay initialization method, which is executed for Overlay and
- * all of its subclasses. This method is automatically called by the
- * constructor, and sets up all DOM references for pre-existing markup,
- * and creates required markup if it is not already present.
- * @method init
- * @param {String} el The element ID representing the Overlay <em>OR</em>
- * @param {HTMLElement} el The element representing the Overlay
- * @param {Object} userConfig The configuration object literal
- * containing the configuration that should be set for this Overlay.
- * See configuration documentation for more details.
- */
- init: function (el, userConfig) {
- /*
- Note that we don't pass the user config in here yet because we
- only want it executed once, at the lowest subclass level
- */
- Overlay.superclass.init.call(this, el/*, userConfig*/);
- this.beforeInitEvent.fire(Overlay);
- Dom.addClass(this.element, Overlay.CSS_OVERLAY);
- if (userConfig) {
- this.cfg.applyConfig(userConfig, true);
- }
- if (this.platform == "mac" && UA.gecko) {
- if (! Config.alreadySubscribed(this.showEvent,
- this.showMacGeckoScrollbars, this)) {
- this.showEvent.subscribe(this.showMacGeckoScrollbars,
- this, true);
- }
- if (! Config.alreadySubscribed(this.hideEvent,
- this.hideMacGeckoScrollbars, this)) {
- this.hideEvent.subscribe(this.hideMacGeckoScrollbars,
- this, true);
- }
- }
- this.initEvent.fire(Overlay);
- },
-
- /**
- * Initializes the custom events for Overlay which are fired
- * automatically at appropriate times by the Overlay class.
- * @method initEvents
- */
- initEvents: function () {
- Overlay.superclass.initEvents.call(this);
- var SIGNATURE = CustomEvent.LIST;
- /**
- * CustomEvent fired before the Overlay is moved.
- * @event beforeMoveEvent
- * @param {Number} x x coordinate
- * @param {Number} y y coordinate
- */
- this.beforeMoveEvent = this.createEvent(EVENT_TYPES.BEFORE_MOVE);
- this.beforeMoveEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired after the Overlay is moved.
- * @event moveEvent
- * @param {Number} x x coordinate
- * @param {Number} y y coordinate
- */
- this.moveEvent = this.createEvent(EVENT_TYPES.MOVE);
- this.moveEvent.signature = SIGNATURE;
- },
-
- /**
- * Initializes the class's configurable properties which can be changed
- * using the Overlay's Config object (cfg).
- * @method initDefaultConfig
- */
- initDefaultConfig: function () {
-
- Overlay.superclass.initDefaultConfig.call(this);
- var cfg = this.cfg;
- // Add overlay config properties //
-
- /**
- * The absolute x-coordinate position of the Overlay
- * @config x
- * @type Number
- * @default null
- */
- cfg.addProperty(DEFAULT_CONFIG.X.key, {
-
- handler: this.configX,
- validator: DEFAULT_CONFIG.X.validator,
- suppressEvent: DEFAULT_CONFIG.X.suppressEvent,
- supercedes: DEFAULT_CONFIG.X.supercedes
-
- });
- /**
- * The absolute y-coordinate position of the Overlay
- * @config y
- * @type Number
- * @default null
- */
- cfg.addProperty(DEFAULT_CONFIG.Y.key, {
- handler: this.configY,
- validator: DEFAULT_CONFIG.Y.validator,
- suppressEvent: DEFAULT_CONFIG.Y.suppressEvent,
- supercedes: DEFAULT_CONFIG.Y.supercedes
- });
- /**
- * An array with the absolute x and y positions of the Overlay
- * @config xy
- * @type Number[]
- * @default null
- */
- cfg.addProperty(DEFAULT_CONFIG.XY.key, {
- handler: this.configXY,
- suppressEvent: DEFAULT_CONFIG.XY.suppressEvent,
- supercedes: DEFAULT_CONFIG.XY.supercedes
- });
- /**
- * <p>
- * The array of context arguments for context-sensitive positioning.
- * </p>
- *
- * <p>
- * The format of the array is: <code>[contextElementOrId, overlayCorner, contextCorner, arrayOfTriggerEvents (optional), xyOffset (optional)]</code>, the
- * the 5 array elements described in detail below:
- * </p>
- *
- * <dl>
- * <dt>contextElementOrId <String|HTMLElement></dt>
- * <dd>A reference to the context element to which the overlay should be aligned (or it's id).</dd>
- * <dt>overlayCorner <String></dt>
- * <dd>The corner of the overlay which is to be used for alignment. This corner will be aligned to the
- * corner of the context element defined by the "contextCorner" entry which follows. Supported string values are:
- * "tr" (top right), "tl" (top left), "br" (bottom right), or "bl" (bottom left).</dd>
- * <dt>contextCorner <String></dt>
- * <dd>The corner of the context element which is to be used for alignment. Supported string values are the same ones listed for the "overlayCorner" entry above.</dd>
- * <dt>arrayOfTriggerEvents (optional) <Array[String|CustomEvent]></dt>
- * <dd>
- * <p>
- * By default, context alignment is a one time operation, aligning the Overlay to the context element when context configuration property is set, or when the <a href="#method_align">align</a>
- * method is invoked. However, you can use the optional "arrayOfTriggerEvents" entry to define the list of events which should force the overlay to re-align itself with the context element.
- * This is useful in situations where the layout of the document may change, resulting in the context element's position being modified.
- * </p>
- * <p>
- * The array can contain either event type strings for events the instance publishes (e.g. "beforeShow") or CustomEvent instances. Additionally the following
- * 3 static container event types are also currently supported : <code>"windowResize", "windowScroll", "textResize"</code> (defined in <a href="#property__TRIGGER_MAP">_TRIGGER_MAP</a> private property).
- * </p>
- * </dd>
- * <dt>xyOffset <Number[]></dt>
- * <dd>
- * A 2 element Array specifying the X and Y pixel amounts by which the Overlay should be offset from the aligned corner. e.g. [5,0] offsets the Overlay 5 pixels to the left, <em>after</em> aligning the given context corners.
- * NOTE: If using this property and no triggers need to be defined, the arrayOfTriggerEvents property should be set to null to maintain correct array positions for the arguments.
- * </dd>
- * </dl>
- *
- * <p>
- * For example, setting this property to <code>["img1", "tl", "bl"]</code> will
- * align the Overlay's top left corner to the bottom left corner of the
- * context element with id "img1".
- * </p>
- * <p>
- * Setting this property to <code>["img1", "tl", "bl", null, [0,5]</code> will
- * align the Overlay's top left corner to the bottom left corner of the
- * context element with id "img1", and then offset it by 5 pixels on the Y axis (providing a 5 pixel gap between the bottom of the context element and top of the overlay).
- * </p>
- * <p>
- * Adding the optional trigger values: <code>["img1", "tl", "bl", ["beforeShow", "windowResize"], [0,5]]</code>,
- * will re-align the overlay position, whenever the "beforeShow" or "windowResize" events are fired.
- * </p>
- *
- * @config context
- * @type Array
- * @default null
- */
- cfg.addProperty(DEFAULT_CONFIG.CONTEXT.key, {
- handler: this.configContext,
- suppressEvent: DEFAULT_CONFIG.CONTEXT.suppressEvent,
- supercedes: DEFAULT_CONFIG.CONTEXT.supercedes
- });
- /**
- * Determines whether or not the Overlay should be anchored
- * to the center of the viewport.
- *
- * <p>This property can be set to:</p>
- *
- * <dl>
- * <dt>true</dt>
- * <dd>
- * To enable fixed center positioning
- * <p>
- * When enabled, the overlay will
- * be positioned in the center of viewport when initially displayed, and
- * will remain in the center of the viewport whenever the window is
- * scrolled or resized.
- * </p>
- * <p>
- * If the overlay is too big for the viewport,
- * it's top left corner will be aligned with the top left corner of the viewport.
- * </p>
- * </dd>
- * <dt>false</dt>
- * <dd>
- * To disable fixed center positioning.
- * <p>In this case the overlay can still be
- * centered as a one-off operation, by invoking the <code>center()</code> method,
- * however it will not remain centered when the window is scrolled/resized.
- * </dd>
- * <dt>"contained"<dt>
- * <dd>To enable fixed center positioning, as with the <code>true</code> option.
- * <p>However, unlike setting the property to <code>true</code>,
- * when the property is set to <code>"contained"</code>, if the overlay is
- * too big for the viewport, it will not get automatically centered when the
- * user scrolls or resizes the window (until the window is large enough to contain the
- * overlay). This is useful in cases where the Overlay has both header and footer
- * UI controls which the user may need to access.
- * </p>
- * </dd>
- * </dl>
- *
- * @config fixedcenter
- * @type Boolean | String
- * @default false
- */
- cfg.addProperty(DEFAULT_CONFIG.FIXED_CENTER.key, {
- handler: this.configFixedCenter,
- value: DEFAULT_CONFIG.FIXED_CENTER.value,
- validator: DEFAULT_CONFIG.FIXED_CENTER.validator,
- supercedes: DEFAULT_CONFIG.FIXED_CENTER.supercedes
- });
-
- /**
- * CSS width of the Overlay.
- * @config width
- * @type String
- * @default null
- */
- cfg.addProperty(DEFAULT_CONFIG.WIDTH.key, {
- handler: this.configWidth,
- suppressEvent: DEFAULT_CONFIG.WIDTH.suppressEvent,
- supercedes: DEFAULT_CONFIG.WIDTH.supercedes
- });
- /**
- * CSS height of the Overlay.
- * @config height
- * @type String
- * @default null
- */
- cfg.addProperty(DEFAULT_CONFIG.HEIGHT.key, {
- handler: this.configHeight,
- suppressEvent: DEFAULT_CONFIG.HEIGHT.suppressEvent,
- supercedes: DEFAULT_CONFIG.HEIGHT.supercedes
- });
- /**
- * Standard module element which should auto fill out the height of the Overlay if the height config property is set.
- * Supported values are "header", "body", "footer".
- *
- * @config autofillheight
- * @type String
- * @default null
- */
- cfg.addProperty(DEFAULT_CONFIG.AUTO_FILL_HEIGHT.key, {
- handler: this.configAutoFillHeight,
- value : DEFAULT_CONFIG.AUTO_FILL_HEIGHT.value,
- validator : this._validateAutoFill,
- supercedes: DEFAULT_CONFIG.AUTO_FILL_HEIGHT.supercedes
- });
- /**
- * CSS z-index of the Overlay.
- * @config zIndex
- * @type Number
- * @default null
- */
- cfg.addProperty(DEFAULT_CONFIG.ZINDEX.key, {
- handler: this.configzIndex,
- value: DEFAULT_CONFIG.ZINDEX.value
- });
- /**
- * True if the Overlay should be prevented from being positioned
- * out of the viewport.
- * @config constraintoviewport
- * @type Boolean
- * @default false
- */
- cfg.addProperty(DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key, {
- handler: this.configConstrainToViewport,
- value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value,
- validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator,
- supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
- });
- /**
- * @config iframe
- * @description Boolean indicating whether or not the Overlay should
- * have an IFRAME shim; used to prevent SELECT elements from
- * poking through an Overlay instance in IE6. When set to "true",
- * the iframe shim is created when the Overlay instance is intially
- * made visible.
- * @type Boolean
- * @default true for IE6 and below, false for all other browsers.
- */
- cfg.addProperty(DEFAULT_CONFIG.IFRAME.key, {
- handler: this.configIframe,
- value: DEFAULT_CONFIG.IFRAME.value,
- validator: DEFAULT_CONFIG.IFRAME.validator,
- supercedes: DEFAULT_CONFIG.IFRAME.supercedes
- });
- /**
- * @config preventcontextoverlap
- * @description Boolean indicating whether or not the Overlay should overlap its
- * context element (defined using the "context" configuration property) when the
- * "constraintoviewport" configuration property is set to "true".
- * @type Boolean
- * @default false
- */
- cfg.addProperty(DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.key, {
- value: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.value,
- validator: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.validator,
- supercedes: DEFAULT_CONFIG.PREVENT_CONTEXT_OVERLAP.supercedes
- });
- },
- /**
- * Moves the Overlay to the specified position. This function is
- * identical to calling this.cfg.setProperty("xy", [x,y]);
- * @method moveTo
- * @param {Number} x The Overlay's new x position
- * @param {Number} y The Overlay's new y position
- */
- moveTo: function (x, y) {
- this.cfg.setProperty("xy", [x, y]);
- },
- /**
- * Adds a CSS class ("hide-scrollbars") and removes a CSS class
- * ("show-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
- * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
- * @method hideMacGeckoScrollbars
- */
- hideMacGeckoScrollbars: function () {
- Dom.replaceClass(this.element, "show-scrollbars", "hide-scrollbars");
- },
- /**
- * Adds a CSS class ("show-scrollbars") and removes a CSS class
- * ("hide-scrollbars") to the Overlay to fix a bug in Gecko on Mac OS X
- * (https://bugzilla.mozilla.org/show_bug.cgi?id=187435)
- * @method showMacGeckoScrollbars
- */
- showMacGeckoScrollbars: function () {
- Dom.replaceClass(this.element, "hide-scrollbars", "show-scrollbars");
- },
- /**
- * Internal implementation to set the visibility of the overlay in the DOM.
- *
- * @method _setDomVisibility
- * @param {boolean} visible Whether to show or hide the Overlay's outer element
- * @protected
- */
- _setDomVisibility : function(show) {
- Dom.setStyle(this.element, "visibility", (show) ? "visible" : "hidden");
- var hiddenClass = Overlay.CSS_HIDDEN;
- if (show) {
- Dom.removeClass(this.element, hiddenClass);
- } else {
- Dom.addClass(this.element, hiddenClass);
- }
- },
- // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
- /**
- * The default event handler fired when the "visible" property is
- * changed. This method is responsible for firing showEvent
- * and hideEvent.
- * @method configVisible
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configVisible: function (type, args, obj) {
- var visible = args[0],
- currentVis = Dom.getStyle(this.element, "visibility"),
- effect = this.cfg.getProperty("effect"),
- effectInstances = [],
- isMacGecko = (this.platform == "mac" && UA.gecko),
- alreadySubscribed = Config.alreadySubscribed,
- eff, ei, e, i, j, k, h,
- nEffects,
- nEffectInstances;
- if (currentVis == "inherit") {
- e = this.element.parentNode;
- while (e.nodeType != 9 && e.nodeType != 11) {
- currentVis = Dom.getStyle(e, "visibility");
- if (currentVis != "inherit") {
- break;
- }
- e = e.parentNode;
- }
- if (currentVis == "inherit") {
- currentVis = "visible";
- }
- }
- if (effect) {
- if (effect instanceof Array) {
- nEffects = effect.length;
- for (i = 0; i < nEffects; i++) {
- eff = effect[i];
- effectInstances[effectInstances.length] =
- eff.effect(this, eff.duration);
- }
- } else {
- effectInstances[effectInstances.length] =
- effect.effect(this, effect.duration);
- }
- }
- if (visible) { // Show
- if (isMacGecko) {
- this.showMacGeckoScrollbars();
- }
- if (effect) { // Animate in
- if (visible) { // Animate in if not showing
- if (currentVis != "visible" || currentVis === "") {
- this.beforeShowEvent.fire();
- nEffectInstances = effectInstances.length;
- for (j = 0; j < nEffectInstances; j++) {
- ei = effectInstances[j];
- if (j === 0 && !alreadySubscribed(
- ei.animateInCompleteEvent,
- this.showEvent.fire, this.showEvent)) {
- /*
- Delegate showEvent until end
- of animateInComplete
- */
- ei.animateInCompleteEvent.subscribe(
- this.showEvent.fire, this.showEvent, true);
- }
- ei.animateIn();
- }
- }
- }
- } else { // Show
- if (currentVis != "visible" || currentVis === "") {
- this.beforeShowEvent.fire();
- this._setDomVisibility(true);
- this.cfg.refireEvent("iframe");
- this.showEvent.fire();
- } else {
- this._setDomVisibility(true);
- }
- }
- } else { // Hide
- if (isMacGecko) {
- this.hideMacGeckoScrollbars();
- }
- if (effect) { // Animate out if showing
- if (currentVis == "visible") {
- this.beforeHideEvent.fire();
- nEffectInstances = effectInstances.length;
- for (k = 0; k < nEffectInstances; k++) {
- h = effectInstances[k];
-
- if (k === 0 && !alreadySubscribed(
- h.animateOutCompleteEvent, this.hideEvent.fire,
- this.hideEvent)) {
-
- /*
- Delegate hideEvent until end
- of animateOutComplete
- */
-
- h.animateOutCompleteEvent.subscribe(
- this.hideEvent.fire, this.hideEvent, true);
-
- }
- h.animateOut();
- }
- } else if (currentVis === "") {
- this._setDomVisibility(false);
- }
- } else { // Simple hide
- if (currentVis == "visible" || currentVis === "") {
- this.beforeHideEvent.fire();
- this._setDomVisibility(false);
- this.hideEvent.fire();
- } else {
- this._setDomVisibility(false);
- }
- }
- }
- },
- /**
- * Fixed center event handler used for centering on scroll/resize, but only if
- * the overlay is visible and, if "fixedcenter" is set to "contained", only if
- * the overlay fits within the viewport.
- *
- * @method doCenterOnDOMEvent
- */
- doCenterOnDOMEvent: function () {
- var cfg = this.cfg,
- fc = cfg.getProperty("fixedcenter");
- if (cfg.getProperty("visible")) {
- if (fc && (fc !== _CONTAINED || this.fitsInViewport())) {
- this.center();
- }
- }
- },
- /**
- * Determines if the Overlay (including the offset value defined by Overlay.VIEWPORT_OFFSET)
- * will fit entirely inside the viewport, in both dimensions - width and height.
- *
- * @method fitsInViewport
- * @return boolean true if the Overlay will fit, false if not
- */
- fitsInViewport : function() {
- var nViewportOffset = Overlay.VIEWPORT_OFFSET,
- element = this.element,
- elementWidth = element.offsetWidth,
- elementHeight = element.offsetHeight,
- viewportWidth = Dom.getViewportWidth(),
- viewportHeight = Dom.getViewportHeight();
- return ((elementWidth + nViewportOffset < viewportWidth) && (elementHeight + nViewportOffset < viewportHeight));
- },
- /**
- * The default event handler fired when the "fixedcenter" property
- * is changed.
- * @method configFixedCenter
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configFixedCenter: function (type, args, obj) {
- var val = args[0],
- alreadySubscribed = Config.alreadySubscribed,
- windowResizeEvent = Overlay.windowResizeEvent,
- windowScrollEvent = Overlay.windowScrollEvent;
- if (val) {
- this.center();
- if (!alreadySubscribed(this.beforeShowEvent, this.center)) {
- this.beforeShowEvent.subscribe(this.center);
- }
- if (!alreadySubscribed(windowResizeEvent, this.doCenterOnDOMEvent, this)) {
- windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
- }
- if (!alreadySubscribed(windowScrollEvent, this.doCenterOnDOMEvent, this)) {
- windowScrollEvent.subscribe(this.doCenterOnDOMEvent, this, true);
- }
- } else {
- this.beforeShowEvent.unsubscribe(this.center);
- windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
- windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
- }
- },
- /**
- * The default event handler fired when the "height" property is changed.
- * @method configHeight
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configHeight: function (type, args, obj) {
- var height = args[0],
- el = this.element;
- Dom.setStyle(el, "height", height);
- this.cfg.refireEvent("iframe");
- },
- /**
- * The default event handler fired when the "autofillheight" property is changed.
- * @method configAutoFillHeight
- *
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configAutoFillHeight: function (type, args, obj) {
- var fillEl = args[0],
- cfg = this.cfg,
- autoFillHeight = "autofillheight",
- height = "height",
- currEl = cfg.getProperty(autoFillHeight),
- autoFill = this._autoFillOnHeightChange;
- cfg.unsubscribeFromConfigEvent(height, autoFill);
- Module.textResizeEvent.unsubscribe(autoFill);
- this.changeContentEvent.unsubscribe(autoFill);
- if (currEl && fillEl !== currEl && this[currEl]) {
- Dom.setStyle(this[currEl], height, "");
- }
- if (fillEl) {
- fillEl = Lang.trim(fillEl.toLowerCase());
- cfg.subscribeToConfigEvent(height, autoFill, this[fillEl], this);
- Module.textResizeEvent.subscribe(autoFill, this[fillEl], this);
- this.changeContentEvent.subscribe(autoFill, this[fillEl], this);
- cfg.setProperty(autoFillHeight, fillEl, true);
- }
- },
- /**
- * The default event handler fired when the "width" property is changed.
- * @method configWidth
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configWidth: function (type, args, obj) {
- var width = args[0],
- el = this.element;
- Dom.setStyle(el, "width", width);
- this.cfg.refireEvent("iframe");
- },
- /**
- * The default event handler fired when the "zIndex" property is changed.
- * @method configzIndex
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configzIndex: function (type, args, obj) {
- var zIndex = args[0],
- el = this.element;
- if (! zIndex) {
- zIndex = Dom.getStyle(el, "zIndex");
- if (! zIndex || isNaN(zIndex)) {
- zIndex = 0;
- }
- }
- if (this.iframe || this.cfg.getProperty("iframe") === true) {
- if (zIndex <= 0) {
- zIndex = 1;
- }
- }
- Dom.setStyle(el, "zIndex", zIndex);
- this.cfg.setProperty("zIndex", zIndex, true);
- if (this.iframe) {
- this.stackIframe();
- }
- },
- /**
- * The default event handler fired when the "xy" property is changed.
- * @method configXY
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configXY: function (type, args, obj) {
- var pos = args[0],
- x = pos[0],
- y = pos[1];
- this.cfg.setProperty("x", x);
- this.cfg.setProperty("y", y);
- this.beforeMoveEvent.fire([x, y]);
- x = this.cfg.getProperty("x");
- y = this.cfg.getProperty("y");
- this.cfg.refireEvent("iframe");
- this.moveEvent.fire([x, y]);
- },
- /**
- * The default event handler fired when the "x" property is changed.
- * @method configX
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configX: function (type, args, obj) {
- var x = args[0],
- y = this.cfg.getProperty("y");
- this.cfg.setProperty("x", x, true);
- this.cfg.setProperty("y", y, true);
- this.beforeMoveEvent.fire([x, y]);
- x = this.cfg.getProperty("x");
- y = this.cfg.getProperty("y");
- Dom.setX(this.element, x, true);
- this.cfg.setProperty("xy", [x, y], true);
- this.cfg.refireEvent("iframe");
- this.moveEvent.fire([x, y]);
- },
- /**
- * The default event handler fired when the "y" property is changed.
- * @method configY
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configY: function (type, args, obj) {
- var x = this.cfg.getProperty("x"),
- y = args[0];
- this.cfg.setProperty("x", x, true);
- this.cfg.setProperty("y", y, true);
- this.beforeMoveEvent.fire([x, y]);
- x = this.cfg.getProperty("x");
- y = this.cfg.getProperty("y");
- Dom.setY(this.element, y, true);
- this.cfg.setProperty("xy", [x, y], true);
- this.cfg.refireEvent("iframe");
- this.moveEvent.fire([x, y]);
- },
-
- /**
- * Shows the iframe shim, if it has been enabled.
- * @method showIframe
- */
- showIframe: function () {
- var oIFrame = this.iframe,
- oParentNode;
- if (oIFrame) {
- oParentNode = this.element.parentNode;
- if (oParentNode != oIFrame.parentNode) {
- this._addToParent(oParentNode, oIFrame);
- }
- oIFrame.style.display = "block";
- }
- },
- /**
- * Hides the iframe shim, if it has been enabled.
- * @method hideIframe
- */
- hideIframe: function () {
- if (this.iframe) {
- this.iframe.style.display = "none";
- }
- },
- /**
- * Syncronizes the size and position of iframe shim to that of its
- * corresponding Overlay instance.
- * @method syncIframe
- */
- syncIframe: function () {
- var oIFrame = this.iframe,
- oElement = this.element,
- nOffset = Overlay.IFRAME_OFFSET,
- nDimensionOffset = (nOffset * 2),
- aXY;
- if (oIFrame) {
- // Size <iframe>
- oIFrame.style.width = (oElement.offsetWidth + nDimensionOffset + "px");
- oIFrame.style.height = (oElement.offsetHeight + nDimensionOffset + "px");
- // Position <iframe>
- aXY = this.cfg.getProperty("xy");
- if (!Lang.isArray(aXY) || (isNaN(aXY[0]) || isNaN(aXY[1]))) {
- this.syncPosition();
- aXY = this.cfg.getProperty("xy");
- }
- Dom.setXY(oIFrame, [(aXY[0] - nOffset), (aXY[1] - nOffset)]);
- }
- },
- /**
- * Sets the zindex of the iframe shim, if it exists, based on the zindex of
- * the Overlay element. The zindex of the iframe is set to be one less
- * than the Overlay element's zindex.
- *
- * <p>NOTE: This method will not bump up the zindex of the Overlay element
- * to ensure that the iframe shim has a non-negative zindex.
- * If you require the iframe zindex to be 0 or higher, the zindex of
- * the Overlay element should be set to a value greater than 0, before
- * this method is called.
- * </p>
- * @method stackIframe
- */
- stackIframe: function () {
- if (this.iframe) {
- var overlayZ = Dom.getStyle(this.element, "zIndex");
- if (!YAHOO.lang.isUndefined(overlayZ) && !isNaN(overlayZ)) {
- Dom.setStyle(this.iframe, "zIndex", (overlayZ - 1));
- }
- }
- },
- /**
- * The default event handler fired when the "iframe" property is changed.
- * @method configIframe
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configIframe: function (type, args, obj) {
- var bIFrame = args[0];
- function createIFrame() {
- var oIFrame = this.iframe,
- oElement = this.element,
- oParent;
- if (!oIFrame) {
- if (!m_oIFrameTemplate) {
- m_oIFrameTemplate = document.createElement("iframe");
- if (this.isSecure) {
- m_oIFrameTemplate.src = Overlay.IFRAME_SRC;
- }
- /*
- Set the opacity of the <iframe> to 0 so that it
- doesn't modify the opacity of any transparent
- elements that may be on top of it (like a shadow).
- */
- if (UA.ie) {
- m_oIFrameTemplate.style.filter = "alpha(opacity=0)";
- /*
- Need to set the "frameBorder" property to 0
- supress the default <iframe> border in IE.
- Setting the CSS "border" property alone
- doesn't supress it.
- */
- m_oIFrameTemplate.frameBorder = 0;
- }
- else {
- m_oIFrameTemplate.style.opacity = "0";
- }
- m_oIFrameTemplate.style.position = "absolute";
- m_oIFrameTemplate.style.border = "none";
- m_oIFrameTemplate.style.margin = "0";
- m_oIFrameTemplate.style.padding = "0";
- m_oIFrameTemplate.style.display = "none";
- m_oIFrameTemplate.tabIndex = -1;
- m_oIFrameTemplate.className = Overlay.CSS_IFRAME;
- }
- oIFrame = m_oIFrameTemplate.cloneNode(false);
- oIFrame.id = this.id + "_f";
- oParent = oElement.parentNode;
- var parentNode = oParent || document.body;
- this._addToParent(parentNode, oIFrame);
- this.iframe = oIFrame;
- }
- /*
- Show the <iframe> before positioning it since the "setXY"
- method of DOM requires the element be in the document
- and visible.
- */
- this.showIframe();
- /*
- Syncronize the size and position of the <iframe> to that
- of the Overlay.
- */
- this.syncIframe();
- this.stackIframe();
- // Add event listeners to update the <iframe> when necessary
- if (!this._hasIframeEventListeners) {
- this.showEvent.subscribe(this.showIframe);
- this.hideEvent.subscribe(this.hideIframe);
- this.changeContentEvent.subscribe(this.syncIframe);
- this._hasIframeEventListeners = true;
- }
- }
- function onBeforeShow() {
- createIFrame.call(this);
- this.beforeShowEvent.unsubscribe(onBeforeShow);
- this._iframeDeferred = false;
- }
- if (bIFrame) { // <iframe> shim is enabled
- if (this.cfg.getProperty("visible")) {
- createIFrame.call(this);
- } else {
- if (!this._iframeDeferred) {
- this.beforeShowEvent.subscribe(onBeforeShow);
- this._iframeDeferred = true;
- }
- }
- } else { // <iframe> shim is disabled
- this.hideIframe();
- if (this._hasIframeEventListeners) {
- this.showEvent.unsubscribe(this.showIframe);
- this.hideEvent.unsubscribe(this.hideIframe);
- this.changeContentEvent.unsubscribe(this.syncIframe);
- this._hasIframeEventListeners = false;
- }
- }
- },
- /**
- * Set's the container's XY value from DOM if not already set.
- *
- * Differs from syncPosition, in that the XY value is only sync'd with DOM if
- * not already set. The method also refire's the XY config property event, so any
- * beforeMove, Move event listeners are invoked.
- *
- * @method _primeXYFromDOM
- * @protected
- */
- _primeXYFromDOM : function() {
- if (YAHOO.lang.isUndefined(this.cfg.getProperty("xy"))) {
- // Set CFG XY based on DOM XY
- this.syncPosition();
- // Account for XY being set silently in syncPosition (no moveTo fired/called)
- this.cfg.refireEvent("xy");
- this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
- }
- },
- /**
- * The default event handler fired when the "constraintoviewport"
- * property is changed.
- * @method configConstrainToViewport
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for
- * the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configConstrainToViewport: function (type, args, obj) {
- var val = args[0];
- if (val) {
- if (! Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
- this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
- }
- if (! Config.alreadySubscribed(this.beforeShowEvent, this._primeXYFromDOM)) {
- this.beforeShowEvent.subscribe(this._primeXYFromDOM);
- }
- } else {
- this.beforeShowEvent.unsubscribe(this._primeXYFromDOM);
- this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
- }
- },
- /**
- * The default event handler fired when the "context" property
- * is changed.
- *
- * @method configContext
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configContext: function (type, args, obj) {
- var contextArgs = args[0],
- contextEl,
- elementMagnetCorner,
- contextMagnetCorner,
- triggers,
- offset,
- defTriggers = this.CONTEXT_TRIGGERS;
- if (contextArgs) {
- contextEl = contextArgs[0];
- elementMagnetCorner = contextArgs[1];
- contextMagnetCorner = contextArgs[2];
- triggers = contextArgs[3];
- offset = contextArgs[4];
- if (defTriggers && defTriggers.length > 0) {
- triggers = (triggers || []).concat(defTriggers);
- }
- if (contextEl) {
- if (typeof contextEl == "string") {
- this.cfg.setProperty("context", [
- document.getElementById(contextEl),
- elementMagnetCorner,
- contextMagnetCorner,
- triggers,
- offset],
- true);
- }
- if (elementMagnetCorner && contextMagnetCorner) {
- this.align(elementMagnetCorner, contextMagnetCorner, offset);
- }
- if (this._contextTriggers) {
- // Unsubscribe Old Set
- this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
- }
- if (triggers) {
- // Subscribe New Set
- this._processTriggers(triggers, _SUBSCRIBE, this._alignOnTrigger);
- this._contextTriggers = triggers;
- }
- }
- }
- },
- /**
- * Custom Event handler for context alignment triggers. Invokes the align method
- *
- * @method _alignOnTrigger
- * @protected
- *
- * @param {String} type The event type (not used by the default implementation)
- * @param {Any[]} args The array of arguments for the trigger event (not used by the default implementation)
- */
- _alignOnTrigger: function(type, args) {
- this.align();
- },
- /**
- * Helper method to locate the custom event instance for the event name string
- * passed in. As a convenience measure, any custom events passed in are returned.
- *
- * @method _findTriggerCE
- * @private
- *
- * @param {String|CustomEvent} t Either a CustomEvent, or event type (e.g. "windowScroll") for which a
- * custom event instance needs to be looked up from the Overlay._TRIGGER_MAP.
- */
- _findTriggerCE : function(t) {
- var tce = null;
- if (t instanceof CustomEvent) {
- tce = t;
- } else if (Overlay._TRIGGER_MAP[t]) {
- tce = Overlay._TRIGGER_MAP[t];
- }
- return tce;
- },
- /**
- * Utility method that subscribes or unsubscribes the given
- * function from the list of trigger events provided.
- *
- * @method _processTriggers
- * @protected
- *
- * @param {Array[String|CustomEvent]} triggers An array of either CustomEvents, event type strings
- * (e.g. "beforeShow", "windowScroll") to/from which the provided function should be
- * subscribed/unsubscribed respectively.
- *
- * @param {String} mode Either "subscribe" or "unsubscribe", specifying whether or not
- * we are subscribing or unsubscribing trigger listeners
- *
- * @param {Function} fn The function to be subscribed/unsubscribed to/from the trigger event.
- * Context is always set to the overlay instance, and no additional object argument
- * get passed to the subscribed function.
- */
- _processTriggers : function(triggers, mode, fn) {
- var t, tce;
- for (var i = 0, l = triggers.length; i < l; ++i) {
- t = triggers[i];
- tce = this._findTriggerCE(t);
- if (tce) {
- tce[mode](fn, this, true);
- } else {
- this[mode](t, fn);
- }
- }
- },
- // END BUILT-IN PROPERTY EVENT HANDLERS //
- /**
- * Aligns the Overlay to its context element using the specified corner
- * points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT,
- * and BOTTOM_RIGHT.
- * @method align
- * @param {String} elementAlign The String representing the corner of
- * the Overlay that should be aligned to the context element
- * @param {String} contextAlign The corner of the context element
- * that the elementAlign corner should stick to.
- * @param {Number[]} xyOffset Optional. A 2 element array specifying the x and y pixel offsets which should be applied
- * after aligning the element and context corners. For example, passing in [5, -10] for this value, would offset the
- * Overlay by 5 pixels along the X axis (horizontally) and -10 pixels along the Y axis (vertically) after aligning the specified corners.
- */
- align: function (elementAlign, contextAlign, xyOffset) {
- var contextArgs = this.cfg.getProperty("context"),
- me = this,
- context,
- element,
- contextRegion;
- function doAlign(v, h) {
- var alignX = null, alignY = null;
- switch (elementAlign) {
-
- case Overlay.TOP_LEFT:
- alignX = h;
- alignY = v;
- break;
-
- case Overlay.TOP_RIGHT:
- alignX = h - element.offsetWidth;
- alignY = v;
- break;
-
- case Overlay.BOTTOM_LEFT:
- alignX = h;
- alignY = v - element.offsetHeight;
- break;
-
- case Overlay.BOTTOM_RIGHT:
- alignX = h - element.offsetWidth;
- alignY = v - element.offsetHeight;
- break;
- }
- if (alignX !== null && alignY !== null) {
- if (xyOffset) {
- alignX += xyOffset[0];
- alignY += xyOffset[1];
- }
- me.moveTo(alignX, alignY);
- }
- }
- if (contextArgs) {
- context = contextArgs[0];
- element = this.element;
- me = this;
- if (! elementAlign) {
- elementAlign = contextArgs[1];
- }
- if (! contextAlign) {
- contextAlign = contextArgs[2];
- }
- if (!xyOffset && contextArgs[4]) {
- xyOffset = contextArgs[4];
- }
- if (element && context) {
- contextRegion = Dom.getRegion(context);
- switch (contextAlign) {
-
- case Overlay.TOP_LEFT:
- doAlign(contextRegion.top, contextRegion.left);
- break;
-
- case Overlay.TOP_RIGHT:
- doAlign(contextRegion.top, contextRegion.right);
- break;
-
- case Overlay.BOTTOM_LEFT:
- doAlign(contextRegion.bottom, contextRegion.left);
- break;
-
- case Overlay.BOTTOM_RIGHT:
- doAlign(contextRegion.bottom, contextRegion.right);
- break;
- }
- }
- }
- },
- /**
- * The default event handler executed when the moveEvent is fired, if the
- * "constraintoviewport" is set to true.
- * @method enforceConstraints
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- enforceConstraints: function (type, args, obj) {
- var pos = args[0];
- var cXY = this.getConstrainedXY(pos[0], pos[1]);
- this.cfg.setProperty("x", cXY[0], true);
- this.cfg.setProperty("y", cXY[1], true);
- this.cfg.setProperty("xy", cXY, true);
- },
- /**
- * Shared implementation method for getConstrainedX and getConstrainedY.
- *
- * <p>
- * Given a coordinate value, returns the calculated coordinate required to
- * position the Overlay if it is to be constrained to the viewport, based on the
- * current element size, viewport dimensions, scroll values and preventoverlap
- * settings
- * </p>
- *
- * @method _getConstrainedPos
- * @protected
- * @param {String} pos The coordinate which needs to be constrained, either "x" or "y"
- * @param {Number} The coordinate value which needs to be constrained
- * @return {Number} The constrained coordinate value
- */
- _getConstrainedPos: function(pos, val) {
- var overlayEl = this.element,
- buffer = Overlay.VIEWPORT_OFFSET,
- x = (pos == "x"),
- overlaySize = (x) ? overlayEl.offsetWidth : overlayEl.offsetHeight,
- viewportSize = (x) ? Dom.getViewportWidth() : Dom.getViewportHeight(),
- docScroll = (x) ? Dom.getDocumentScrollLeft() : Dom.getDocumentScrollTop(),
- overlapPositions = (x) ? Overlay.PREVENT_OVERLAP_X : Overlay.PREVENT_OVERLAP_Y,
- context = this.cfg.getProperty("context"),
- bOverlayFitsInViewport = (overlaySize + buffer < viewportSize),
- bPreventContextOverlap = this.cfg.getProperty("preventcontextoverlap") && context && overlapPositions[(context[1] + context[2])],
- minConstraint = docScroll + buffer,
- maxConstraint = docScroll + viewportSize - overlaySize - buffer,
- constrainedVal = val;
- if (val < minConstraint || val > maxConstraint) {
- if (bPreventContextOverlap) {
- constrainedVal = this._preventOverlap(pos, context[0], overlaySize, viewportSize, docScroll);
- } else {
- if (bOverlayFitsInViewport) {
- if (val < minConstraint) {
- constrainedVal = minConstraint;
- } else if (val > maxConstraint) {
- constrainedVal = maxConstraint;
- }
- } else {
- constrainedVal = minConstraint;
- }
- }
- }
- return constrainedVal;
- },
- /**
- * Helper method, used to position the Overlap to prevent overlap with the
- * context element (used when preventcontextoverlap is enabled)
- *
- * @method _preventOverlap
- * @protected
- * @param {String} pos The coordinate to prevent overlap for, either "x" or "y".
- * @param {HTMLElement} contextEl The context element
- * @param {Number} overlaySize The related overlay dimension value (for "x", the width, for "y", the height)
- * @param {Number} viewportSize The related viewport dimension value (for "x", the width, for "y", the height)
- * @param {Object} docScroll The related document scroll value (for "x", the scrollLeft, for "y", the scrollTop)
- *
- * @return {Number} The new coordinate value which was set to prevent overlap
- */
- _preventOverlap : function(pos, contextEl, overlaySize, viewportSize, docScroll) {
-
- var x = (pos == "x"),
- buffer = Overlay.VIEWPORT_OFFSET,
- overlay = this,
- contextElPos = ((x) ? Dom.getX(contextEl) : Dom.getY(contextEl)) - docScroll,
- contextElSize = (x) ? contextEl.offsetWidth : contextEl.offsetHeight,
- minRegionSize = contextElPos - buffer,
- maxRegionSize = (viewportSize - (contextElPos + contextElSize)) - buffer,
- bFlipped = false,
- flip = function () {
- var flippedVal;
- if ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) {
- flippedVal = (contextElPos - overlaySize);
- } else {
- flippedVal = (contextElPos + contextElSize);
- }
- overlay.cfg.setProperty(pos, (flippedVal + docScroll), true);
- return flippedVal;
- },
- setPosition = function () {
- var displayRegionSize = ((overlay.cfg.getProperty(pos) - docScroll) > contextElPos) ? maxRegionSize : minRegionSize,
- position;
- if (overlaySize > displayRegionSize) {
- if (bFlipped) {
- /*
- All possible positions and values have been
- tried, but none were successful, so fall back
- to the original size and position.
- */
- flip();
- } else {
- flip();
- bFlipped = true;
- position = setPosition();
- }
- }
- return position;
- };
- setPosition();
- return this.cfg.getProperty(pos);
- },
- /**
- * Given x coordinate value, returns the calculated x coordinate required to
- * position the Overlay if it is to be constrained to the viewport, based on the
- * current element size, viewport dimensions and scroll values.
- *
- * @param {Number} x The X coordinate value to be constrained
- * @return {Number} The constrained x coordinate
- */
- getConstrainedX: function (x) {
- return this._getConstrainedPos("x", x);
- },
- /**
- * Given y coordinate value, returns the calculated y coordinate required to
- * position the Overlay if it is to be constrained to the viewport, based on the
- * current element size, viewport dimensions and scroll values.
- *
- * @param {Number} y The Y coordinate value to be constrained
- * @return {Number} The constrained y coordinate
- */
- getConstrainedY : function (y) {
- return this._getConstrainedPos("y", y);
- },
- /**
- * Given x, y coordinate values, returns the calculated coordinates required to
- * position the Overlay if it is to be constrained to the viewport, based on the
- * current element size, viewport dimensions and scroll values.
- *
- * @param {Number} x The X coordinate value to be constrained
- * @param {Number} y The Y coordinate value to be constrained
- * @return {Array} The constrained x and y coordinates at index 0 and 1 respectively;
- */
- getConstrainedXY: function(x, y) {
- return [this.getConstrainedX(x), this.getConstrainedY(y)];
- },
- /**
- * Centers the container in the viewport.
- * @method center
- */
- center: function () {
- var nViewportOffset = Overlay.VIEWPORT_OFFSET,
- elementWidth = this.element.offsetWidth,
- elementHeight = this.element.offsetHeight,
- viewPortWidth = Dom.getViewportWidth(),
- viewPortHeight = Dom.getViewportHeight(),
- x,
- y;
- if (elementWidth < viewPortWidth) {
- x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
- } else {
- x = nViewportOffset + Dom.getDocumentScrollLeft();
- }
- if (elementHeight < viewPortHeight) {
- y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
- } else {
- y = nViewportOffset + Dom.getDocumentScrollTop();
- }
- this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
- this.cfg.refireEvent("iframe");
- if (UA.webkit) {
- this.forceContainerRedraw();
- }
- },
- /**
- * Synchronizes the Panel's "xy", "x", and "y" properties with the
- * Panel's position in the DOM. This is primarily used to update
- * position information during drag & drop.
- * @method syncPosition
- */
- syncPosition: function () {
- var pos = Dom.getXY(this.element);
- this.cfg.setProperty("x", pos[0], true);
- this.cfg.setProperty("y", pos[1], true);
- this.cfg.setProperty("xy", pos, true);
- },
- /**
- * Event handler fired when the resize monitor element is resized.
- * @method onDomResize
- * @param {DOMEvent} e The resize DOM event
- * @param {Object} obj The scope object
- */
- onDomResize: function (e, obj) {
- var me = this;
- Overlay.superclass.onDomResize.call(this, e, obj);
- setTimeout(function () {
- me.syncPosition();
- me.cfg.refireEvent("iframe");
- me.cfg.refireEvent("context");
- }, 0);
- },
- /**
- * Determines the content box height of the given element (height of the element, without padding or borders) in pixels.
- *
- * @method _getComputedHeight
- * @private
- * @param {HTMLElement} el The element for which the content height needs to be determined
- * @return {Number} The content box height of the given element, or null if it could not be determined.
- */
- _getComputedHeight : (function() {
- if (document.defaultView && document.defaultView.getComputedStyle) {
- return function(el) {
- var height = null;
- if (el.ownerDocument && el.ownerDocument.defaultView) {
- var computed = el.ownerDocument.defaultView.getComputedStyle(el, '');
- if (computed) {
- height = parseInt(computed.height, 10);
- }
- }
- return (Lang.isNumber(height)) ? height : null;
- };
- } else {
- return function(el) {
- var height = null;
- if (el.style.pixelHeight) {
- height = el.style.pixelHeight;
- }
- return (Lang.isNumber(height)) ? height : null;
- };
- }
- })(),
- /**
- * autofillheight validator. Verifies that the autofill value is either null
- * or one of the strings : "body", "header" or "footer".
- *
- * @method _validateAutoFillHeight
- * @protected
- * @param {String} val
- * @return true, if valid, false otherwise
- */
- _validateAutoFillHeight : function(val) {
- return (!val) || (Lang.isString(val) && Overlay.STD_MOD_RE.test(val));
- },
- /**
- * The default custom event handler executed when the overlay's height is changed,
- * if the autofillheight property has been set.
- *
- * @method _autoFillOnHeightChange
- * @protected
- * @param {String} type The event type
- * @param {Array} args The array of arguments passed to event subscribers
- * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
- * out the containers height
- */
- _autoFillOnHeightChange : function(type, args, el) {
- var height = this.cfg.getProperty("height");
- if ((height && height !== "auto") || (height === 0)) {
- this.fillHeight(el);
- }
- },
- /**
- * Returns the sub-pixel height of the el, using getBoundingClientRect, if available,
- * otherwise returns the offsetHeight
- * @method _getPreciseHeight
- * @private
- * @param {HTMLElement} el
- * @return {Float} The sub-pixel height if supported by the browser, else the rounded height.
- */
- _getPreciseHeight : function(el) {
- var height = el.offsetHeight;
- if (el.getBoundingClientRect) {
- var rect = el.getBoundingClientRect();
- height = rect.bottom - rect.top;
- }
- return height;
- },
- /**
- * <p>
- * Sets the height on the provided header, body or footer element to
- * fill out the height of the container. It determines the height of the
- * containers content box, based on it's configured height value, and
- * sets the height of the autofillheight element to fill out any
- * space remaining after the other standard module element heights
- * have been accounted for.
- * </p>
- * <p><strong>NOTE:</strong> This method is not designed to work if an explicit
- * height has not been set on the container, since for an "auto" height container,
- * the heights of the header/body/footer will drive the height of the container.</p>
- *
- * @method fillHeight
- * @param {HTMLElement} el The element which should be resized to fill out the height
- * of the container element.
- */
- fillHeight : function(el) {
- if (el) {
- var container = this.innerElement || this.element,
- containerEls = [this.header, this.body, this.footer],
- containerEl,
- total = 0,
- filled = 0,
- remaining = 0,
- validEl = false;
- for (var i = 0, l = containerEls.length; i < l; i++) {
- containerEl = containerEls[i];
- if (containerEl) {
- if (el !== containerEl) {
- filled += this._getPreciseHeight(containerEl);
- } else {
- validEl = true;
- }
- }
- }
- if (validEl) {
- if (UA.ie || UA.opera) {
- // Need to set height to 0, to allow height to be reduced
- Dom.setStyle(el, 'height', 0 + 'px');
- }
- total = this._getComputedHeight(container);
- // Fallback, if we can't get computed value for content height
- if (total === null) {
- Dom.addClass(container, "yui-override-padding");
- total = container.clientHeight; // Content, No Border, 0 Padding (set by yui-override-padding)
- Dom.removeClass(container, "yui-override-padding");
- }
-
- remaining = Math.max(total - filled, 0);
-
- Dom.setStyle(el, "height", remaining + "px");
-
- // Re-adjust height if required, to account for el padding and border
- if (el.offsetHeight != remaining) {
- remaining = Math.max(remaining - (el.offsetHeight - remaining), 0);
- }
- Dom.setStyle(el, "height", remaining + "px");
- }
- }
- },
- /**
- * Places the Overlay on top of all other instances of
- * YAHOO.widget.Overlay.
- * @method bringToTop
- */
- bringToTop: function () {
- var aOverlays = [],
- oElement = this.element;
- function compareZIndexDesc(p_oOverlay1, p_oOverlay2) {
- var sZIndex1 = Dom.getStyle(p_oOverlay1, "zIndex"),
- sZIndex2 = Dom.getStyle(p_oOverlay2, "zIndex"),
- nZIndex1 = (!sZIndex1 || isNaN(sZIndex1)) ? 0 : parseInt(sZIndex1, 10),
- nZIndex2 = (!sZIndex2 || isNaN(sZIndex2)) ? 0 : parseInt(sZIndex2, 10);
- if (nZIndex1 > nZIndex2) {
- return -1;
- } else if (nZIndex1 < nZIndex2) {
- return 1;
- } else {
- return 0;
- }
- }
- function isOverlayElement(p_oElement) {
- var isOverlay = Dom.hasClass(p_oElement, Overlay.CSS_OVERLAY),
- Panel = YAHOO.widget.Panel;
- if (isOverlay && !Dom.isAncestor(oElement, p_oElement)) {
- if (Panel && Dom.hasClass(p_oElement, Panel.CSS_PANEL)) {
- aOverlays[aOverlays.length] = p_oElement.parentNode;
- } else {
- aOverlays[aOverlays.length] = p_oElement;
- }
- }
- }
- Dom.getElementsBy(isOverlayElement, "DIV", document.body);
- aOverlays.sort(compareZIndexDesc);
- var oTopOverlay = aOverlays[0],
- nTopZIndex;
- if (oTopOverlay) {
- nTopZIndex = Dom.getStyle(oTopOverlay, "zIndex");
- if (!isNaN(nTopZIndex)) {
- var bRequiresBump = false;
- if (oTopOverlay != oElement) {
- bRequiresBump = true;
- } else if (aOverlays.length > 1) {
- var nNextZIndex = Dom.getStyle(aOverlays[1], "zIndex");
- // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
- if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
- bRequiresBump = true;
- }
- }
- if (bRequiresBump) {
- this.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
- }
- }
- }
- },
- /**
- * Removes the Overlay element from the DOM and sets all child
- * elements to null.
- * @method destroy
- */
- destroy: function () {
- if (this.iframe) {
- this.iframe.parentNode.removeChild(this.iframe);
- }
- this.iframe = null;
- Overlay.windowResizeEvent.unsubscribe(
- this.doCenterOnDOMEvent, this);
-
- Overlay.windowScrollEvent.unsubscribe(
- this.doCenterOnDOMEvent, this);
- Module.textResizeEvent.unsubscribe(this._autoFillOnHeightChange);
- if (this._contextTriggers) {
- // Unsubscribe context triggers - to cover context triggers which listen for global
- // events such as windowResize and windowScroll. Easier just to unsubscribe all
- this._processTriggers(this._contextTriggers, _UNSUBSCRIBE, this._alignOnTrigger);
- }
- Overlay.superclass.destroy.call(this);
- },
- /**
- * Can be used to force the container to repaint/redraw it's contents.
- * <p>
- * By default applies and then removes a 1px bottom margin through the
- * application/removal of a "yui-force-redraw" class.
- * </p>
- * <p>
- * It is currently used by Overlay to force a repaint for webkit
- * browsers, when centering.
- * </p>
- * @method forceContainerRedraw
- */
- forceContainerRedraw : function() {
- var c = this;
- Dom.addClass(c.element, "yui-force-redraw");
- setTimeout(function() {
- Dom.removeClass(c.element, "yui-force-redraw");
- }, 0);
- },
- /**
- * Returns a String representation of the object.
- * @method toString
- * @return {String} The string representation of the Overlay.
- */
- toString: function () {
- return "Overlay " + this.id;
- }
- });
- }());
- (function () {
- /**
- * OverlayManager is used for maintaining the focus status of
- * multiple Overlays.
- * @namespace YAHOO.widget
- * @namespace YAHOO.widget
- * @class OverlayManager
- * @constructor
- * @param {Array} overlays Optional. A collection of Overlays to register
- * with the manager.
- * @param {Object} userConfig The object literal representing the user
- * configuration of the OverlayManager
- */
- YAHOO.widget.OverlayManager = function (userConfig) {
- this.init(userConfig);
- };
- var Overlay = YAHOO.widget.Overlay,
- Event = YAHOO.util.Event,
- Dom = YAHOO.util.Dom,
- Config = YAHOO.util.Config,
- CustomEvent = YAHOO.util.CustomEvent,
- OverlayManager = YAHOO.widget.OverlayManager;
- /**
- * The CSS class representing a focused Overlay
- * @property OverlayManager.CSS_FOCUSED
- * @static
- * @final
- * @type String
- */
- OverlayManager.CSS_FOCUSED = "focused";
- OverlayManager.prototype = {
- /**
- * The class's constructor function
- * @property contructor
- * @type Function
- */
- constructor: OverlayManager,
- /**
- * The array of Overlays that are currently registered
- * @property overlays
- * @type YAHOO.widget.Overlay[]
- */
- overlays: null,
- /**
- * Initializes the default configuration of the OverlayManager
- * @method initDefaultConfig
- */
- initDefaultConfig: function () {
- /**
- * The collection of registered Overlays in use by
- * the OverlayManager
- * @config overlays
- * @type YAHOO.widget.Overlay[]
- * @default null
- */
- this.cfg.addProperty("overlays", { suppressEvent: true } );
- /**
- * The default DOM event that should be used to focus an Overlay
- * @config focusevent
- * @type String
- * @default "mousedown"
- */
- this.cfg.addProperty("focusevent", { value: "mousedown" } );
- },
- /**
- * Initializes the OverlayManager
- * @method init
- * @param {Overlay[]} overlays Optional. A collection of Overlays to
- * register with the manager.
- * @param {Object} userConfig The object literal representing the user
- * configuration of the OverlayManager
- */
- init: function (userConfig) {
- /**
- * The OverlayManager's Config object used for monitoring
- * configuration properties.
- * @property cfg
- * @type Config
- */
- this.cfg = new Config(this);
- this.initDefaultConfig();
- if (userConfig) {
- this.cfg.applyConfig(userConfig, true);
- }
- this.cfg.fireQueue();
- /**
- * The currently activated Overlay
- * @property activeOverlay
- * @private
- * @type YAHOO.widget.Overlay
- */
- var activeOverlay = null;
- /**
- * Returns the currently focused Overlay
- * @method getActive
- * @return {Overlay} The currently focused Overlay
- */
- this.getActive = function () {
- return activeOverlay;
- };
- /**
- * Focuses the specified Overlay
- * @method focus
- * @param {Overlay} overlay The Overlay to focus
- * @param {String} overlay The id of the Overlay to focus
- */
- this.focus = function (overlay) {
- var o = this.find(overlay);
- if (o) {
- o.focus();
- }
- };
- /**
- * Removes the specified Overlay from the manager
- * @method remove
- * @param {Overlay} overlay The Overlay to remove
- * @param {String} overlay The id of the Overlay to remove
- */
- this.remove = function (overlay) {
- var o = this.find(overlay),
- originalZ;
- if (o) {
- if (activeOverlay == o) {
- activeOverlay = null;
- }
- var bDestroyed = (o.element === null && o.cfg === null) ? true : false;
- if (!bDestroyed) {
- // Set it's zindex so that it's sorted to the end.
- originalZ = Dom.getStyle(o.element, "zIndex");
- o.cfg.setProperty("zIndex", -1000, true);
- }
- this.overlays.sort(this.compareZIndexDesc);
- this.overlays = this.overlays.slice(0, (this.overlays.length - 1));
- o.hideEvent.unsubscribe(o.blur);
- o.destroyEvent.unsubscribe(this._onOverlayDestroy, o);
- o.focusEvent.unsubscribe(this._onOverlayFocusHandler, o);
- o.blurEvent.unsubscribe(this._onOverlayBlurHandler, o);
- if (!bDestroyed) {
- Event.removeListener(o.element, this.cfg.getProperty("focusevent"), this._onOverlayElementFocus);
- o.cfg.setProperty("zIndex", originalZ, true);
- o.cfg.setProperty("manager", null);
- }
- /* _managed Flag for custom or existing. Don't want to remove existing */
- if (o.focusEvent._managed) { o.focusEvent = null; }
- if (o.blurEvent._managed) { o.blurEvent = null; }
- if (o.focus._managed) { o.focus = null; }
- if (o.blur._managed) { o.blur = null; }
- }
- };
- /**
- * Removes focus from all registered Overlays in the manager
- * @method blurAll
- */
- this.blurAll = function () {
- var nOverlays = this.overlays.length,
- i;
- if (nOverlays > 0) {
- i = nOverlays - 1;
- do {
- this.overlays[i].blur();
- }
- while(i--);
- }
- };
- /**
- * Updates the state of the OverlayManager and overlay, as a result of the overlay
- * being blurred.
- *
- * @method _manageBlur
- * @param {Overlay} overlay The overlay instance which got blurred.
- * @protected
- */
- this._manageBlur = function (overlay) {
- var changed = false;
- if (activeOverlay == overlay) {
- Dom.removeClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
- activeOverlay = null;
- changed = true;
- }
- return changed;
- };
- /**
- * Updates the state of the OverlayManager and overlay, as a result of the overlay
- * receiving focus.
- *
- * @method _manageFocus
- * @param {Overlay} overlay The overlay instance which got focus.
- * @protected
- */
- this._manageFocus = function(overlay) {
- var changed = false;
- if (activeOverlay != overlay) {
- if (activeOverlay) {
- activeOverlay.blur();
- }
- activeOverlay = overlay;
- this.bringToTop(activeOverlay);
- Dom.addClass(activeOverlay.element, OverlayManager.CSS_FOCUSED);
- changed = true;
- }
- return changed;
- };
- var overlays = this.cfg.getProperty("overlays");
- if (! this.overlays) {
- this.overlays = [];
- }
- if (overlays) {
- this.register(overlays);
- this.overlays.sort(this.compareZIndexDesc);
- }
- },
- /**
- * @method _onOverlayElementFocus
- * @description Event handler for the DOM event that is used to focus
- * the Overlay instance as specified by the "focusevent"
- * configuration property.
- * @private
- * @param {Event} p_oEvent Object representing the DOM event
- * object passed back by the event utility (Event).
- */
- _onOverlayElementFocus: function (p_oEvent) {
- var oTarget = Event.getTarget(p_oEvent),
- oClose = this.close;
- if (oClose && (oTarget == oClose || Dom.isAncestor(oClose, oTarget))) {
- this.blur();
- } else {
- this.focus();
- }
- },
- /**
- * @method _onOverlayDestroy
- * @description "destroy" event handler for the Overlay.
- * @private
- * @param {String} p_sType String representing the name of the event
- * that was fired.
- * @param {Array} p_aArgs Array of arguments sent when the event
- * was fired.
- * @param {Overlay} p_oOverlay Object representing the overlay that
- * fired the event.
- */
- _onOverlayDestroy: function (p_sType, p_aArgs, p_oOverlay) {
- this.remove(p_oOverlay);
- },
- /**
- * @method _onOverlayFocusHandler
- *
- * @description focusEvent Handler, used to delegate to _manageFocus with the correct arguments.
- *
- * @private
- * @param {String} p_sType String representing the name of the event
- * that was fired.
- * @param {Array} p_aArgs Array of arguments sent when the event
- * was fired.
- * @param {Overlay} p_oOverlay Object representing the overlay that
- * fired the event.
- */
- _onOverlayFocusHandler: function(p_sType, p_aArgs, p_oOverlay) {
- this._manageFocus(p_oOverlay);
- },
- /**
- * @method _onOverlayBlurHandler
- * @description blurEvent Handler, used to delegate to _manageBlur with the correct arguments.
- *
- * @private
- * @param {String} p_sType String representing the name of the event
- * that was fired.
- * @param {Array} p_aArgs Array of arguments sent when the event
- * was fired.
- * @param {Overlay} p_oOverlay Object representing the overlay that
- * fired the event.
- */
- _onOverlayBlurHandler: function(p_sType, p_aArgs, p_oOverlay) {
- this._manageBlur(p_oOverlay);
- },
- /**
- * Subscribes to the Overlay based instance focusEvent, to allow the OverlayManager to
- * monitor focus state.
- *
- * If the instance already has a focusEvent (e.g. Menu), OverlayManager will subscribe
- * to the existing focusEvent, however if a focusEvent or focus method does not exist
- * on the instance, the _bindFocus method will add them, and the focus method will
- * update the OverlayManager's state directly.
- *
- * @method _bindFocus
- * @param {Overlay} overlay The overlay for which focus needs to be managed
- * @protected
- */
- _bindFocus : function(overlay) {
- var mgr = this;
- if (!overlay.focusEvent) {
- overlay.focusEvent = overlay.createEvent("focus");
- overlay.focusEvent.signature = CustomEvent.LIST;
- overlay.focusEvent._managed = true;
- } else {
- overlay.focusEvent.subscribe(mgr._onOverlayFocusHandler, overlay, mgr);
- }
- if (!overlay.focus) {
- Event.on(overlay.element, mgr.cfg.getProperty("focusevent"), mgr._onOverlayElementFocus, null, overlay);
- overlay.focus = function () {
- if (mgr._manageFocus(this)) {
- // For Panel/Dialog
- if (this.cfg.getProperty("visible") && this.focusFirst) {
- this.focusFirst();
- }
- this.focusEvent.fire();
- }
- };
- overlay.focus._managed = true;
- }
- },
- /**
- * Subscribes to the Overlay based instance's blurEvent to allow the OverlayManager to
- * monitor blur state.
- *
- * If the instance already has a blurEvent (e.g. Menu), OverlayManager will subscribe
- * to the existing blurEvent, however if a blurEvent or blur method does not exist
- * on the instance, the _bindBlur method will add them, and the blur method
- * update the OverlayManager's state directly.
- *
- * @method _bindBlur
- * @param {Overlay} overlay The overlay for which blur needs to be managed
- * @protected
- */
- _bindBlur : function(overlay) {
- var mgr = this;
- if (!overlay.blurEvent) {
- overlay.blurEvent = overlay.createEvent("blur");
- overlay.blurEvent.signature = CustomEvent.LIST;
- overlay.focusEvent._managed = true;
- } else {
- overlay.blurEvent.subscribe(mgr._onOverlayBlurHandler, overlay, mgr);
- }
- if (!overlay.blur) {
- overlay.blur = function () {
- if (mgr._manageBlur(this)) {
- this.blurEvent.fire();
- }
- };
- overlay.blur._managed = true;
- }
- overlay.hideEvent.subscribe(overlay.blur);
- },
- /**
- * Subscribes to the Overlay based instance's destroyEvent, to allow the Overlay
- * to be removed for the OverlayManager when destroyed.
- *
- * @method _bindDestroy
- * @param {Overlay} overlay The overlay instance being managed
- * @protected
- */
- _bindDestroy : function(overlay) {
- var mgr = this;
- overlay.destroyEvent.subscribe(mgr._onOverlayDestroy, overlay, mgr);
- },
- /**
- * Ensures the zIndex configuration property on the managed overlay based instance
- * is set to the computed zIndex value from the DOM (with "auto" translating to 0).
- *
- * @method _syncZIndex
- * @param {Overlay} overlay The overlay instance being managed
- * @protected
- */
- _syncZIndex : function(overlay) {
- var zIndex = Dom.getStyle(overlay.element, "zIndex");
- if (!isNaN(zIndex)) {
- overlay.cfg.setProperty("zIndex", parseInt(zIndex, 10));
- } else {
- overlay.cfg.setProperty("zIndex", 0);
- }
- },
- /**
- * Registers an Overlay or an array of Overlays with the manager. Upon
- * registration, the Overlay receives functions for focus and blur,
- * along with CustomEvents for each.
- *
- * @method register
- * @param {Overlay} overlay An Overlay to register with the manager.
- * @param {Overlay[]} overlay An array of Overlays to register with
- * the manager.
- * @return {boolean} true if any Overlays are registered.
- */
- register: function (overlay) {
- var registered = false,
- i,
- n;
- if (overlay instanceof Overlay) {
- overlay.cfg.addProperty("manager", { value: this } );
- this._bindFocus(overlay);
- this._bindBlur(overlay);
- this._bindDestroy(overlay);
- this._syncZIndex(overlay);
- this.overlays.push(overlay);
- this.bringToTop(overlay);
- registered = true;
- } else if (overlay instanceof Array) {
- for (i = 0, n = overlay.length; i < n; i++) {
- registered = this.register(overlay[i]) || registered;
- }
- }
- return registered;
- },
- /**
- * Places the specified Overlay instance on top of all other
- * Overlay instances.
- * @method bringToTop
- * @param {YAHOO.widget.Overlay} p_oOverlay Object representing an
- * Overlay instance.
- * @param {String} p_oOverlay String representing the id of an
- * Overlay instance.
- */
- bringToTop: function (p_oOverlay) {
- var oOverlay = this.find(p_oOverlay),
- nTopZIndex,
- oTopOverlay,
- aOverlays;
- if (oOverlay) {
- aOverlays = this.overlays;
- aOverlays.sort(this.compareZIndexDesc);
- oTopOverlay = aOverlays[0];
- if (oTopOverlay) {
- nTopZIndex = Dom.getStyle(oTopOverlay.element, "zIndex");
- if (!isNaN(nTopZIndex)) {
- var bRequiresBump = false;
- if (oTopOverlay !== oOverlay) {
- bRequiresBump = true;
- } else if (aOverlays.length > 1) {
- var nNextZIndex = Dom.getStyle(aOverlays[1].element, "zIndex");
- // Don't rely on DOM order to stack if 2 overlays are at the same zindex.
- if (!isNaN(nNextZIndex) && (nTopZIndex == nNextZIndex)) {
- bRequiresBump = true;
- }
- }
- if (bRequiresBump) {
- oOverlay.cfg.setProperty("zindex", (parseInt(nTopZIndex, 10) + 2));
- }
- }
- aOverlays.sort(this.compareZIndexDesc);
- }
- }
- },
- /**
- * Attempts to locate an Overlay by instance or ID.
- * @method find
- * @param {Overlay} overlay An Overlay to locate within the manager
- * @param {String} overlay An Overlay id to locate within the manager
- * @return {Overlay} The requested Overlay, if found, or null if it
- * cannot be located.
- */
- find: function (overlay) {
- var isInstance = overlay instanceof Overlay,
- overlays = this.overlays,
- n = overlays.length,
- found = null,
- o,
- i;
- if (isInstance || typeof overlay == "string") {
- for (i = n-1; i >= 0; i--) {
- o = overlays[i];
- if ((isInstance && (o === overlay)) || (o.id == overlay)) {
- found = o;
- break;
- }
- }
- }
- return found;
- },
- /**
- * Used for sorting the manager's Overlays by z-index.
- * @method compareZIndexDesc
- * @private
- * @return {Number} 0, 1, or -1, depending on where the Overlay should
- * fall in the stacking order.
- */
- compareZIndexDesc: function (o1, o2) {
- var zIndex1 = (o1.cfg) ? o1.cfg.getProperty("zIndex") : null, // Sort invalid (destroyed)
- zIndex2 = (o2.cfg) ? o2.cfg.getProperty("zIndex") : null; // objects at bottom.
- if (zIndex1 === null && zIndex2 === null) {
- return 0;
- } else if (zIndex1 === null){
- return 1;
- } else if (zIndex2 === null) {
- return -1;
- } else if (zIndex1 > zIndex2) {
- return -1;
- } else if (zIndex1 < zIndex2) {
- return 1;
- } else {
- return 0;
- }
- },
- /**
- * Shows all Overlays in the manager.
- * @method showAll
- */
- showAll: function () {
- var overlays = this.overlays,
- n = overlays.length,
- i;
- for (i = n - 1; i >= 0; i--) {
- overlays[i].show();
- }
- },
- /**
- * Hides all Overlays in the manager.
- * @method hideAll
- */
- hideAll: function () {
- var overlays = this.overlays,
- n = overlays.length,
- i;
- for (i = n - 1; i >= 0; i--) {
- overlays[i].hide();
- }
- },
- /**
- * Returns a string representation of the object.
- * @method toString
- * @return {String} The string representation of the OverlayManager
- */
- toString: function () {
- return "OverlayManager";
- }
- };
- }());
- (function () {
- /**
- * Tooltip is an implementation of Overlay that behaves like an OS tooltip,
- * displaying when the user mouses over a particular element, and
- * disappearing on mouse out.
- * @namespace YAHOO.widget
- * @class Tooltip
- * @extends YAHOO.widget.Overlay
- * @constructor
- * @param {String} el The element ID representing the Tooltip <em>OR</em>
- * @param {HTMLElement} el The element representing the Tooltip
- * @param {Object} userConfig The configuration object literal containing
- * the configuration that should be set for this Overlay. See configuration
- * documentation for more details.
- */
- YAHOO.widget.Tooltip = function (el, userConfig) {
- YAHOO.widget.Tooltip.superclass.constructor.call(this, el, userConfig);
- };
- var Lang = YAHOO.lang,
- Event = YAHOO.util.Event,
- CustomEvent = YAHOO.util.CustomEvent,
- Dom = YAHOO.util.Dom,
- Tooltip = YAHOO.widget.Tooltip,
- UA = YAHOO.env.ua,
- bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
- m_oShadowTemplate,
- /**
- * Constant representing the Tooltip's configuration properties
- * @property DEFAULT_CONFIG
- * @private
- * @final
- * @type Object
- */
- DEFAULT_CONFIG = {
- "PREVENT_OVERLAP": {
- key: "preventoverlap",
- value: true,
- validator: Lang.isBoolean,
- supercedes: ["x", "y", "xy"]
- },
- "SHOW_DELAY": {
- key: "showdelay",
- value: 200,
- validator: Lang.isNumber
- },
- "AUTO_DISMISS_DELAY": {
- key: "autodismissdelay",
- value: 5000,
- validator: Lang.isNumber
- },
- "HIDE_DELAY": {
- key: "hidedelay",
- value: 250,
- validator: Lang.isNumber
- },
- "TEXT": {
- key: "text",
- suppressEvent: true
- },
- "CONTAINER": {
- key: "container"
- },
- "DISABLED": {
- key: "disabled",
- value: false,
- suppressEvent: true
- },
- "XY_OFFSET": {
- key: "xyoffset",
- value: [0, 25],
- suppressEvent: true
- }
- },
- /**
- * Constant representing the name of the Tooltip's events
- * @property EVENT_TYPES
- * @private
- * @final
- * @type Object
- */
- EVENT_TYPES = {
- "CONTEXT_MOUSE_OVER": "contextMouseOver",
- "CONTEXT_MOUSE_OUT": "contextMouseOut",
- "CONTEXT_TRIGGER": "contextTrigger"
- };
- /**
- * Constant representing the Tooltip CSS class
- * @property YAHOO.widget.Tooltip.CSS_TOOLTIP
- * @static
- * @final
- * @type String
- */
- Tooltip.CSS_TOOLTIP = "yui-tt";
- function restoreOriginalWidth(sOriginalWidth, sForcedWidth) {
- var oConfig = this.cfg,
- sCurrentWidth = oConfig.getProperty("width");
- if (sCurrentWidth == sForcedWidth) {
- oConfig.setProperty("width", sOriginalWidth);
- }
- }
- /*
- changeContent event handler that sets a Tooltip instance's "width"
- configuration property to the value of its root HTML
- elements's offsetWidth if a specific width has not been set.
- */
- function setWidthToOffsetWidth(p_sType, p_aArgs) {
- if ("_originalWidth" in this) {
- restoreOriginalWidth.call(this, this._originalWidth, this._forcedWidth);
- }
- var oBody = document.body,
- oConfig = this.cfg,
- sOriginalWidth = oConfig.getProperty("width"),
- sNewWidth,
- oClone;
- if ((!sOriginalWidth || sOriginalWidth == "auto") &&
- (oConfig.getProperty("container") != oBody ||
- oConfig.getProperty("x") >= Dom.getViewportWidth() ||
- oConfig.getProperty("y") >= Dom.getViewportHeight())) {
- oClone = this.element.cloneNode(true);
- oClone.style.visibility = "hidden";
- oClone.style.top = "0px";
- oClone.style.left = "0px";
- oBody.appendChild(oClone);
- sNewWidth = (oClone.offsetWidth + "px");
- oBody.removeChild(oClone);
- oClone = null;
- oConfig.setProperty("width", sNewWidth);
- oConfig.refireEvent("xy");
- this._originalWidth = sOriginalWidth || "";
- this._forcedWidth = sNewWidth;
- }
- }
- // "onDOMReady" that renders the ToolTip
- function onDOMReady(p_sType, p_aArgs, p_oObject) {
- this.render(p_oObject);
- }
- // "init" event handler that automatically renders the Tooltip
- function onInit() {
- Event.onDOMReady(onDOMReady, this.cfg.getProperty("container"), this);
- }
- YAHOO.extend(Tooltip, YAHOO.widget.Overlay, {
- /**
- * The Tooltip initialization method. This method is automatically
- * called by the constructor. A Tooltip is automatically rendered by
- * the init method, and it also is set to be invisible by default,
- * and constrained to viewport by default as well.
- * @method init
- * @param {String} el The element ID representing the Tooltip <em>OR</em>
- * @param {HTMLElement} el The element representing the Tooltip
- * @param {Object} userConfig The configuration object literal
- * containing the configuration that should be set for this Tooltip.
- * See configuration documentation for more details.
- */
- init: function (el, userConfig) {
- Tooltip.superclass.init.call(this, el);
- this.beforeInitEvent.fire(Tooltip);
- Dom.addClass(this.element, Tooltip.CSS_TOOLTIP);
- if (userConfig) {
- this.cfg.applyConfig(userConfig, true);
- }
- this.cfg.queueProperty("visible", false);
- this.cfg.queueProperty("constraintoviewport", true);
- this.setBody("");
- this.subscribe("changeContent", setWidthToOffsetWidth);
- this.subscribe("init", onInit);
- this.subscribe("render", this.onRender);
- this.initEvent.fire(Tooltip);
- },
- /**
- * Initializes the custom events for Tooltip
- * @method initEvents
- */
- initEvents: function () {
- Tooltip.superclass.initEvents.call(this);
- var SIGNATURE = CustomEvent.LIST;
- /**
- * CustomEvent fired when user mouses over a context element. Returning false from
- * a subscriber to this event will prevent the tooltip from being displayed for
- * the current context element.
- *
- * @event contextMouseOverEvent
- * @param {HTMLElement} context The context element which the user just moused over
- * @param {DOMEvent} e The DOM event object, associated with the mouse over
- */
- this.contextMouseOverEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OVER);
- this.contextMouseOverEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired when the user mouses out of a context element.
- *
- * @event contextMouseOutEvent
- * @param {HTMLElement} context The context element which the user just moused out of
- * @param {DOMEvent} e The DOM event object, associated with the mouse out
- */
- this.contextMouseOutEvent = this.createEvent(EVENT_TYPES.CONTEXT_MOUSE_OUT);
- this.contextMouseOutEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired just before the tooltip is displayed for the current context.
- * <p>
- * You can subscribe to this event if you need to set up the text for the
- * tooltip based on the context element for which it is about to be displayed.
- * </p>
- * <p>This event differs from the beforeShow event in following respects:</p>
- * <ol>
- * <li>
- * When moving from one context element to another, if the tooltip is not
- * hidden (the <code>hidedelay</code> is not reached), the beforeShow and Show events will not
- * be fired when the tooltip is displayed for the new context since it is already visible.
- * However the contextTrigger event is always fired before displaying the tooltip for
- * a new context.
- * </li>
- * <li>
- * The trigger event provides access to the context element, allowing you to
- * set the text of the tooltip based on context element for which the tooltip is
- * triggered.
- * </li>
- * </ol>
- * <p>
- * It is not possible to prevent the tooltip from being displayed
- * using this event. You can use the contextMouseOverEvent if you need to prevent
- * the tooltip from being displayed.
- * </p>
- * @event contextTriggerEvent
- * @param {HTMLElement} context The context element for which the tooltip is triggered
- */
- this.contextTriggerEvent = this.createEvent(EVENT_TYPES.CONTEXT_TRIGGER);
- this.contextTriggerEvent.signature = SIGNATURE;
- },
- /**
- * Initializes the class's configurable properties which can be
- * changed using the Overlay's Config object (cfg).
- * @method initDefaultConfig
- */
- initDefaultConfig: function () {
- Tooltip.superclass.initDefaultConfig.call(this);
- /**
- * Specifies whether the Tooltip should be kept from overlapping
- * its context element.
- * @config preventoverlap
- * @type Boolean
- * @default true
- */
- this.cfg.addProperty(DEFAULT_CONFIG.PREVENT_OVERLAP.key, {
- value: DEFAULT_CONFIG.PREVENT_OVERLAP.value,
- validator: DEFAULT_CONFIG.PREVENT_OVERLAP.validator,
- supercedes: DEFAULT_CONFIG.PREVENT_OVERLAP.supercedes
- });
- /**
- * The number of milliseconds to wait before showing a Tooltip
- * on mouseover.
- * @config showdelay
- * @type Number
- * @default 200
- */
- this.cfg.addProperty(DEFAULT_CONFIG.SHOW_DELAY.key, {
- handler: this.configShowDelay,
- value: 200,
- validator: DEFAULT_CONFIG.SHOW_DELAY.validator
- });
- /**
- * The number of milliseconds to wait before automatically
- * dismissing a Tooltip after the mouse has been resting on the
- * context element.
- * @config autodismissdelay
- * @type Number
- * @default 5000
- */
- this.cfg.addProperty(DEFAULT_CONFIG.AUTO_DISMISS_DELAY.key, {
- handler: this.configAutoDismissDelay,
- value: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.value,
- validator: DEFAULT_CONFIG.AUTO_DISMISS_DELAY.validator
- });
- /**
- * The number of milliseconds to wait before hiding a Tooltip
- * after mouseout.
- * @config hidedelay
- * @type Number
- * @default 250
- */
- this.cfg.addProperty(DEFAULT_CONFIG.HIDE_DELAY.key, {
- handler: this.configHideDelay,
- value: DEFAULT_CONFIG.HIDE_DELAY.value,
- validator: DEFAULT_CONFIG.HIDE_DELAY.validator
- });
- /**
- * Specifies the Tooltip's text.
- * @config text
- * @type String
- * @default null
- */
- this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
- handler: this.configText,
- suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent
- });
- /**
- * Specifies the container element that the Tooltip's markup
- * should be rendered into.
- * @config container
- * @type HTMLElement/String
- * @default document.body
- */
- this.cfg.addProperty(DEFAULT_CONFIG.CONTAINER.key, {
- handler: this.configContainer,
- value: document.body
- });
- /**
- * Specifies whether or not the tooltip is disabled. Disabled tooltips
- * will not be displayed. If the tooltip is driven by the title attribute
- * of the context element, the title attribute will still be removed for
- * disabled tooltips, to prevent default tooltip behavior.
- *
- * @config disabled
- * @type Boolean
- * @default false
- */
- this.cfg.addProperty(DEFAULT_CONFIG.DISABLED.key, {
- handler: this.configContainer,
- value: DEFAULT_CONFIG.DISABLED.value,
- supressEvent: DEFAULT_CONFIG.DISABLED.suppressEvent
- });
- /**
- * Specifies the XY offset from the mouse position, where the tooltip should be displayed, specified
- * as a 2 element array (e.g. [10, 20]);
- *
- * @config xyoffset
- * @type Array
- * @default [0, 25]
- */
- this.cfg.addProperty(DEFAULT_CONFIG.XY_OFFSET.key, {
- value: DEFAULT_CONFIG.XY_OFFSET.value.concat(),
- supressEvent: DEFAULT_CONFIG.XY_OFFSET.suppressEvent
- });
- /**
- * Specifies the element or elements that the Tooltip should be
- * anchored to on mouseover.
- * @config context
- * @type HTMLElement[]/String[]
- * @default null
- */
- /**
- * String representing the width of the Tooltip. <em>Please note:
- * </em> As of version 2.3 if either no value or a value of "auto"
- * is specified, and the Toolip's "container" configuration property
- * is set to something other than <code>document.body</code> or
- * its "context" element resides outside the immediately visible
- * portion of the document, the width of the Tooltip will be
- * calculated based on the offsetWidth of its root HTML and set just
- * before it is made visible. The original value will be
- * restored when the Tooltip is hidden. This ensures the Tooltip is
- * rendered at a usable width. For more information see
- * YUILibrary bug #1685496 and YUILibrary
- * bug #1735423.
- * @config width
- * @type String
- * @default null
- */
-
- },
-
- // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
-
- /**
- * The default event handler fired when the "text" property is changed.
- * @method configText
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configText: function (type, args, obj) {
- var text = args[0];
- if (text) {
- this.setBody(text);
- }
- },
-
- /**
- * The default event handler fired when the "container" property
- * is changed.
- * @method configContainer
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For
- * configuration handlers, args[0] will equal the newly applied value
- * for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configContainer: function (type, args, obj) {
- var container = args[0];
- if (typeof container == 'string') {
- this.cfg.setProperty("container", document.getElementById(container), true);
- }
- },
-
- /**
- * @method _removeEventListeners
- * @description Removes all of the DOM event handlers from the HTML
- * element(s) that trigger the display of the tooltip.
- * @protected
- */
- _removeEventListeners: function () {
-
- var aElements = this._context,
- nElements,
- oElement,
- i;
- if (aElements) {
- nElements = aElements.length;
- if (nElements > 0) {
- i = nElements - 1;
- do {
- oElement = aElements[i];
- Event.removeListener(oElement, "mouseover", this.onContextMouseOver);
- Event.removeListener(oElement, "mousemove", this.onContextMouseMove);
- Event.removeListener(oElement, "mouseout", this.onContextMouseOut);
- }
- while (i--);
- }
- }
- },
-
- /**
- * The default event handler fired when the "context" property
- * is changed.
- * @method configContext
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configContext: function (type, args, obj) {
- var context = args[0],
- aElements,
- nElements,
- oElement,
- i;
- if (context) {
- // Normalize parameter into an array
- if (! (context instanceof Array)) {
- if (typeof context == "string") {
- this.cfg.setProperty("context", [document.getElementById(context)], true);
- } else { // Assuming this is an element
- this.cfg.setProperty("context", [context], true);
- }
- context = this.cfg.getProperty("context");
- }
- // Remove any existing mouseover/mouseout listeners
- this._removeEventListeners();
- // Add mouseover/mouseout listeners to context elements
- this._context = context;
- aElements = this._context;
- if (aElements) {
- nElements = aElements.length;
- if (nElements > 0) {
- i = nElements - 1;
- do {
- oElement = aElements[i];
- Event.on(oElement, "mouseover", this.onContextMouseOver, this);
- Event.on(oElement, "mousemove", this.onContextMouseMove, this);
- Event.on(oElement, "mouseout", this.onContextMouseOut, this);
- }
- while (i--);
- }
- }
- }
- },
- // END BUILT-IN PROPERTY EVENT HANDLERS //
- // BEGIN BUILT-IN DOM EVENT HANDLERS //
- /**
- * The default event handler fired when the user moves the mouse while
- * over the context element.
- * @method onContextMouseMove
- * @param {DOMEvent} e The current DOM event
- * @param {Object} obj The object argument
- */
- onContextMouseMove: function (e, obj) {
- obj.pageX = Event.getPageX(e);
- obj.pageY = Event.getPageY(e);
- },
- /**
- * The default event handler fired when the user mouses over the
- * context element.
- * @method onContextMouseOver
- * @param {DOMEvent} e The current DOM event
- * @param {Object} obj The object argument
- */
- onContextMouseOver: function (e, obj) {
- var context = this;
- if (context.title) {
- obj._tempTitle = context.title;
- context.title = "";
- }
- // Fire first, to honor disabled set in the listner
- if (obj.fireEvent("contextMouseOver", context, e) !== false
- && !obj.cfg.getProperty("disabled")) {
- // Stop the tooltip from being hidden (set on last mouseout)
- if (obj.hideProcId) {
- clearTimeout(obj.hideProcId);
- obj.hideProcId = null;
- }
- Event.on(context, "mousemove", obj.onContextMouseMove, obj);
- /**
- * The unique process ID associated with the thread responsible
- * for showing the Tooltip.
- * @type int
- */
- obj.showProcId = obj.doShow(e, context);
- }
- },
- /**
- * The default event handler fired when the user mouses out of
- * the context element.
- * @method onContextMouseOut
- * @param {DOMEvent} e The current DOM event
- * @param {Object} obj The object argument
- */
- onContextMouseOut: function (e, obj) {
- var el = this;
- if (obj._tempTitle) {
- el.title = obj._tempTitle;
- obj._tempTitle = null;
- }
- if (obj.showProcId) {
- clearTimeout(obj.showProcId);
- obj.showProcId = null;
- }
- if (obj.hideProcId) {
- clearTimeout(obj.hideProcId);
- obj.hideProcId = null;
- }
- obj.fireEvent("contextMouseOut", el, e);
- obj.hideProcId = setTimeout(function () {
- obj.hide();
- }, obj.cfg.getProperty("hidedelay"));
- },
- // END BUILT-IN DOM EVENT HANDLERS //
- /**
- * Processes the showing of the Tooltip by setting the timeout delay
- * and offset of the Tooltip.
- * @method doShow
- * @param {DOMEvent} e The current DOM event
- * @param {HTMLElement} context The current context element
- * @return {Number} The process ID of the timeout function associated
- * with doShow
- */
- doShow: function (e, context) {
- var offset = this.cfg.getProperty("xyoffset"),
- xOffset = offset[0],
- yOffset = offset[1],
- me = this;
- if (UA.opera && context.tagName &&
- context.tagName.toUpperCase() == "A") {
- yOffset += 12;
- }
- return setTimeout(function () {
- var txt = me.cfg.getProperty("text");
- // title does not over-ride text
- if (me._tempTitle && (txt === "" || YAHOO.lang.isUndefined(txt) || YAHOO.lang.isNull(txt))) {
- me.setBody(me._tempTitle);
- } else {
- me.cfg.refireEvent("text");
- }
- me.moveTo(me.pageX + xOffset, me.pageY + yOffset);
- if (me.cfg.getProperty("preventoverlap")) {
- me.preventOverlap(me.pageX, me.pageY);
- }
- Event.removeListener(context, "mousemove", me.onContextMouseMove);
- me.contextTriggerEvent.fire(context);
- me.show();
- me.hideProcId = me.doHide();
- }, this.cfg.getProperty("showdelay"));
- },
- /**
- * Sets the timeout for the auto-dismiss delay, which by default is 5
- * seconds, meaning that a tooltip will automatically dismiss itself
- * after 5 seconds of being displayed.
- * @method doHide
- */
- doHide: function () {
- var me = this;
- return setTimeout(function () {
- me.hide();
- }, this.cfg.getProperty("autodismissdelay"));
- },
- /**
- * Fired when the Tooltip is moved, this event handler is used to
- * prevent the Tooltip from overlapping with its context element.
- * @method preventOverlay
- * @param {Number} pageX The x coordinate position of the mouse pointer
- * @param {Number} pageY The y coordinate position of the mouse pointer
- */
- preventOverlap: function (pageX, pageY) {
-
- var height = this.element.offsetHeight,
- mousePoint = new YAHOO.util.Point(pageX, pageY),
- elementRegion = Dom.getRegion(this.element);
-
- elementRegion.top -= 5;
- elementRegion.left -= 5;
- elementRegion.right += 5;
- elementRegion.bottom += 5;
-
-
- if (elementRegion.contains(mousePoint)) {
- this.cfg.setProperty("y", (pageY - height - 5));
- }
- },
- /**
- * @method onRender
- * @description "render" event handler for the Tooltip.
- * @param {String} p_sType String representing the name of the event
- * that was fired.
- * @param {Array} p_aArgs Array of arguments sent when the event
- * was fired.
- */
- onRender: function (p_sType, p_aArgs) {
-
- function sizeShadow() {
-
- var oElement = this.element,
- oShadow = this.underlay;
-
- if (oShadow) {
- oShadow.style.width = (oElement.offsetWidth + 6) + "px";
- oShadow.style.height = (oElement.offsetHeight + 1) + "px";
- }
-
- }
- function addShadowVisibleClass() {
- Dom.addClass(this.underlay, "yui-tt-shadow-visible");
- if (UA.ie) {
- this.forceUnderlayRedraw();
- }
- }
- function removeShadowVisibleClass() {
- Dom.removeClass(this.underlay, "yui-tt-shadow-visible");
- }
- function createShadow() {
-
- var oShadow = this.underlay,
- oElement,
- Module,
- nIE,
- me;
-
- if (!oShadow) {
-
- oElement = this.element;
- Module = YAHOO.widget.Module;
- nIE = UA.ie;
- me = this;
- if (!m_oShadowTemplate) {
- m_oShadowTemplate = document.createElement("div");
- m_oShadowTemplate.className = "yui-tt-shadow";
- }
- oShadow = m_oShadowTemplate.cloneNode(false);
- oElement.appendChild(oShadow);
- this.underlay = oShadow;
- // Backward compatibility, even though it's probably
- // intended to be "private", it isn't marked as such in the api docs
- this._shadow = this.underlay;
- addShadowVisibleClass.call(this);
- this.subscribe("beforeShow", addShadowVisibleClass);
- this.subscribe("hide", removeShadowVisibleClass);
- if (bIEQuirks) {
- window.setTimeout(function () {
- sizeShadow.call(me);
- }, 0);
-
- this.cfg.subscribeToConfigEvent("width", sizeShadow);
- this.cfg.subscribeToConfigEvent("height", sizeShadow);
- this.subscribe("changeContent", sizeShadow);
- Module.textResizeEvent.subscribe(sizeShadow, this, true);
- this.subscribe("destroy", function () {
- Module.textResizeEvent.unsubscribe(sizeShadow, this);
- });
- }
- }
- }
- function onBeforeShow() {
- createShadow.call(this);
- this.unsubscribe("beforeShow", onBeforeShow);
- }
- if (this.cfg.getProperty("visible")) {
- createShadow.call(this);
- } else {
- this.subscribe("beforeShow", onBeforeShow);
- }
-
- },
- /**
- * Forces the underlay element to be repainted, through the application/removal
- * of a yui-force-redraw class to the underlay element.
- *
- * @method forceUnderlayRedraw
- */
- forceUnderlayRedraw : function() {
- var tt = this;
- Dom.addClass(tt.underlay, "yui-force-redraw");
- setTimeout(function() {Dom.removeClass(tt.underlay, "yui-force-redraw");}, 0);
- },
- /**
- * Removes the Tooltip element from the DOM and sets all child
- * elements to null.
- * @method destroy
- */
- destroy: function () {
-
- // Remove any existing mouseover/mouseout listeners
- this._removeEventListeners();
- Tooltip.superclass.destroy.call(this);
-
- },
-
- /**
- * Returns a string representation of the object.
- * @method toString
- * @return {String} The string representation of the Tooltip
- */
- toString: function () {
- return "Tooltip " + this.id;
- }
-
- });
- }());
- (function () {
- /**
- * Panel is an implementation of Overlay that behaves like an OS window,
- * with a draggable header and an optional close icon at the top right.
- * @namespace YAHOO.widget
- * @class Panel
- * @extends YAHOO.widget.Overlay
- * @constructor
- * @param {String} el The element ID representing the Panel <em>OR</em>
- * @param {HTMLElement} el The element representing the Panel
- * @param {Object} userConfig The configuration object literal containing
- * the configuration that should be set for this Panel. See configuration
- * documentation for more details.
- */
- YAHOO.widget.Panel = function (el, userConfig) {
- YAHOO.widget.Panel.superclass.constructor.call(this, el, userConfig);
- };
- var _currentModal = null;
- var Lang = YAHOO.lang,
- Util = YAHOO.util,
- Dom = Util.Dom,
- Event = Util.Event,
- CustomEvent = Util.CustomEvent,
- KeyListener = YAHOO.util.KeyListener,
- Config = Util.Config,
- Overlay = YAHOO.widget.Overlay,
- Panel = YAHOO.widget.Panel,
- UA = YAHOO.env.ua,
- bIEQuirks = (UA.ie && (UA.ie <= 6 || document.compatMode == "BackCompat")),
- m_oMaskTemplate,
- m_oUnderlayTemplate,
- m_oCloseIconTemplate,
- /**
- * Constant representing the name of the Panel's events
- * @property EVENT_TYPES
- * @private
- * @final
- * @type Object
- */
- EVENT_TYPES = {
- "SHOW_MASK": "showMask",
- "HIDE_MASK": "hideMask",
- "DRAG": "drag"
- },
- /**
- * Constant representing the Panel's configuration properties
- * @property DEFAULT_CONFIG
- * @private
- * @final
- * @type Object
- */
- DEFAULT_CONFIG = {
- "CLOSE": {
- key: "close",
- value: true,
- validator: Lang.isBoolean,
- supercedes: ["visible"]
- },
- "DRAGGABLE": {
- key: "draggable",
- value: (Util.DD ? true : false),
- validator: Lang.isBoolean,
- supercedes: ["visible"]
- },
- "DRAG_ONLY" : {
- key: "dragonly",
- value: false,
- validator: Lang.isBoolean,
- supercedes: ["draggable"]
- },
- "UNDERLAY": {
- key: "underlay",
- value: "shadow",
- supercedes: ["visible"]
- },
- "MODAL": {
- key: "modal",
- value: false,
- validator: Lang.isBoolean,
- supercedes: ["visible", "zindex"]
- },
- "KEY_LISTENERS": {
- key: "keylisteners",
- suppressEvent: true,
- supercedes: ["visible"]
- },
- "STRINGS" : {
- key: "strings",
- supercedes: ["close"],
- validator: Lang.isObject,
- value: {
- close: "Close"
- }
- }
- };
- /**
- * Constant representing the default CSS class used for a Panel
- * @property YAHOO.widget.Panel.CSS_PANEL
- * @static
- * @final
- * @type String
- */
- Panel.CSS_PANEL = "yui-panel";
-
- /**
- * Constant representing the default CSS class used for a Panel's
- * wrapping container
- * @property YAHOO.widget.Panel.CSS_PANEL_CONTAINER
- * @static
- * @final
- * @type String
- */
- Panel.CSS_PANEL_CONTAINER = "yui-panel-container";
- /**
- * Constant representing the default set of focusable elements
- * on the pagewhich Modal Panels will prevent access to, when
- * the modal mask is displayed
- *
- * @property YAHOO.widget.Panel.FOCUSABLE
- * @static
- * @type Array
- */
- Panel.FOCUSABLE = [
- "a",
- "button",
- "select",
- "textarea",
- "input",
- "iframe"
- ];
- // Private CustomEvent listeners
- /*
- "beforeRender" event handler that creates an empty header for a Panel
- instance if its "draggable" configuration property is set to "true"
- and no header has been created.
- */
- function createHeader(p_sType, p_aArgs) {
- if (!this.header && this.cfg.getProperty("draggable")) {
- this.setHeader(" ");
- }
- }
- /*
- "hide" event handler that sets a Panel instance's "width"
- configuration property back to its original value before
- "setWidthToOffsetWidth" was called.
- */
-
- function restoreOriginalWidth(p_sType, p_aArgs, p_oObject) {
- var sOriginalWidth = p_oObject[0],
- sNewWidth = p_oObject[1],
- oConfig = this.cfg,
- sCurrentWidth = oConfig.getProperty("width");
- if (sCurrentWidth == sNewWidth) {
- oConfig.setProperty("width", sOriginalWidth);
- }
- this.unsubscribe("hide", restoreOriginalWidth, p_oObject);
- }
- /*
- "beforeShow" event handler that sets a Panel instance's "width"
- configuration property to the value of its root HTML
- elements's offsetWidth
- */
- function setWidthToOffsetWidth(p_sType, p_aArgs) {
- var oConfig,
- sOriginalWidth,
- sNewWidth;
- if (bIEQuirks) {
- oConfig = this.cfg;
- sOriginalWidth = oConfig.getProperty("width");
-
- if (!sOriginalWidth || sOriginalWidth == "auto") {
-
- sNewWidth = (this.element.offsetWidth + "px");
-
- oConfig.setProperty("width", sNewWidth);
- this.subscribe("hide", restoreOriginalWidth,
- [(sOriginalWidth || ""), sNewWidth]);
-
- }
- }
- }
- YAHOO.extend(Panel, Overlay, {
- /**
- * The Overlay initialization method, which is executed for Overlay and
- * all of its subclasses. This method is automatically called by the
- * constructor, and sets up all DOM references for pre-existing markup,
- * and creates required markup if it is not already present.
- * @method init
- * @param {String} el The element ID representing the Overlay <em>OR</em>
- * @param {HTMLElement} el The element representing the Overlay
- * @param {Object} userConfig The configuration object literal
- * containing the configuration that should be set for this Overlay.
- * See configuration documentation for more details.
- */
- init: function (el, userConfig) {
- /*
- Note that we don't pass the user config in here yet because
- we only want it executed once, at the lowest subclass level
- */
- Panel.superclass.init.call(this, el/*, userConfig*/);
- this.beforeInitEvent.fire(Panel);
- Dom.addClass(this.element, Panel.CSS_PANEL);
- this.buildWrapper();
- if (userConfig) {
- this.cfg.applyConfig(userConfig, true);
- }
- this.subscribe("showMask", this._addFocusHandlers);
- this.subscribe("hideMask", this._removeFocusHandlers);
- this.subscribe("beforeRender", createHeader);
- this.subscribe("render", function() {
- this.setFirstLastFocusable();
- this.subscribe("changeContent", this.setFirstLastFocusable);
- });
- this.subscribe("show", this.focusFirst);
- this.initEvent.fire(Panel);
- },
- /**
- * @method _onElementFocus
- * @private
- *
- * "focus" event handler for a focuable element. Used to automatically
- * blur the element when it receives focus to ensure that a Panel
- * instance's modality is not compromised.
- *
- * @param {Event} e The DOM event object
- */
- _onElementFocus : function(e){
- if(_currentModal === this) {
- var target = Event.getTarget(e),
- doc = document.documentElement,
- insideDoc = (target !== doc && target !== window);
- // mask and documentElement checks added for IE, which focuses on the mask when it's clicked on, and focuses on
- // the documentElement, when the document scrollbars are clicked on
- if (insideDoc && target !== this.element && target !== this.mask && !Dom.isAncestor(this.element, target)) {
- try {
- if (this.firstElement) {
- this.firstElement.focus();
- } else {
- if (this._modalFocus) {
- this._modalFocus.focus();
- } else {
- this.innerElement.focus();
- }
- }
- } catch(err){
- // Just in case we fail to focus
- try {
- if (insideDoc && target !== document.body) {
- target.blur();
- }
- } catch(err2) { }
- }
- }
- }
- },
- /**
- * @method _addFocusHandlers
- * @protected
- *
- * "showMask" event handler that adds a "focus" event handler to all
- * focusable elements in the document to enforce a Panel instance's
- * modality from being compromised.
- *
- * @param p_sType {String} Custom event type
- * @param p_aArgs {Array} Custom event arguments
- */
- _addFocusHandlers: function(p_sType, p_aArgs) {
- if (!this.firstElement) {
- if (UA.webkit || UA.opera) {
- if (!this._modalFocus) {
- this._createHiddenFocusElement();
- }
- } else {
- this.innerElement.tabIndex = 0;
- }
- }
- this.setTabLoop(this.firstElement, this.lastElement);
- Event.onFocus(document.documentElement, this._onElementFocus, this, true);
- _currentModal = this;
- },
- /**
- * Creates a hidden focusable element, used to focus on,
- * to enforce modality for browsers in which focus cannot
- * be applied to the container box.
- *
- * @method _createHiddenFocusElement
- * @private
- */
- _createHiddenFocusElement : function() {
- var e = document.createElement("button");
- e.style.height = "1px";
- e.style.width = "1px";
- e.style.position = "absolute";
- e.style.left = "-10000em";
- e.style.opacity = 0;
- e.tabIndex = -1;
- this.innerElement.appendChild(e);
- this._modalFocus = e;
- },
- /**
- * @method _removeFocusHandlers
- * @protected
- *
- * "hideMask" event handler that removes all "focus" event handlers added
- * by the "addFocusEventHandlers" method.
- *
- * @param p_sType {String} Event type
- * @param p_aArgs {Array} Event Arguments
- */
- _removeFocusHandlers: function(p_sType, p_aArgs) {
- Event.removeFocusListener(document.documentElement, this._onElementFocus, this);
- if (_currentModal == this) {
- _currentModal = null;
- }
- },
- /**
- * Sets focus to the first element in the Panel.
- *
- * @method focusFirst
- */
- focusFirst: function (type, args, obj) {
- var el = this.firstElement;
- if (args && args[1]) {
- Event.stopEvent(args[1]);
- }
- if (el) {
- try {
- el.focus();
- } catch(err) {
- // Ignore
- }
- }
- },
- /**
- * Sets focus to the last element in the Panel.
- *
- * @method focusLast
- */
- focusLast: function (type, args, obj) {
- var el = this.lastElement;
- if (args && args[1]) {
- Event.stopEvent(args[1]);
- }
- if (el) {
- try {
- el.focus();
- } catch(err) {
- // Ignore
- }
- }
- },
- /**
- * Sets up a tab, shift-tab loop between the first and last elements
- * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
- * instance properties, which are reset everytime this method is invoked.
- *
- * @method setTabLoop
- * @param {HTMLElement} firstElement
- * @param {HTMLElement} lastElement
- *
- */
- setTabLoop : function(firstElement, lastElement) {
- var backTab = this.preventBackTab, tab = this.preventTabOut,
- showEvent = this.showEvent, hideEvent = this.hideEvent;
- if (backTab) {
- backTab.disable();
- showEvent.unsubscribe(backTab.enable, backTab);
- hideEvent.unsubscribe(backTab.disable, backTab);
- backTab = this.preventBackTab = null;
- }
- if (tab) {
- tab.disable();
- showEvent.unsubscribe(tab.enable, tab);
- hideEvent.unsubscribe(tab.disable,tab);
- tab = this.preventTabOut = null;
- }
- if (firstElement) {
- this.preventBackTab = new KeyListener(firstElement,
- {shift:true, keys:9},
- {fn:this.focusLast, scope:this, correctScope:true}
- );
- backTab = this.preventBackTab;
- showEvent.subscribe(backTab.enable, backTab, true);
- hideEvent.subscribe(backTab.disable,backTab, true);
- }
- if (lastElement) {
- this.preventTabOut = new KeyListener(lastElement,
- {shift:false, keys:9},
- {fn:this.focusFirst, scope:this, correctScope:true}
- );
- tab = this.preventTabOut;
- showEvent.subscribe(tab.enable, tab, true);
- hideEvent.subscribe(tab.disable,tab, true);
- }
- },
- /**
- * Returns an array of the currently focusable items which reside within
- * Panel. The set of focusable elements the method looks for are defined
- * in the Panel.FOCUSABLE static property
- *
- * @method getFocusableElements
- * @param {HTMLElement} root element to start from.
- */
- getFocusableElements : function(root) {
- root = root || this.innerElement;
- var focusable = {};
- for (var i = 0; i < Panel.FOCUSABLE.length; i++) {
- focusable[Panel.FOCUSABLE[i]] = true;
- }
- function isFocusable(el) {
- if (el.focus && el.type !== "hidden" && !el.disabled && focusable[el.tagName.toLowerCase()]) {
- return true;
- }
- return false;
- }
- // Not looking by Tag, since we want elements in DOM order
- return Dom.getElementsBy(isFocusable, null, root);
- },
- /**
- * Sets the firstElement and lastElement instance properties
- * to the first and last focusable elements in the Panel.
- *
- * @method setFirstLastFocusable
- */
- setFirstLastFocusable : function() {
- this.firstElement = null;
- this.lastElement = null;
- var elements = this.getFocusableElements();
- this.focusableElements = elements;
- if (elements.length > 0) {
- this.firstElement = elements[0];
- this.lastElement = elements[elements.length - 1];
- }
- if (this.cfg.getProperty("modal")) {
- this.setTabLoop(this.firstElement, this.lastElement);
- }
- },
- /**
- * Initializes the custom events for Module which are fired
- * automatically at appropriate times by the Module class.
- */
- initEvents: function () {
- Panel.superclass.initEvents.call(this);
- var SIGNATURE = CustomEvent.LIST;
- /**
- * CustomEvent fired after the modality mask is shown
- * @event showMaskEvent
- */
- this.showMaskEvent = this.createEvent(EVENT_TYPES.SHOW_MASK);
- this.showMaskEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired after the modality mask is hidden
- * @event hideMaskEvent
- */
- this.hideMaskEvent = this.createEvent(EVENT_TYPES.HIDE_MASK);
- this.hideMaskEvent.signature = SIGNATURE;
- /**
- * CustomEvent when the Panel is dragged
- * @event dragEvent
- */
- this.dragEvent = this.createEvent(EVENT_TYPES.DRAG);
- this.dragEvent.signature = SIGNATURE;
- },
- /**
- * Initializes the class's configurable properties which can be changed
- * using the Panel's Config object (cfg).
- * @method initDefaultConfig
- */
- initDefaultConfig: function () {
- Panel.superclass.initDefaultConfig.call(this);
- // Add panel config properties //
- /**
- * True if the Panel should display a "close" button
- * @config close
- * @type Boolean
- * @default true
- */
- this.cfg.addProperty(DEFAULT_CONFIG.CLOSE.key, {
- handler: this.configClose,
- value: DEFAULT_CONFIG.CLOSE.value,
- validator: DEFAULT_CONFIG.CLOSE.validator,
- supercedes: DEFAULT_CONFIG.CLOSE.supercedes
- });
- /**
- * Boolean specifying if the Panel should be draggable. The default
- * value is "true" if the Drag and Drop utility is included,
- * otherwise it is "false." <strong>PLEASE NOTE:</strong> There is a
- * known issue in IE 6 (Strict Mode and Quirks Mode) and IE 7
- * (Quirks Mode) where Panels that either don't have a value set for
- * their "width" configuration property, or their "width"
- * configuration property is set to "auto" will only be draggable by
- * placing the mouse on the text of the Panel's header element.
- * To fix this bug, draggable Panels missing a value for their
- * "width" configuration property, or whose "width" configuration
- * property is set to "auto" will have it set to the value of
- * their root HTML element's offsetWidth before they are made
- * visible. The calculated width is then removed when the Panel is
- * hidden. <em>This fix is only applied to draggable Panels in IE 6
- * (Strict Mode and Quirks Mode) and IE 7 (Quirks Mode)</em>. For
- * more information on this issue see:
- * YUILibrary bugs #1726972 and #1589210.
- * @config draggable
- * @type Boolean
- * @default true
- */
- this.cfg.addProperty(DEFAULT_CONFIG.DRAGGABLE.key, {
- handler: this.configDraggable,
- value: (Util.DD) ? true : false,
- validator: DEFAULT_CONFIG.DRAGGABLE.validator,
- supercedes: DEFAULT_CONFIG.DRAGGABLE.supercedes
- });
- /**
- * Boolean specifying if the draggable Panel should be drag only, not interacting with drop
- * targets on the page.
- * <p>
- * When set to true, draggable Panels will not check to see if they are over drop targets,
- * or fire the DragDrop events required to support drop target interaction (onDragEnter,
- * onDragOver, onDragOut, onDragDrop etc.).
- * If the Panel is not designed to be dropped on any target elements on the page, then this
- * flag can be set to true to improve performance.
- * </p>
- * <p>
- * When set to false, all drop target related events will be fired.
- * </p>
- * <p>
- * The property is set to false by default to maintain backwards compatibility but should be
- * set to true if drop target interaction is not required for the Panel, to improve performance.</p>
- *
- * @config dragOnly
- * @type Boolean
- * @default false
- */
- this.cfg.addProperty(DEFAULT_CONFIG.DRAG_ONLY.key, {
- value: DEFAULT_CONFIG.DRAG_ONLY.value,
- validator: DEFAULT_CONFIG.DRAG_ONLY.validator,
- supercedes: DEFAULT_CONFIG.DRAG_ONLY.supercedes
- });
- /**
- * Sets the type of underlay to display for the Panel. Valid values
- * are "shadow," "matte," and "none". <strong>PLEASE NOTE:</strong>
- * The creation of the underlay element is deferred until the Panel
- * is initially made visible. For Gecko-based browsers on Mac
- * OS X the underlay elment is always created as it is used as a
- * shim to prevent Aqua scrollbars below a Panel instance from poking
- * through it (See YUILibrary bug #1723530).
- * @config underlay
- * @type String
- * @default shadow
- */
- this.cfg.addProperty(DEFAULT_CONFIG.UNDERLAY.key, {
- handler: this.configUnderlay,
- value: DEFAULT_CONFIG.UNDERLAY.value,
- supercedes: DEFAULT_CONFIG.UNDERLAY.supercedes
- });
-
- /**
- * True if the Panel should be displayed in a modal fashion,
- * automatically creating a transparent mask over the document that
- * will not be removed until the Panel is dismissed.
- * @config modal
- * @type Boolean
- * @default false
- */
- this.cfg.addProperty(DEFAULT_CONFIG.MODAL.key, {
- handler: this.configModal,
- value: DEFAULT_CONFIG.MODAL.value,
- validator: DEFAULT_CONFIG.MODAL.validator,
- supercedes: DEFAULT_CONFIG.MODAL.supercedes
- });
- /**
- * A KeyListener (or array of KeyListeners) that will be enabled
- * when the Panel is shown, and disabled when the Panel is hidden.
- * @config keylisteners
- * @type YAHOO.util.KeyListener[]
- * @default null
- */
- this.cfg.addProperty(DEFAULT_CONFIG.KEY_LISTENERS.key, {
- handler: this.configKeyListeners,
- suppressEvent: DEFAULT_CONFIG.KEY_LISTENERS.suppressEvent,
- supercedes: DEFAULT_CONFIG.KEY_LISTENERS.supercedes
- });
- /**
- * UI Strings used by the Panel
- *
- * @config strings
- * @type Object
- * @default An object literal with the properties shown below:
- * <dl>
- * <dt>close</dt><dd><em>String</em> : The string to use for the close icon. Defaults to "Close".</dd>
- * </dl>
- */
- this.cfg.addProperty(DEFAULT_CONFIG.STRINGS.key, {
- value:DEFAULT_CONFIG.STRINGS.value,
- handler:this.configStrings,
- validator:DEFAULT_CONFIG.STRINGS.validator,
- supercedes:DEFAULT_CONFIG.STRINGS.supercedes
- });
- },
- // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
-
- /**
- * The default event handler fired when the "close" property is changed.
- * The method controls the appending or hiding of the close icon at the
- * top right of the Panel.
- * @method configClose
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configClose: function (type, args, obj) {
- var val = args[0],
- oClose = this.close,
- strings = this.cfg.getProperty("strings");
- if (val) {
- if (!oClose) {
- if (!m_oCloseIconTemplate) {
- m_oCloseIconTemplate = document.createElement("a");
- m_oCloseIconTemplate.className = "container-close";
- m_oCloseIconTemplate.href = "#";
- }
- oClose = m_oCloseIconTemplate.cloneNode(true);
- this.innerElement.appendChild(oClose);
- oClose.innerHTML = (strings && strings.close) ? strings.close : " ";
- Event.on(oClose, "click", this._doClose, this, true);
- this.close = oClose;
- } else {
- oClose.style.display = "block";
- }
- } else {
- if (oClose) {
- oClose.style.display = "none";
- }
- }
- },
- /**
- * Event handler for the close icon
- *
- * @method _doClose
- * @protected
- *
- * @param {DOMEvent} e
- */
- _doClose : function (e) {
- Event.preventDefault(e);
- this.hide();
- },
- /**
- * The default event handler fired when the "draggable" property
- * is changed.
- * @method configDraggable
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configDraggable: function (type, args, obj) {
- var val = args[0];
- if (val) {
- if (!Util.DD) {
- this.cfg.setProperty("draggable", false);
- return;
- }
- if (this.header) {
- Dom.setStyle(this.header, "cursor", "move");
- this.registerDragDrop();
- }
- this.subscribe("beforeShow", setWidthToOffsetWidth);
- } else {
- if (this.dd) {
- this.dd.unreg();
- }
- if (this.header) {
- Dom.setStyle(this.header,"cursor","auto");
- }
- this.unsubscribe("beforeShow", setWidthToOffsetWidth);
- }
- },
-
- /**
- * The default event handler fired when the "underlay" property
- * is changed.
- * @method configUnderlay
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configUnderlay: function (type, args, obj) {
- var bMacGecko = (this.platform == "mac" && UA.gecko),
- sUnderlay = args[0].toLowerCase(),
- oUnderlay = this.underlay,
- oElement = this.element;
- function createUnderlay() {
- var bNew = false;
- if (!oUnderlay) { // create if not already in DOM
- if (!m_oUnderlayTemplate) {
- m_oUnderlayTemplate = document.createElement("div");
- m_oUnderlayTemplate.className = "underlay";
- }
- oUnderlay = m_oUnderlayTemplate.cloneNode(false);
- this.element.appendChild(oUnderlay);
- this.underlay = oUnderlay;
- if (bIEQuirks) {
- this.sizeUnderlay();
- this.cfg.subscribeToConfigEvent("width", this.sizeUnderlay);
- this.cfg.subscribeToConfigEvent("height", this.sizeUnderlay);
- this.changeContentEvent.subscribe(this.sizeUnderlay);
- YAHOO.widget.Module.textResizeEvent.subscribe(this.sizeUnderlay, this, true);
- }
- if (UA.webkit && UA.webkit < 420) {
- this.changeContentEvent.subscribe(this.forceUnderlayRedraw);
- }
- bNew = true;
- }
- }
- function onBeforeShow() {
- var bNew = createUnderlay.call(this);
- if (!bNew && bIEQuirks) {
- this.sizeUnderlay();
- }
- this._underlayDeferred = false;
- this.beforeShowEvent.unsubscribe(onBeforeShow);
- }
- function destroyUnderlay() {
- if (this._underlayDeferred) {
- this.beforeShowEvent.unsubscribe(onBeforeShow);
- this._underlayDeferred = false;
- }
- if (oUnderlay) {
- this.cfg.unsubscribeFromConfigEvent("width", this.sizeUnderlay);
- this.cfg.unsubscribeFromConfigEvent("height",this.sizeUnderlay);
- this.changeContentEvent.unsubscribe(this.sizeUnderlay);
- this.changeContentEvent.unsubscribe(this.forceUnderlayRedraw);
- YAHOO.widget.Module.textResizeEvent.unsubscribe(this.sizeUnderlay, this, true);
- this.element.removeChild(oUnderlay);
- this.underlay = null;
- }
- }
- switch (sUnderlay) {
- case "shadow":
- Dom.removeClass(oElement, "matte");
- Dom.addClass(oElement, "shadow");
- break;
- case "matte":
- if (!bMacGecko) {
- destroyUnderlay.call(this);
- }
- Dom.removeClass(oElement, "shadow");
- Dom.addClass(oElement, "matte");
- break;
- default:
- if (!bMacGecko) {
- destroyUnderlay.call(this);
- }
- Dom.removeClass(oElement, "shadow");
- Dom.removeClass(oElement, "matte");
- break;
- }
- if ((sUnderlay == "shadow") || (bMacGecko && !oUnderlay)) {
- if (this.cfg.getProperty("visible")) {
- var bNew = createUnderlay.call(this);
- if (!bNew && bIEQuirks) {
- this.sizeUnderlay();
- }
- } else {
- if (!this._underlayDeferred) {
- this.beforeShowEvent.subscribe(onBeforeShow);
- this._underlayDeferred = true;
- }
- }
- }
- },
-
- /**
- * The default event handler fired when the "modal" property is
- * changed. This handler subscribes or unsubscribes to the show and hide
- * events to handle the display or hide of the modality mask.
- * @method configModal
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configModal: function (type, args, obj) {
- var modal = args[0];
- if (modal) {
- if (!this._hasModalityEventListeners) {
- this.subscribe("beforeShow", this.buildMask);
- this.subscribe("beforeShow", this.bringToTop);
- this.subscribe("beforeShow", this.showMask);
- this.subscribe("hide", this.hideMask);
- Overlay.windowResizeEvent.subscribe(this.sizeMask,
- this, true);
- this._hasModalityEventListeners = true;
- }
- } else {
- if (this._hasModalityEventListeners) {
- if (this.cfg.getProperty("visible")) {
- this.hideMask();
- this.removeMask();
- }
- this.unsubscribe("beforeShow", this.buildMask);
- this.unsubscribe("beforeShow", this.bringToTop);
- this.unsubscribe("beforeShow", this.showMask);
- this.unsubscribe("hide", this.hideMask);
- Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
- this._hasModalityEventListeners = false;
- }
- }
- },
- /**
- * Removes the modality mask.
- * @method removeMask
- */
- removeMask: function () {
- var oMask = this.mask,
- oParentNode;
- if (oMask) {
- /*
- Hide the mask before destroying it to ensure that DOM
- event handlers on focusable elements get removed.
- */
- this.hideMask();
- oParentNode = oMask.parentNode;
- if (oParentNode) {
- oParentNode.removeChild(oMask);
- }
- this.mask = null;
- }
- },
-
- /**
- * The default event handler fired when the "keylisteners" property
- * is changed.
- * @method configKeyListeners
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configKeyListeners: function (type, args, obj) {
- var listeners = args[0],
- listener,
- nListeners,
- i;
-
- if (listeners) {
- if (listeners instanceof Array) {
- nListeners = listeners.length;
- for (i = 0; i < nListeners; i++) {
- listener = listeners[i];
-
- if (!Config.alreadySubscribed(this.showEvent,
- listener.enable, listener)) {
- this.showEvent.subscribe(listener.enable,
- listener, true);
- }
- if (!Config.alreadySubscribed(this.hideEvent,
- listener.disable, listener)) {
- this.hideEvent.subscribe(listener.disable,
- listener, true);
- this.destroyEvent.subscribe(listener.disable,
- listener, true);
- }
- }
- } else {
- if (!Config.alreadySubscribed(this.showEvent,
- listeners.enable, listeners)) {
- this.showEvent.subscribe(listeners.enable,
- listeners, true);
- }
- if (!Config.alreadySubscribed(this.hideEvent,
- listeners.disable, listeners)) {
- this.hideEvent.subscribe(listeners.disable,
- listeners, true);
- this.destroyEvent.subscribe(listeners.disable,
- listeners, true);
- }
- }
- }
- },
- /**
- * The default handler for the "strings" property
- * @method configStrings
- */
- configStrings : function(type, args, obj) {
- var val = Lang.merge(DEFAULT_CONFIG.STRINGS.value, args[0]);
- this.cfg.setProperty(DEFAULT_CONFIG.STRINGS.key, val, true);
- },
- /**
- * The default event handler fired when the "height" property is changed.
- * @method configHeight
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configHeight: function (type, args, obj) {
- var height = args[0],
- el = this.innerElement;
- Dom.setStyle(el, "height", height);
- this.cfg.refireEvent("iframe");
- },
- /**
- * The default custom event handler executed when the Panel's height is changed,
- * if the autofillheight property has been set.
- *
- * @method _autoFillOnHeightChange
- * @protected
- * @param {String} type The event type
- * @param {Array} args The array of arguments passed to event subscribers
- * @param {HTMLElement} el The header, body or footer element which is to be resized to fill
- * out the containers height
- */
- _autoFillOnHeightChange : function(type, args, el) {
- Panel.superclass._autoFillOnHeightChange.apply(this, arguments);
- if (bIEQuirks) {
- var panel = this;
- setTimeout(function() {
- panel.sizeUnderlay();
- },0);
- }
- },
- /**
- * The default event handler fired when the "width" property is changed.
- * @method configWidth
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configWidth: function (type, args, obj) {
-
- var width = args[0],
- el = this.innerElement;
-
- Dom.setStyle(el, "width", width);
- this.cfg.refireEvent("iframe");
-
- },
-
- /**
- * The default event handler fired when the "zIndex" property is changed.
- * @method configzIndex
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configzIndex: function (type, args, obj) {
- Panel.superclass.configzIndex.call(this, type, args, obj);
- if (this.mask || this.cfg.getProperty("modal") === true) {
- var panelZ = Dom.getStyle(this.element, "zIndex");
- if (!panelZ || isNaN(panelZ)) {
- panelZ = 0;
- }
- if (panelZ === 0) {
- // Recursive call to configzindex (which should be stopped
- // from going further because panelZ should no longer === 0)
- this.cfg.setProperty("zIndex", 1);
- } else {
- this.stackMask();
- }
- }
- },
- // END BUILT-IN PROPERTY EVENT HANDLERS //
- /**
- * Builds the wrapping container around the Panel that is used for
- * positioning the shadow and matte underlays. The container element is
- * assigned to a local instance variable called container, and the
- * element is reinserted inside of it.
- * @method buildWrapper
- */
- buildWrapper: function () {
- var elementParent = this.element.parentNode,
- originalElement = this.element,
- wrapper = document.createElement("div");
- wrapper.className = Panel.CSS_PANEL_CONTAINER;
- wrapper.id = originalElement.id + "_c";
- if (elementParent) {
- elementParent.insertBefore(wrapper, originalElement);
- }
- wrapper.appendChild(originalElement);
- this.element = wrapper;
- this.innerElement = originalElement;
- Dom.setStyle(this.innerElement, "visibility", "inherit");
- },
- /**
- * Adjusts the size of the shadow based on the size of the element.
- * @method sizeUnderlay
- */
- sizeUnderlay: function () {
- var oUnderlay = this.underlay,
- oElement;
- if (oUnderlay) {
- oElement = this.element;
- oUnderlay.style.width = oElement.offsetWidth + "px";
- oUnderlay.style.height = oElement.offsetHeight + "px";
- }
- },
- /**
- * Registers the Panel's header for drag & drop capability.
- * @method registerDragDrop
- */
- registerDragDrop: function () {
- var me = this;
- if (this.header) {
- if (!Util.DD) {
- return;
- }
- var bDragOnly = (this.cfg.getProperty("dragonly") === true);
- /**
- * The YAHOO.util.DD instance, used to implement the draggable header for the panel if draggable is enabled
- *
- * @property dd
- * @type YAHOO.util.DD
- */
- this.dd = new Util.DD(this.element.id, this.id, {dragOnly: bDragOnly});
- if (!this.header.id) {
- this.header.id = this.id + "_h";
- }
- this.dd.startDrag = function () {
- var offsetHeight,
- offsetWidth,
- viewPortWidth,
- viewPortHeight,
- scrollX,
- scrollY;
- if (YAHOO.env.ua.ie == 6) {
- Dom.addClass(me.element,"drag");
- }
- if (me.cfg.getProperty("constraintoviewport")) {
- var nViewportOffset = Overlay.VIEWPORT_OFFSET;
- offsetHeight = me.element.offsetHeight;
- offsetWidth = me.element.offsetWidth;
- viewPortWidth = Dom.getViewportWidth();
- viewPortHeight = Dom.getViewportHeight();
- scrollX = Dom.getDocumentScrollLeft();
- scrollY = Dom.getDocumentScrollTop();
- if (offsetHeight + nViewportOffset < viewPortHeight) {
- this.minY = scrollY + nViewportOffset;
- this.maxY = scrollY + viewPortHeight - offsetHeight - nViewportOffset;
- } else {
- this.minY = scrollY + nViewportOffset;
- this.maxY = scrollY + nViewportOffset;
- }
- if (offsetWidth + nViewportOffset < viewPortWidth) {
- this.minX = scrollX + nViewportOffset;
- this.maxX = scrollX + viewPortWidth - offsetWidth - nViewportOffset;
- } else {
- this.minX = scrollX + nViewportOffset;
- this.maxX = scrollX + nViewportOffset;
- }
- this.constrainX = true;
- this.constrainY = true;
- } else {
- this.constrainX = false;
- this.constrainY = false;
- }
- me.dragEvent.fire("startDrag", arguments);
- };
- this.dd.onDrag = function () {
- me.syncPosition();
- me.cfg.refireEvent("iframe");
- if (this.platform == "mac" && YAHOO.env.ua.gecko) {
- this.showMacGeckoScrollbars();
- }
- me.dragEvent.fire("onDrag", arguments);
- };
- this.dd.endDrag = function () {
- if (YAHOO.env.ua.ie == 6) {
- Dom.removeClass(me.element,"drag");
- }
- me.dragEvent.fire("endDrag", arguments);
- me.moveEvent.fire(me.cfg.getProperty("xy"));
- };
- this.dd.setHandleElId(this.header.id);
- this.dd.addInvalidHandleType("INPUT");
- this.dd.addInvalidHandleType("SELECT");
- this.dd.addInvalidHandleType("TEXTAREA");
- }
- },
-
- /**
- * Builds the mask that is laid over the document when the Panel is
- * configured to be modal.
- * @method buildMask
- */
- buildMask: function () {
- var oMask = this.mask;
- if (!oMask) {
- if (!m_oMaskTemplate) {
- m_oMaskTemplate = document.createElement("div");
- m_oMaskTemplate.className = "mask";
- m_oMaskTemplate.innerHTML = " ";
- }
- oMask = m_oMaskTemplate.cloneNode(true);
- oMask.id = this.id + "_mask";
- document.body.insertBefore(oMask, document.body.firstChild);
- this.mask = oMask;
- if (YAHOO.env.ua.gecko && this.platform == "mac") {
- Dom.addClass(this.mask, "block-scrollbars");
- }
- // Stack mask based on the element zindex
- this.stackMask();
- }
- },
- /**
- * Hides the modality mask.
- * @method hideMask
- */
- hideMask: function () {
- if (this.cfg.getProperty("modal") && this.mask) {
- this.mask.style.display = "none";
- Dom.removeClass(document.body, "masked");
- this.hideMaskEvent.fire();
- }
- },
- /**
- * Shows the modality mask.
- * @method showMask
- */
- showMask: function () {
- if (this.cfg.getProperty("modal") && this.mask) {
- Dom.addClass(document.body, "masked");
- this.sizeMask();
- this.mask.style.display = "block";
- this.showMaskEvent.fire();
- }
- },
- /**
- * Sets the size of the modality mask to cover the entire scrollable
- * area of the document
- * @method sizeMask
- */
- sizeMask: function () {
- if (this.mask) {
- // Shrink mask first, so it doesn't affect the document size.
- var mask = this.mask,
- viewWidth = Dom.getViewportWidth(),
- viewHeight = Dom.getViewportHeight();
- if (mask.offsetHeight > viewHeight) {
- mask.style.height = viewHeight + "px";
- }
- if (mask.offsetWidth > viewWidth) {
- mask.style.width = viewWidth + "px";
- }
- // Then size it to the document
- mask.style.height = Dom.getDocumentHeight() + "px";
- mask.style.width = Dom.getDocumentWidth() + "px";
- }
- },
- /**
- * Sets the zindex of the mask, if it exists, based on the zindex of
- * the Panel element. The zindex of the mask is set to be one less
- * than the Panel element's zindex.
- *
- * <p>NOTE: This method will not bump up the zindex of the Panel
- * to ensure that the mask has a non-negative zindex. If you require the
- * mask zindex to be 0 or higher, the zindex of the Panel
- * should be set to a value higher than 0, before this method is called.
- * </p>
- * @method stackMask
- */
- stackMask: function() {
- if (this.mask) {
- var panelZ = Dom.getStyle(this.element, "zIndex");
- if (!YAHOO.lang.isUndefined(panelZ) && !isNaN(panelZ)) {
- Dom.setStyle(this.mask, "zIndex", panelZ - 1);
- }
- }
- },
- /**
- * Renders the Panel by inserting the elements that are not already in
- * the main Panel into their correct places. Optionally appends the
- * Panel to the specified node prior to the render's execution. NOTE:
- * For Panels without existing markup, the appendToNode argument is
- * REQUIRED. If this argument is ommitted and the current element is
- * not present in the document, the function will return false,
- * indicating that the render was a failure.
- * @method render
- * @param {String} appendToNode The element id to which the Module
- * should be appended to prior to rendering <em>OR</em>
- * @param {HTMLElement} appendToNode The element to which the Module
- * should be appended to prior to rendering
- * @return {boolean} Success or failure of the render
- */
- render: function (appendToNode) {
- return Panel.superclass.render.call(this, appendToNode, this.innerElement);
- },
- /**
- * Renders the currently set header into it's proper position under the
- * module element. If the module element is not provided, "this.innerElement"
- * is used.
- *
- * @method _renderHeader
- * @protected
- * @param {HTMLElement} moduleElement Optional. A reference to the module element
- */
- _renderHeader: function(moduleElement){
- moduleElement = moduleElement || this.innerElement;
- Panel.superclass._renderHeader.call(this, moduleElement);
- },
- /**
- * Renders the currently set body into it's proper position under the
- * module element. If the module element is not provided, "this.innerElement"
- * is used.
- *
- * @method _renderBody
- * @protected
- * @param {HTMLElement} moduleElement Optional. A reference to the module element.
- */
- _renderBody: function(moduleElement){
- moduleElement = moduleElement || this.innerElement;
- Panel.superclass._renderBody.call(this, moduleElement);
- },
- /**
- * Renders the currently set footer into it's proper position under the
- * module element. If the module element is not provided, "this.innerElement"
- * is used.
- *
- * @method _renderFooter
- * @protected
- * @param {HTMLElement} moduleElement Optional. A reference to the module element
- */
- _renderFooter: function(moduleElement){
- moduleElement = moduleElement || this.innerElement;
- Panel.superclass._renderFooter.call(this, moduleElement);
- },
-
- /**
- * Removes the Panel element from the DOM and sets all child elements
- * to null.
- * @method destroy
- */
- destroy: function () {
- Overlay.windowResizeEvent.unsubscribe(this.sizeMask, this);
- this.removeMask();
- if (this.close) {
- Event.purgeElement(this.close);
- }
- Panel.superclass.destroy.call(this);
- },
- /**
- * Forces the underlay element to be repainted through the application/removal
- * of a yui-force-redraw class to the underlay element.
- *
- * @method forceUnderlayRedraw
- */
- forceUnderlayRedraw : function () {
- var u = this.underlay;
- Dom.addClass(u, "yui-force-redraw");
- setTimeout(function(){Dom.removeClass(u, "yui-force-redraw");}, 0);
- },
- /**
- * Returns a String representation of the object.
- * @method toString
- * @return {String} The string representation of the Panel.
- */
- toString: function () {
- return "Panel " + this.id;
- }
-
- });
- }());
- (function () {
- /**
- * <p>
- * Dialog is an implementation of Panel that can be used to submit form
- * data.
- * </p>
- * <p>
- * Built-in functionality for buttons with event handlers is included.
- * If the optional YUI Button dependancy is included on the page, the buttons
- * created will be instances of YAHOO.widget.Button, otherwise regular HTML buttons
- * will be created.
- * </p>
- * <p>
- * Forms can be processed in 3 ways -- via an asynchronous Connection utility call,
- * a simple form POST or GET, or manually. The YUI Connection utility should be
- * included if you're using the default "async" postmethod, but is not required if
- * you're using any of the other postmethod values.
- * </p>
- * @namespace YAHOO.widget
- * @class Dialog
- * @extends YAHOO.widget.Panel
- * @constructor
- * @param {String} el The element ID representing the Dialog <em>OR</em>
- * @param {HTMLElement} el The element representing the Dialog
- * @param {Object} userConfig The configuration object literal containing
- * the configuration that should be set for this Dialog. See configuration
- * documentation for more details.
- */
- YAHOO.widget.Dialog = function (el, userConfig) {
- YAHOO.widget.Dialog.superclass.constructor.call(this, el, userConfig);
- };
- var Event = YAHOO.util.Event,
- CustomEvent = YAHOO.util.CustomEvent,
- Dom = YAHOO.util.Dom,
- Dialog = YAHOO.widget.Dialog,
- Lang = YAHOO.lang,
- /**
- * Constant representing the name of the Dialog's events
- * @property EVENT_TYPES
- * @private
- * @final
- * @type Object
- */
- EVENT_TYPES = {
- "BEFORE_SUBMIT": "beforeSubmit",
- "SUBMIT": "submit",
- "MANUAL_SUBMIT": "manualSubmit",
- "ASYNC_SUBMIT": "asyncSubmit",
- "FORM_SUBMIT": "formSubmit",
- "CANCEL": "cancel"
- },
- /**
- * Constant representing the Dialog's configuration properties
- * @property DEFAULT_CONFIG
- * @private
- * @final
- * @type Object
- */
- DEFAULT_CONFIG = {
- "POST_METHOD": {
- key: "postmethod",
- value: "async"
- },
- "POST_DATA" : {
- key: "postdata",
- value: null
- },
- "BUTTONS": {
- key: "buttons",
- value: "none",
- supercedes: ["visible"]
- },
- "HIDEAFTERSUBMIT" : {
- key: "hideaftersubmit",
- value: true
- }
- };
- /**
- * Constant representing the default CSS class used for a Dialog
- * @property YAHOO.widget.Dialog.CSS_DIALOG
- * @static
- * @final
- * @type String
- */
- Dialog.CSS_DIALOG = "yui-dialog";
- function removeButtonEventHandlers() {
- var aButtons = this._aButtons,
- nButtons,
- oButton,
- i;
- if (Lang.isArray(aButtons)) {
- nButtons = aButtons.length;
- if (nButtons > 0) {
- i = nButtons - 1;
- do {
- oButton = aButtons[i];
- if (YAHOO.widget.Button && oButton instanceof YAHOO.widget.Button) {
- oButton.destroy();
- }
- else if (oButton.tagName.toUpperCase() == "BUTTON") {
- Event.purgeElement(oButton);
- Event.purgeElement(oButton, false);
- }
- }
- while (i--);
- }
- }
- }
- YAHOO.extend(Dialog, YAHOO.widget.Panel, {
- /**
- * @property form
- * @description Object reference to the Dialog's
- * <code><form></code> element.
- * @default null
- * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
- * level-one-html.html#ID-40002357">HTMLFormElement</a>
- */
- form: null,
-
- /**
- * Initializes the class's configurable properties which can be changed
- * using the Dialog's Config object (cfg).
- * @method initDefaultConfig
- */
- initDefaultConfig: function () {
- Dialog.superclass.initDefaultConfig.call(this);
- /**
- * The internally maintained callback object for use with the
- * Connection utility. The format of the callback object is
- * similar to Connection Manager's callback object and is
- * simply passed through to Connection Manager when the async
- * request is made.
- * @property callback
- * @type Object
- */
- this.callback = {
- /**
- * The function to execute upon success of the
- * Connection submission (when the form does not
- * contain a file input element).
- *
- * @property callback.success
- * @type Function
- */
- success: null,
- /**
- * The function to execute upon failure of the
- * Connection submission
- * @property callback.failure
- * @type Function
- */
- failure: null,
- /**
- *<p>
- * The function to execute upon success of the
- * Connection submission, when the form contains
- * a file input element.
- * </p>
- * <p>
- * <em>NOTE:</em> Connection manager will not
- * invoke the success or failure handlers for the file
- * upload use case. This will be the only callback
- * handler invoked.
- * </p>
- * <p>
- * For more information, see the <a href="http://developer.yahoo.com/yui/connection/#file">
- * Connection Manager documenation on file uploads</a>.
- * </p>
- * @property callback.upload
- * @type Function
- */
- /**
- * The arbitraty argument or arguments to pass to the Connection
- * callback functions
- * @property callback.argument
- * @type Object
- */
- argument: null
- };
- // Add form dialog config properties //
- /**
- * The method to use for posting the Dialog's form. Possible values
- * are "async", "form", and "manual".
- * @config postmethod
- * @type String
- * @default async
- */
- this.cfg.addProperty(DEFAULT_CONFIG.POST_METHOD.key, {
- handler: this.configPostMethod,
- value: DEFAULT_CONFIG.POST_METHOD.value,
- validator: function (val) {
- if (val != "form" && val != "async" && val != "none" &&
- val != "manual") {
- return false;
- } else {
- return true;
- }
- }
- });
- /**
- * Any additional post data which needs to be sent when using the
- * <a href="#config_postmethod">async</a> postmethod for dialog POST submissions.
- * The format for the post data string is defined by Connection Manager's
- * <a href="YAHOO.util.Connect.html#method_asyncRequest">asyncRequest</a>
- * method.
- * @config postdata
- * @type String
- * @default null
- */
- this.cfg.addProperty(DEFAULT_CONFIG.POST_DATA.key, {
- value: DEFAULT_CONFIG.POST_DATA.value
- });
- /**
- * This property is used to configure whether or not the
- * dialog should be automatically hidden after submit.
- *
- * @config hideaftersubmit
- * @type Boolean
- * @default true
- */
- this.cfg.addProperty(DEFAULT_CONFIG.HIDEAFTERSUBMIT.key, {
- value: DEFAULT_CONFIG.HIDEAFTERSUBMIT.value
- });
- /**
- * Array of object literals, each containing a set of properties
- * defining a button to be appended into the Dialog's footer.
- *
- * <p>Each button object in the buttons array can have three properties:</p>
- * <dl>
- * <dt>text:</dt>
- * <dd>
- * The text that will display on the face of the button. The text can
- * include HTML, as long as it is compliant with HTML Button specifications.
- * </dd>
- * <dt>handler:</dt>
- * <dd>Can be either:
- * <ol>
- * <li>A reference to a function that should fire when the
- * button is clicked. (In this case scope of this function is
- * always its Dialog instance.)</li>
- *
- * <li>An object literal representing the code to be
- * executed when the button is clicked.
- *
- * <p>Format:</p>
- *
- * <p>
- * <code>{
- * <br>
- * <strong>fn:</strong> Function, //
- * The handler to call when the event fires.
- * <br>
- * <strong>obj:</strong> Object, //
- * An object to pass back to the handler.
- * <br>
- * <strong>scope:</strong> Object //
- * The object to use for the scope of the handler.
- * <br>
- * }</code>
- * </p>
- * </li>
- * </ol>
- * </dd>
- * <dt>isDefault:</dt>
- * <dd>
- * An optional boolean value that specifies that a button
- * should be highlighted and focused by default.
- * </dd>
- * </dl>
- *
- * <em>NOTE:</em>If the YUI Button Widget is included on the page,
- * the buttons created will be instances of YAHOO.widget.Button.
- * Otherwise, HTML Buttons (<code><BUTTON></code>) will be
- * created.
- *
- * @config buttons
- * @type {Array|String}
- * @default "none"
- */
- this.cfg.addProperty(DEFAULT_CONFIG.BUTTONS.key, {
- handler: this.configButtons,
- value: DEFAULT_CONFIG.BUTTONS.value,
- supercedes : DEFAULT_CONFIG.BUTTONS.supercedes
- });
- },
- /**
- * Initializes the custom events for Dialog which are fired
- * automatically at appropriate times by the Dialog class.
- * @method initEvents
- */
- initEvents: function () {
- Dialog.superclass.initEvents.call(this);
- var SIGNATURE = CustomEvent.LIST;
- /**
- * CustomEvent fired prior to submission
- * @event beforeSubmitEvent
- */
- this.beforeSubmitEvent =
- this.createEvent(EVENT_TYPES.BEFORE_SUBMIT);
- this.beforeSubmitEvent.signature = SIGNATURE;
-
- /**
- * CustomEvent fired after submission
- * @event submitEvent
- */
- this.submitEvent = this.createEvent(EVENT_TYPES.SUBMIT);
- this.submitEvent.signature = SIGNATURE;
-
- /**
- * CustomEvent fired for manual submission, before the generic submit event is fired
- * @event manualSubmitEvent
- */
- this.manualSubmitEvent =
- this.createEvent(EVENT_TYPES.MANUAL_SUBMIT);
- this.manualSubmitEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired after asynchronous submission, before the generic submit event is fired
- *
- * @event asyncSubmitEvent
- * @param {Object} conn The connection object, returned by YAHOO.util.Connect.asyncRequest
- */
- this.asyncSubmitEvent = this.createEvent(EVENT_TYPES.ASYNC_SUBMIT);
- this.asyncSubmitEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired after form-based submission, before the generic submit event is fired
- * @event formSubmitEvent
- */
- this.formSubmitEvent = this.createEvent(EVENT_TYPES.FORM_SUBMIT);
- this.formSubmitEvent.signature = SIGNATURE;
- /**
- * CustomEvent fired after cancel
- * @event cancelEvent
- */
- this.cancelEvent = this.createEvent(EVENT_TYPES.CANCEL);
- this.cancelEvent.signature = SIGNATURE;
-
- },
-
- /**
- * The Dialog initialization method, which is executed for Dialog and
- * all of its subclasses. This method is automatically called by the
- * constructor, and sets up all DOM references for pre-existing markup,
- * and creates required markup if it is not already present.
- *
- * @method init
- * @param {String} el The element ID representing the Dialog <em>OR</em>
- * @param {HTMLElement} el The element representing the Dialog
- * @param {Object} userConfig The configuration object literal
- * containing the configuration that should be set for this Dialog.
- * See configuration documentation for more details.
- */
- init: function (el, userConfig) {
- /*
- Note that we don't pass the user config in here yet because
- we only want it executed once, at the lowest subclass level
- */
- Dialog.superclass.init.call(this, el/*, userConfig*/);
- this.beforeInitEvent.fire(Dialog);
- Dom.addClass(this.element, Dialog.CSS_DIALOG);
- this.cfg.setProperty("visible", false);
- if (userConfig) {
- this.cfg.applyConfig(userConfig, true);
- }
- this.showEvent.subscribe(this.focusFirst, this, true);
- this.beforeHideEvent.subscribe(this.blurButtons, this, true);
- this.subscribe("changeBody", this.registerForm);
- this.initEvent.fire(Dialog);
- },
- /**
- * Submits the Dialog's form depending on the value of the
- * "postmethod" configuration property. <strong>Please note:
- * </strong> As of version 2.3 this method will automatically handle
- * asyncronous file uploads should the Dialog instance's form contain
- * <code><input type="file"></code> elements. If a Dialog
- * instance will be handling asyncronous file uploads, its
- * <code>callback</code> property will need to be setup with a
- * <code>upload</code> handler rather than the standard
- * <code>success</code> and, or <code>failure</code> handlers. For more
- * information, see the <a href="http://developer.yahoo.com/yui/
- * connection/#file">Connection Manager documenation on file uploads</a>.
- * @method doSubmit
- */
- doSubmit: function () {
- var Connect = YAHOO.util.Connect,
- oForm = this.form,
- bUseFileUpload = false,
- bUseSecureFileUpload = false,
- aElements,
- nElements,
- i,
- formAttrs;
- switch (this.cfg.getProperty("postmethod")) {
- case "async":
- aElements = oForm.elements;
- nElements = aElements.length;
- if (nElements > 0) {
- i = nElements - 1;
- do {
- if (aElements[i].type == "file") {
- bUseFileUpload = true;
- break;
- }
- }
- while(i--);
- }
- if (bUseFileUpload && YAHOO.env.ua.ie && this.isSecure) {
- bUseSecureFileUpload = true;
- }
- formAttrs = this._getFormAttributes(oForm);
- Connect.setForm(oForm, bUseFileUpload, bUseSecureFileUpload);
- var postData = this.cfg.getProperty("postdata");
- var c = Connect.asyncRequest(formAttrs.method, formAttrs.action, this.callback, postData);
- this.asyncSubmitEvent.fire(c);
- break;
- case "form":
- oForm.submit();
- this.formSubmitEvent.fire();
- break;
- case "none":
- case "manual":
- this.manualSubmitEvent.fire();
- break;
- }
- },
- /**
- * Retrieves important attributes (currently method and action) from
- * the form element, accounting for any elements which may have the same name
- * as the attributes. Defaults to "POST" and "" for method and action respectively
- * if the attribute cannot be retrieved.
- *
- * @method _getFormAttributes
- * @protected
- * @param {HTMLFormElement} oForm The HTML Form element from which to retrieve the attributes
- * @return {Object} Object literal, with method and action String properties.
- */
- _getFormAttributes : function(oForm){
- var attrs = {
- method : null,
- action : null
- };
- if (oForm) {
- if (oForm.getAttributeNode) {
- var action = oForm.getAttributeNode("action");
- var method = oForm.getAttributeNode("method");
- if (action) {
- attrs.action = action.value;
- }
- if (method) {
- attrs.method = method.value;
- }
- } else {
- attrs.action = oForm.getAttribute("action");
- attrs.method = oForm.getAttribute("method");
- }
- }
- attrs.method = (Lang.isString(attrs.method) ? attrs.method : "POST").toUpperCase();
- attrs.action = Lang.isString(attrs.action) ? attrs.action : "";
- return attrs;
- },
- /**
- * Prepares the Dialog's internal FORM object, creating one if one is
- * not currently present.
- * @method registerForm
- */
- registerForm: function() {
- var form = this.element.getElementsByTagName("form")[0];
- if (this.form) {
- if (this.form == form && Dom.isAncestor(this.element, this.form)) {
- return;
- } else {
- Event.purgeElement(this.form);
- this.form = null;
- }
- }
- if (!form) {
- form = document.createElement("form");
- form.name = "frm_" + this.id;
- this.body.appendChild(form);
- }
- if (form) {
- this.form = form;
- Event.on(form, "submit", this._submitHandler, this, true);
- }
- },
- /**
- * Internal handler for the form submit event
- *
- * @method _submitHandler
- * @protected
- * @param {DOMEvent} e The DOM Event object
- */
- _submitHandler : function(e) {
- Event.stopEvent(e);
- this.submit();
- this.form.blur();
- },
- /**
- * Sets up a tab, shift-tab loop between the first and last elements
- * provided. NOTE: Sets up the preventBackTab and preventTabOut KeyListener
- * instance properties, which are reset everytime this method is invoked.
- *
- * @method setTabLoop
- * @param {HTMLElement} firstElement
- * @param {HTMLElement} lastElement
- *
- */
- setTabLoop : function(firstElement, lastElement) {
- firstElement = firstElement || this.firstButton;
- lastElement = this.lastButton || lastElement;
- Dialog.superclass.setTabLoop.call(this, firstElement, lastElement);
- },
- /**
- * Configures instance properties, pointing to the
- * first and last focusable elements in the Dialog's form.
- *
- * @method setFirstLastFocusable
- */
- setFirstLastFocusable : function() {
- Dialog.superclass.setFirstLastFocusable.call(this);
- var i, l, el, elements = this.focusableElements;
- this.firstFormElement = null;
- this.lastFormElement = null;
- if (this.form && elements && elements.length > 0) {
- l = elements.length;
- for (i = 0; i < l; ++i) {
- el = elements[i];
- if (this.form === el.form) {
- this.firstFormElement = el;
- break;
- }
- }
- for (i = l-1; i >= 0; --i) {
- el = elements[i];
- if (this.form === el.form) {
- this.lastFormElement = el;
- break;
- }
- }
- }
- },
- // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
- /**
- * The default event handler fired when the "close" property is
- * changed. The method controls the appending or hiding of the close
- * icon at the top right of the Dialog.
- * @method configClose
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For
- * configuration handlers, args[0] will equal the newly applied value
- * for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configClose: function (type, args, obj) {
- Dialog.superclass.configClose.apply(this, arguments);
- },
- /**
- * Event handler for the close icon
- *
- * @method _doClose
- * @protected
- *
- * @param {DOMEvent} e
- */
- _doClose : function(e) {
- Event.preventDefault(e);
- this.cancel();
- },
- /**
- * The default event handler for the "buttons" configuration property
- * @method configButtons
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configButtons: function (type, args, obj) {
- var Button = YAHOO.widget.Button,
- aButtons = args[0],
- oInnerElement = this.innerElement,
- oButton,
- oButtonEl,
- oYUIButton,
- nButtons,
- oSpan,
- oFooter,
- i;
- removeButtonEventHandlers.call(this);
- this._aButtons = null;
- if (Lang.isArray(aButtons)) {
- oSpan = document.createElement("span");
- oSpan.className = "button-group";
- nButtons = aButtons.length;
- this._aButtons = [];
- this.defaultHtmlButton = null;
- for (i = 0; i < nButtons; i++) {
- oButton = aButtons[i];
- if (Button) {
- oYUIButton = new Button({ label: oButton.text});
- oYUIButton.appendTo(oSpan);
- oButtonEl = oYUIButton.get("element");
- if (oButton.isDefault) {
- oYUIButton.addClass("default");
- this.defaultHtmlButton = oButtonEl;
- }
- if (Lang.isFunction(oButton.handler)) {
- oYUIButton.set("onclick", {
- fn: oButton.handler,
- obj: this,
- scope: this
- });
- } else if (Lang.isObject(oButton.handler) && Lang.isFunction(oButton.handler.fn)) {
- oYUIButton.set("onclick", {
- fn: oButton.handler.fn,
- obj: ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this),
- scope: (oButton.handler.scope || this)
- });
- }
- this._aButtons[this._aButtons.length] = oYUIButton;
- } else {
- oButtonEl = document.createElement("button");
- oButtonEl.setAttribute("type", "button");
- if (oButton.isDefault) {
- oButtonEl.className = "default";
- this.defaultHtmlButton = oButtonEl;
- }
- oButtonEl.innerHTML = oButton.text;
- if (Lang.isFunction(oButton.handler)) {
- Event.on(oButtonEl, "click", oButton.handler, this, true);
- } else if (Lang.isObject(oButton.handler) &&
- Lang.isFunction(oButton.handler.fn)) {
-
- Event.on(oButtonEl, "click",
- oButton.handler.fn,
- ((!Lang.isUndefined(oButton.handler.obj)) ? oButton.handler.obj : this),
- (oButton.handler.scope || this));
- }
- oSpan.appendChild(oButtonEl);
- this._aButtons[this._aButtons.length] = oButtonEl;
- }
- oButton.htmlButton = oButtonEl;
- if (i === 0) {
- this.firstButton = oButtonEl;
- }
- if (i == (nButtons - 1)) {
- this.lastButton = oButtonEl;
- }
- }
- this.setFooter(oSpan);
- oFooter = this.footer;
- if (Dom.inDocument(this.element) && !Dom.isAncestor(oInnerElement, oFooter)) {
- oInnerElement.appendChild(oFooter);
- }
- this.buttonSpan = oSpan;
- } else { // Do cleanup
- oSpan = this.buttonSpan;
- oFooter = this.footer;
- if (oSpan && oFooter) {
- oFooter.removeChild(oSpan);
- this.buttonSpan = null;
- this.firstButton = null;
- this.lastButton = null;
- this.defaultHtmlButton = null;
- }
- }
- this.changeContentEvent.fire();
- },
- /**
- * @method getButtons
- * @description Returns an array containing each of the Dialog's
- * buttons, by default an array of HTML <code><BUTTON></code>
- * elements. If the Dialog's buttons were created using the
- * YAHOO.widget.Button class (via the inclusion of the optional Button
- * dependancy on the page), an array of YAHOO.widget.Button instances
- * is returned.
- * @return {Array}
- */
- getButtons: function () {
- return this._aButtons || null;
- },
- /**
- * <p>
- * Sets focus to the first focusable element in the Dialog's form if found,
- * else, the default button if found, else the first button defined via the
- * "buttons" configuration property.
- * </p>
- * <p>
- * This method is invoked when the Dialog is made visible.
- * </p>
- * @method focusFirst
- */
- focusFirst: function (type, args, obj) {
- var el = this.firstFormElement;
- if (args && args[1]) {
- Event.stopEvent(args[1]);
- }
- if (el) {
- try {
- el.focus();
- } catch(oException) {
- // Ignore
- }
- } else {
- if (this.defaultHtmlButton) {
- this.focusDefaultButton();
- } else {
- this.focusFirstButton();
- }
- }
- },
- /**
- * Sets focus to the last element in the Dialog's form or the last
- * button defined via the "buttons" configuration property.
- * @method focusLast
- */
- focusLast: function (type, args, obj) {
- var aButtons = this.cfg.getProperty("buttons"),
- el = this.lastFormElement;
- if (args && args[1]) {
- Event.stopEvent(args[1]);
- }
- if (aButtons && Lang.isArray(aButtons)) {
- this.focusLastButton();
- } else {
- if (el) {
- try {
- el.focus();
- } catch(oException) {
- // Ignore
- }
- }
- }
- },
- /**
- * Helper method to normalize button references. It either returns the
- * YUI Button instance for the given element if found,
- * or the passes back the HTMLElement reference if a corresponding YUI Button
- * reference is not found or YAHOO.widget.Button does not exist on the page.
- *
- * @method _getButton
- * @private
- * @param {HTMLElement} button
- * @return {YAHOO.widget.Button|HTMLElement}
- */
- _getButton : function(button) {
- var Button = YAHOO.widget.Button;
- // If we have an HTML button and YUI Button is on the page,
- // get the YUI Button reference if available.
- if (Button && button && button.nodeName && button.id) {
- button = Button.getButton(button.id) || button;
- }
- return button;
- },
- /**
- * Sets the focus to the button that is designated as the default via
- * the "buttons" configuration property. By default, this method is
- * called when the Dialog is made visible.
- * @method focusDefaultButton
- */
- focusDefaultButton: function () {
- var button = this._getButton(this.defaultHtmlButton);
- if (button) {
- /*
- Place the call to the "focus" method inside a try/catch
- block to prevent IE from throwing JavaScript errors if
- the element is disabled or hidden.
- */
- try {
- button.focus();
- } catch(oException) {
- }
- }
- },
- /**
- * Blurs all the buttons defined via the "buttons"
- * configuration property.
- * @method blurButtons
- */
- blurButtons: function () {
-
- var aButtons = this.cfg.getProperty("buttons"),
- nButtons,
- oButton,
- oElement,
- i;
- if (aButtons && Lang.isArray(aButtons)) {
- nButtons = aButtons.length;
- if (nButtons > 0) {
- i = (nButtons - 1);
- do {
- oButton = aButtons[i];
- if (oButton) {
- oElement = this._getButton(oButton.htmlButton);
- if (oElement) {
- /*
- Place the call to the "blur" method inside
- a try/catch block to prevent IE from
- throwing JavaScript errors if the element
- is disabled or hidden.
- */
- try {
- oElement.blur();
- } catch(oException) {
- // ignore
- }
- }
- }
- } while(i--);
- }
- }
- },
- /**
- * Sets the focus to the first button created via the "buttons"
- * configuration property.
- * @method focusFirstButton
- */
- focusFirstButton: function () {
- var aButtons = this.cfg.getProperty("buttons"),
- oButton,
- oElement;
- if (aButtons && Lang.isArray(aButtons)) {
- oButton = aButtons[0];
- if (oButton) {
- oElement = this._getButton(oButton.htmlButton);
- if (oElement) {
- /*
- Place the call to the "focus" method inside a
- try/catch block to prevent IE from throwing
- JavaScript errors if the element is disabled
- or hidden.
- */
- try {
- oElement.focus();
- } catch(oException) {
- // ignore
- }
- }
- }
- }
- },
- /**
- * Sets the focus to the last button created via the "buttons"
- * configuration property.
- * @method focusLastButton
- */
- focusLastButton: function () {
- var aButtons = this.cfg.getProperty("buttons"),
- nButtons,
- oButton,
- oElement;
- if (aButtons && Lang.isArray(aButtons)) {
- nButtons = aButtons.length;
- if (nButtons > 0) {
- oButton = aButtons[(nButtons - 1)];
- if (oButton) {
- oElement = this._getButton(oButton.htmlButton);
- if (oElement) {
- /*
- Place the call to the "focus" method inside a
- try/catch block to prevent IE from throwing
- JavaScript errors if the element is disabled
- or hidden.
- */
-
- try {
- oElement.focus();
- } catch(oException) {
- // Ignore
- }
- }
- }
- }
- }
- },
- /**
- * The default event handler for the "postmethod" configuration property
- * @method configPostMethod
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For
- * configuration handlers, args[0] will equal the newly applied value
- * for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configPostMethod: function (type, args, obj) {
- this.registerForm();
- },
- // END BUILT-IN PROPERTY EVENT HANDLERS //
-
- /**
- * Built-in function hook for writing a validation function that will
- * be checked for a "true" value prior to a submit. This function, as
- * implemented by default, always returns true, so it should be
- * overridden if validation is necessary.
- * @method validate
- */
- validate: function () {
- return true;
- },
- /**
- * Executes a submit of the Dialog if validation
- * is successful. By default the Dialog is hidden
- * after submission, but you can set the "hideaftersubmit"
- * configuration property to false, to prevent the Dialog
- * from being hidden.
- *
- * @method submit
- */
- submit: function () {
- if (this.validate()) {
- if (this.beforeSubmitEvent.fire()) {
- this.doSubmit();
- this.submitEvent.fire();
-
- if (this.cfg.getProperty("hideaftersubmit")) {
- this.hide();
- }
-
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- },
- /**
- * Executes the cancel of the Dialog followed by a hide.
- * @method cancel
- */
- cancel: function () {
- this.cancelEvent.fire();
- this.hide();
- },
-
- /**
- * Returns a JSON-compatible data structure representing the data
- * currently contained in the form.
- * @method getData
- * @return {Object} A JSON object reprsenting the data of the
- * current form.
- */
- getData: function () {
- var oForm = this.form,
- aElements,
- nTotalElements,
- oData,
- sName,
- oElement,
- nElements,
- sType,
- sTagName,
- aOptions,
- nOptions,
- aValues,
- oOption,
- oRadio,
- oCheckbox,
- valueAttr,
- i,
- n;
-
- function isFormElement(p_oElement) {
- var sTag = p_oElement.tagName.toUpperCase();
- return ((sTag == "INPUT" || sTag == "TEXTAREA" ||
- sTag == "SELECT") && p_oElement.name == sName);
- }
- if (oForm) {
- aElements = oForm.elements;
- nTotalElements = aElements.length;
- oData = {};
- for (i = 0; i < nTotalElements; i++) {
- sName = aElements[i].name;
- /*
- Using "Dom.getElementsBy" to safeguard user from JS
- errors that result from giving a form field (or set of
- fields) the same name as a native method of a form
- (like "submit") or a DOM collection (such as the "item"
- method). Originally tried accessing fields via the
- "namedItem" method of the "element" collection, but
- discovered that it won't return a collection of fields
- in Gecko.
- */
- oElement = Dom.getElementsBy(isFormElement, "*", oForm);
- nElements = oElement.length;
- if (nElements > 0) {
- if (nElements == 1) {
- oElement = oElement[0];
- sType = oElement.type;
- sTagName = oElement.tagName.toUpperCase();
- switch (sTagName) {
- case "INPUT":
- if (sType == "checkbox") {
- oData[sName] = oElement.checked;
- } else if (sType != "radio") {
- oData[sName] = oElement.value;
- }
- break;
- case "TEXTAREA":
- oData[sName] = oElement.value;
- break;
-
- case "SELECT":
- aOptions = oElement.options;
- nOptions = aOptions.length;
- aValues = [];
-
- for (n = 0; n < nOptions; n++) {
- oOption = aOptions[n];
- if (oOption.selected) {
- valueAttr = oOption.attributes.value;
- aValues[aValues.length] = (valueAttr && valueAttr.specified) ? oOption.value : oOption.text;
- }
- }
- oData[sName] = aValues;
- break;
- }
-
- } else {
- sType = oElement[0].type;
- switch (sType) {
- case "radio":
- for (n = 0; n < nElements; n++) {
- oRadio = oElement[n];
- if (oRadio.checked) {
- oData[sName] = oRadio.value;
- break;
- }
- }
- break;
-
- case "checkbox":
- aValues = [];
- for (n = 0; n < nElements; n++) {
- oCheckbox = oElement[n];
- if (oCheckbox.checked) {
- aValues[aValues.length] = oCheckbox.value;
- }
- }
- oData[sName] = aValues;
- break;
- }
- }
- }
- }
- }
- return oData;
- },
- /**
- * Removes the Panel element from the DOM and sets all child elements
- * to null.
- * @method destroy
- */
- destroy: function () {
- removeButtonEventHandlers.call(this);
- this._aButtons = null;
- var aForms = this.element.getElementsByTagName("form"),
- oForm;
- if (aForms.length > 0) {
- oForm = aForms[0];
- if (oForm) {
- Event.purgeElement(oForm);
- if (oForm.parentNode) {
- oForm.parentNode.removeChild(oForm);
- }
- this.form = null;
- }
- }
- Dialog.superclass.destroy.call(this);
- },
- /**
- * Returns a string representation of the object.
- * @method toString
- * @return {String} The string representation of the Dialog
- */
- toString: function () {
- return "Dialog " + this.id;
- }
-
- });
- }());
- (function () {
- /**
- * SimpleDialog is a simple implementation of Dialog that can be used to
- * submit a single value. Forms can be processed in 3 ways -- via an
- * asynchronous Connection utility call, a simple form POST or GET,
- * or manually.
- * @namespace YAHOO.widget
- * @class SimpleDialog
- * @extends YAHOO.widget.Dialog
- * @constructor
- * @param {String} el The element ID representing the SimpleDialog
- * <em>OR</em>
- * @param {HTMLElement} el The element representing the SimpleDialog
- * @param {Object} userConfig The configuration object literal containing
- * the configuration that should be set for this SimpleDialog. See
- * configuration documentation for more details.
- */
- YAHOO.widget.SimpleDialog = function (el, userConfig) {
-
- YAHOO.widget.SimpleDialog.superclass.constructor.call(this,
- el, userConfig);
-
- };
- var Dom = YAHOO.util.Dom,
- SimpleDialog = YAHOO.widget.SimpleDialog,
-
- /**
- * Constant representing the SimpleDialog's configuration properties
- * @property DEFAULT_CONFIG
- * @private
- * @final
- * @type Object
- */
- DEFAULT_CONFIG = {
-
- "ICON": {
- key: "icon",
- value: "none",
- suppressEvent: true
- },
-
- "TEXT": {
- key: "text",
- value: "",
- suppressEvent: true,
- supercedes: ["icon"]
- }
-
- };
- /**
- * Constant for the standard network icon for a blocking action
- * @property YAHOO.widget.SimpleDialog.ICON_BLOCK
- * @static
- * @final
- * @type String
- */
- SimpleDialog.ICON_BLOCK = "blckicon";
-
- /**
- * Constant for the standard network icon for alarm
- * @property YAHOO.widget.SimpleDialog.ICON_ALARM
- * @static
- * @final
- * @type String
- */
- SimpleDialog.ICON_ALARM = "alrticon";
-
- /**
- * Constant for the standard network icon for help
- * @property YAHOO.widget.SimpleDialog.ICON_HELP
- * @static
- * @final
- * @type String
- */
- SimpleDialog.ICON_HELP = "hlpicon";
-
- /**
- * Constant for the standard network icon for info
- * @property YAHOO.widget.SimpleDialog.ICON_INFO
- * @static
- * @final
- * @type String
- */
- SimpleDialog.ICON_INFO = "infoicon";
-
- /**
- * Constant for the standard network icon for warn
- * @property YAHOO.widget.SimpleDialog.ICON_WARN
- * @static
- * @final
- * @type String
- */
- SimpleDialog.ICON_WARN = "warnicon";
-
- /**
- * Constant for the standard network icon for a tip
- * @property YAHOO.widget.SimpleDialog.ICON_TIP
- * @static
- * @final
- * @type String
- */
- SimpleDialog.ICON_TIP = "tipicon";
- /**
- * Constant representing the name of the CSS class applied to the element
- * created by the "icon" configuration property.
- * @property YAHOO.widget.SimpleDialog.ICON_CSS_CLASSNAME
- * @static
- * @final
- * @type String
- */
- SimpleDialog.ICON_CSS_CLASSNAME = "yui-icon";
-
- /**
- * Constant representing the default CSS class used for a SimpleDialog
- * @property YAHOO.widget.SimpleDialog.CSS_SIMPLEDIALOG
- * @static
- * @final
- * @type String
- */
- SimpleDialog.CSS_SIMPLEDIALOG = "yui-simple-dialog";
-
- YAHOO.extend(SimpleDialog, YAHOO.widget.Dialog, {
-
- /**
- * Initializes the class's configurable properties which can be changed
- * using the SimpleDialog's Config object (cfg).
- * @method initDefaultConfig
- */
- initDefaultConfig: function () {
-
- SimpleDialog.superclass.initDefaultConfig.call(this);
-
- // Add dialog config properties //
-
- /**
- * Sets the informational icon for the SimpleDialog
- * @config icon
- * @type String
- * @default "none"
- */
- this.cfg.addProperty(DEFAULT_CONFIG.ICON.key, {
- handler: this.configIcon,
- value: DEFAULT_CONFIG.ICON.value,
- suppressEvent: DEFAULT_CONFIG.ICON.suppressEvent
- });
-
- /**
- * Sets the text for the SimpleDialog
- * @config text
- * @type String
- * @default ""
- */
- this.cfg.addProperty(DEFAULT_CONFIG.TEXT.key, {
- handler: this.configText,
- value: DEFAULT_CONFIG.TEXT.value,
- suppressEvent: DEFAULT_CONFIG.TEXT.suppressEvent,
- supercedes: DEFAULT_CONFIG.TEXT.supercedes
- });
-
- },
-
-
- /**
- * The SimpleDialog initialization method, which is executed for
- * SimpleDialog and all of its subclasses. This method is automatically
- * called by the constructor, and sets up all DOM references for
- * pre-existing markup, and creates required markup if it is not
- * already present.
- * @method init
- * @param {String} el The element ID representing the SimpleDialog
- * <em>OR</em>
- * @param {HTMLElement} el The element representing the SimpleDialog
- * @param {Object} userConfig The configuration object literal
- * containing the configuration that should be set for this
- * SimpleDialog. See configuration documentation for more details.
- */
- init: function (el, userConfig) {
- /*
- Note that we don't pass the user config in here yet because we
- only want it executed once, at the lowest subclass level
- */
- SimpleDialog.superclass.init.call(this, el/*, userConfig*/);
-
- this.beforeInitEvent.fire(SimpleDialog);
-
- Dom.addClass(this.element, SimpleDialog.CSS_SIMPLEDIALOG);
-
- this.cfg.queueProperty("postmethod", "manual");
-
- if (userConfig) {
- this.cfg.applyConfig(userConfig, true);
- }
-
- this.beforeRenderEvent.subscribe(function () {
- if (! this.body) {
- this.setBody("");
- }
- }, this, true);
-
- this.initEvent.fire(SimpleDialog);
-
- },
-
- /**
- * Prepares the SimpleDialog's internal FORM object, creating one if one
- * is not currently present, and adding the value hidden field.
- * @method registerForm
- */
- registerForm: function () {
- SimpleDialog.superclass.registerForm.call(this);
- this.form.innerHTML += "<input type=\"hidden\" name=\"" +
- this.id + "\" value=\"\"/>";
- },
-
- // BEGIN BUILT-IN PROPERTY EVENT HANDLERS //
-
- /**
- * Fired when the "icon" property is set.
- * @method configIcon
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configIcon: function (type,args,obj) {
-
- var sIcon = args[0],
- oBody = this.body,
- sCSSClass = SimpleDialog.ICON_CSS_CLASSNAME,
- aElements,
- oIcon,
- oIconParent;
-
- if (sIcon && sIcon != "none") {
- aElements = Dom.getElementsByClassName(sCSSClass, "*" , oBody);
- if (aElements.length === 1) {
- oIcon = aElements[0];
- oIconParent = oIcon.parentNode;
- if (oIconParent) {
- oIconParent.removeChild(oIcon);
- oIcon = null;
- }
- }
- if (sIcon.indexOf(".") == -1) {
- oIcon = document.createElement("span");
- oIcon.className = (sCSSClass + " " + sIcon);
- oIcon.innerHTML = " ";
- } else {
- oIcon = document.createElement("img");
- oIcon.src = (this.imageRoot + sIcon);
- oIcon.className = sCSSClass;
- }
-
- if (oIcon) {
-
- oBody.insertBefore(oIcon, oBody.firstChild);
-
- }
- }
- },
- /**
- * Fired when the "text" property is set.
- * @method configText
- * @param {String} type The CustomEvent type (usually the property name)
- * @param {Object[]} args The CustomEvent arguments. For configuration
- * handlers, args[0] will equal the newly applied value for the property.
- * @param {Object} obj The scope object. For configuration handlers,
- * this will usually equal the owner.
- */
- configText: function (type,args,obj) {
- var text = args[0];
- if (text) {
- this.setBody(text);
- this.cfg.refireEvent("icon");
- }
- },
-
- // END BUILT-IN PROPERTY EVENT HANDLERS //
-
- /**
- * Returns a string representation of the object.
- * @method toString
- * @return {String} The string representation of the SimpleDialog
- */
- toString: function () {
- return "SimpleDialog " + this.id;
- }
- /**
- * <p>
- * Sets the SimpleDialog's body content to the HTML specified.
- * If no body is present, one will be automatically created.
- * An empty string can be passed to the method to clear the contents of the body.
- * </p>
- * <p><strong>NOTE:</strong> SimpleDialog provides the <a href="#config_text">text</a>
- * and <a href="#config_icon">icon</a> configuration properties to set the contents
- * of it's body element in accordance with the UI design for a SimpleDialog (an
- * icon and message text). Calling setBody on the SimpleDialog will not enforce this
- * UI design constraint and will replace the entire contents of the SimpleDialog body.
- * It should only be used if you wish the replace the default icon/text body structure
- * of a SimpleDialog with your own custom markup.</p>
- *
- * @method setBody
- * @param {String} bodyContent The HTML used to set the body.
- * As a convenience, non HTMLElement objects can also be passed into
- * the method, and will be treated as strings, with the body innerHTML
- * set to their default toString implementations.
- * <em>OR</em>
- * @param {HTMLElement} bodyContent The HTMLElement to add as the first and only child of the body element.
- * <em>OR</em>
- * @param {DocumentFragment} bodyContent The document fragment
- * containing elements which are to be added to the body
- */
- });
- }());
- (function () {
- /**
- * ContainerEffect encapsulates animation transitions that are executed when
- * an Overlay is shown or hidden.
- * @namespace YAHOO.widget
- * @class ContainerEffect
- * @constructor
- * @param {YAHOO.widget.Overlay} overlay The Overlay that the animation
- * should be associated with
- * @param {Object} attrIn The object literal representing the animation
- * arguments to be used for the animate-in transition. The arguments for
- * this literal are: attributes(object, see YAHOO.util.Anim for description),
- * duration(Number), and method(i.e. Easing.easeIn).
- * @param {Object} attrOut The object literal representing the animation
- * arguments to be used for the animate-out transition. The arguments for
- * this literal are: attributes(object, see YAHOO.util.Anim for description),
- * duration(Number), and method(i.e. Easing.easeIn).
- * @param {HTMLElement} targetElement Optional. The target element that
- * should be animated during the transition. Defaults to overlay.element.
- * @param {class} Optional. The animation class to instantiate. Defaults to
- * YAHOO.util.Anim. Other options include YAHOO.util.Motion.
- */
- YAHOO.widget.ContainerEffect = function (overlay, attrIn, attrOut, targetElement, animClass) {
- if (!animClass) {
- animClass = YAHOO.util.Anim;
- }
- /**
- * The overlay to animate
- * @property overlay
- * @type YAHOO.widget.Overlay
- */
- this.overlay = overlay;
-
- /**
- * The animation attributes to use when transitioning into view
- * @property attrIn
- * @type Object
- */
- this.attrIn = attrIn;
-
- /**
- * The animation attributes to use when transitioning out of view
- * @property attrOut
- * @type Object
- */
- this.attrOut = attrOut;
-
- /**
- * The target element to be animated
- * @property targetElement
- * @type HTMLElement
- */
- this.targetElement = targetElement || overlay.element;
-
- /**
- * The animation class to use for animating the overlay
- * @property animClass
- * @type class
- */
- this.animClass = animClass;
-
- };
- var Dom = YAHOO.util.Dom,
- CustomEvent = YAHOO.util.CustomEvent,
- ContainerEffect = YAHOO.widget.ContainerEffect;
- /**
- * A pre-configured ContainerEffect instance that can be used for fading
- * an overlay in and out.
- * @method FADE
- * @static
- * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
- * @param {Number} dur The duration of the animation
- * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
- */
- ContainerEffect.FADE = function (overlay, dur) {
- var Easing = YAHOO.util.Easing,
- fin = {
- attributes: {opacity:{from:0, to:1}},
- duration: dur,
- method: Easing.easeIn
- },
- fout = {
- attributes: {opacity:{to:0}},
- duration: dur,
- method: Easing.easeOut
- },
- fade = new ContainerEffect(overlay, fin, fout, overlay.element);
- fade.handleUnderlayStart = function() {
- var underlay = this.overlay.underlay;
- if (underlay && YAHOO.env.ua.ie) {
- var hasFilters = (underlay.filters && underlay.filters.length > 0);
- if(hasFilters) {
- Dom.addClass(overlay.element, "yui-effect-fade");
- }
- }
- };
- fade.handleUnderlayComplete = function() {
- var underlay = this.overlay.underlay;
- if (underlay && YAHOO.env.ua.ie) {
- Dom.removeClass(overlay.element, "yui-effect-fade");
- }
- };
- fade.handleStartAnimateIn = function (type, args, obj) {
- Dom.addClass(obj.overlay.element, "hide-select");
- if (!obj.overlay.underlay) {
- obj.overlay.cfg.refireEvent("underlay");
- }
- obj.handleUnderlayStart();
- obj.overlay._setDomVisibility(true);
- Dom.setStyle(obj.overlay.element, "opacity", 0);
- };
- fade.handleCompleteAnimateIn = function (type,args,obj) {
- Dom.removeClass(obj.overlay.element, "hide-select");
- if (obj.overlay.element.style.filter) {
- obj.overlay.element.style.filter = null;
- }
- obj.handleUnderlayComplete();
- obj.overlay.cfg.refireEvent("iframe");
- obj.animateInCompleteEvent.fire();
- };
- fade.handleStartAnimateOut = function (type, args, obj) {
- Dom.addClass(obj.overlay.element, "hide-select");
- obj.handleUnderlayStart();
- };
- fade.handleCompleteAnimateOut = function (type, args, obj) {
- Dom.removeClass(obj.overlay.element, "hide-select");
- if (obj.overlay.element.style.filter) {
- obj.overlay.element.style.filter = null;
- }
- obj.overlay._setDomVisibility(false);
- Dom.setStyle(obj.overlay.element, "opacity", 1);
- obj.handleUnderlayComplete();
- obj.overlay.cfg.refireEvent("iframe");
- obj.animateOutCompleteEvent.fire();
- };
- fade.init();
- return fade;
- };
-
-
- /**
- * A pre-configured ContainerEffect instance that can be used for sliding an
- * overlay in and out.
- * @method SLIDE
- * @static
- * @param {YAHOO.widget.Overlay} overlay The Overlay object to animate
- * @param {Number} dur The duration of the animation
- * @return {YAHOO.widget.ContainerEffect} The configured ContainerEffect object
- */
- ContainerEffect.SLIDE = function (overlay, dur) {
- var Easing = YAHOO.util.Easing,
- x = overlay.cfg.getProperty("x") || Dom.getX(overlay.element),
- y = overlay.cfg.getProperty("y") || Dom.getY(overlay.element),
- clientWidth = Dom.getClientWidth(),
- offsetWidth = overlay.element.offsetWidth,
- sin = {
- attributes: { points: { to: [x, y] } },
- duration: dur,
- method: Easing.easeIn
- },
- sout = {
- attributes: { points: { to: [(clientWidth + 25), y] } },
- duration: dur,
- method: Easing.easeOut
- },
- slide = new ContainerEffect(overlay, sin, sout, overlay.element, YAHOO.util.Motion);
- slide.handleStartAnimateIn = function (type,args,obj) {
- obj.overlay.element.style.left = ((-25) - offsetWidth) + "px";
- obj.overlay.element.style.top = y + "px";
- };
- slide.handleTweenAnimateIn = function (type, args, obj) {
-
- var pos = Dom.getXY(obj.overlay.element),
- currentX = pos[0],
- currentY = pos[1];
-
- if (Dom.getStyle(obj.overlay.element, "visibility") ==
- "hidden" && currentX < x) {
- obj.overlay._setDomVisibility(true);
- }
-
- obj.overlay.cfg.setProperty("xy", [currentX, currentY], true);
- obj.overlay.cfg.refireEvent("iframe");
- };
-
- slide.handleCompleteAnimateIn = function (type, args, obj) {
- obj.overlay.cfg.setProperty("xy", [x, y], true);
- obj.startX = x;
- obj.startY = y;
- obj.overlay.cfg.refireEvent("iframe");
- obj.animateInCompleteEvent.fire();
- };
-
- slide.handleStartAnimateOut = function (type, args, obj) {
-
- var vw = Dom.getViewportWidth(),
- pos = Dom.getXY(obj.overlay.element),
- yso = pos[1];
-
- obj.animOut.attributes.points.to = [(vw + 25), yso];
- };
-
- slide.handleTweenAnimateOut = function (type, args, obj) {
-
- var pos = Dom.getXY(obj.overlay.element),
- xto = pos[0],
- yto = pos[1];
-
- obj.overlay.cfg.setProperty("xy", [xto, yto], true);
- obj.overlay.cfg.refireEvent("iframe");
- };
-
- slide.handleCompleteAnimateOut = function (type, args, obj) {
- obj.overlay._setDomVisibility(false);
- obj.overlay.cfg.setProperty("xy", [x, y]);
- obj.animateOutCompleteEvent.fire();
- };
- slide.init();
- return slide;
- };
- ContainerEffect.prototype = {
- /**
- * Initializes the animation classes and events.
- * @method init
- */
- init: function () {
- this.beforeAnimateInEvent = this.createEvent("beforeAnimateIn");
- this.beforeAnimateInEvent.signature = CustomEvent.LIST;
-
- this.beforeAnimateOutEvent = this.createEvent("beforeAnimateOut");
- this.beforeAnimateOutEvent.signature = CustomEvent.LIST;
-
- this.animateInCompleteEvent = this.createEvent("animateInComplete");
- this.animateInCompleteEvent.signature = CustomEvent.LIST;
-
- this.animateOutCompleteEvent =
- this.createEvent("animateOutComplete");
- this.animateOutCompleteEvent.signature = CustomEvent.LIST;
-
- this.animIn = new this.animClass(this.targetElement,
- this.attrIn.attributes, this.attrIn.duration,
- this.attrIn.method);
- this.animIn.onStart.subscribe(this.handleStartAnimateIn, this);
- this.animIn.onTween.subscribe(this.handleTweenAnimateIn, this);
- this.animIn.onComplete.subscribe(this.handleCompleteAnimateIn,
- this);
-
- this.animOut = new this.animClass(this.targetElement,
- this.attrOut.attributes, this.attrOut.duration,
- this.attrOut.method);
- this.animOut.onStart.subscribe(this.handleStartAnimateOut, this);
- this.animOut.onTween.subscribe(this.handleTweenAnimateOut, this);
- this.animOut.onComplete.subscribe(this.handleCompleteAnimateOut,
- this);
- },
-
- /**
- * Triggers the in-animation.
- * @method animateIn
- */
- animateIn: function () {
- this.beforeAnimateInEvent.fire();
- this.animIn.animate();
- },
- /**
- * Triggers the out-animation.
- * @method animateOut
- */
- animateOut: function () {
- this.beforeAnimateOutEvent.fire();
- this.animOut.animate();
- },
- /**
- * The default onStart handler for the in-animation.
- * @method handleStartAnimateIn
- * @param {String} type The CustomEvent type
- * @param {Object[]} args The CustomEvent arguments
- * @param {Object} obj The scope object
- */
- handleStartAnimateIn: function (type, args, obj) { },
- /**
- * The default onTween handler for the in-animation.
- * @method handleTweenAnimateIn
- * @param {String} type The CustomEvent type
- * @param {Object[]} args The CustomEvent arguments
- * @param {Object} obj The scope object
- */
- handleTweenAnimateIn: function (type, args, obj) { },
- /**
- * The default onComplete handler for the in-animation.
- * @method handleCompleteAnimateIn
- * @param {String} type The CustomEvent type
- * @param {Object[]} args The CustomEvent arguments
- * @param {Object} obj The scope object
- */
- handleCompleteAnimateIn: function (type, args, obj) { },
- /**
- * The default onStart handler for the out-animation.
- * @method handleStartAnimateOut
- * @param {String} type The CustomEvent type
- * @param {Object[]} args The CustomEvent arguments
- * @param {Object} obj The scope object
- */
- handleStartAnimateOut: function (type, args, obj) { },
- /**
- * The default onTween handler for the out-animation.
- * @method handleTweenAnimateOut
- * @param {String} type The CustomEvent type
- * @param {Object[]} args The CustomEvent arguments
- * @param {Object} obj The scope object
- */
- handleTweenAnimateOut: function (type, args, obj) { },
- /**
- * The default onComplete handler for the out-animation.
- * @method handleCompleteAnimateOut
- * @param {String} type The CustomEvent type
- * @param {Object[]} args The CustomEvent arguments
- * @param {Object} obj The scope object
- */
- handleCompleteAnimateOut: function (type, args, obj) { },
-
- /**
- * Returns a string representation of the object.
- * @method toString
- * @return {String} The string representation of the ContainerEffect
- */
- toString: function () {
- var output = "ContainerEffect";
- if (this.overlay) {
- output += " [" + this.overlay.toString() + "]";
- }
- return output;
- }
- };
- YAHOO.lang.augmentProto(ContainerEffect, YAHOO.util.EventProvider);
- })();
- YAHOO.register("container", YAHOO.widget.Module, {version: "2.8.0r4", build: "2449"});
|