jindo.min.js 347 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686
  1. /**
  2. * Jindo2 Framework
  3. * @version 1.5.2
  4. * NHN_Library:Jindo-1.5.2;JavaScript Framework;
  5. */
  6. /**
  7. * @fileOverview $와 $Class를 정의한 파일
  8. */
  9. if (typeof window != "undefined" && typeof window.nhn == "undefined") {
  10. window.nhn = {};
  11. }
  12. if (typeof window != "undefined") {
  13. if (typeof window.jindo == "undefined") {
  14. window.jindo = {};
  15. }
  16. } else {
  17. if (!jindo) {
  18. jindo = {};
  19. }
  20. }
  21. /**
  22. * $Jindo 객체를 리턴한다. $Jindo 객체는 프레임웍에 대한 정보와 유틸리티 함수를 제공한다.
  23. * @constructor
  24. * @class $Jindo 객체는 프레임웍에 대한 정보와 유틸리티 함수를 제공한다.
  25. * @description [Lite]
  26. */
  27. jindo.$Jindo = function() {
  28. var cl=arguments.callee;
  29. var cc=cl._cached;
  30. if (cc) return cc;
  31. if (!(this instanceof cl)) return new cl();
  32. if (!cc) cl._cached = this;
  33. this.version = "1.5.2";
  34. }
  35. /**
  36. * @function
  37. * $ 함수는 다음의 두 가지 역할을 한다.
  38. * <ul><li/>ID를 사용하여 HTML 엘리먼트를 가져온다. 매개변수를 두 개 이상 지정하면 HTML 엘리먼트를 원소로하는 배열을 리턴한다.
  39. * <li>또한 "<tagName>" 과 같은 형식의 문자열을 입력하면 tagName을 가지는 객체를 생성한다.</li></ul>
  40. * @param {String...} sID HTML 엘리먼트의 ID. ID는 하나 이상 지정할 수 있다. (1.4.6부터는 마지막 매개변수에 document을 지정할수 있다.)
  41. * @return {Element|Array} HTML 엘리먼트 혹은 HTML 엘리먼트를 원소로 가지는 배열을 리턴한다. 만약 ID에 해당하는 HTML 엘리먼트가 없으면 null을 리턴한다.
  42. * @description [Lite]
  43. * @example
  44. // ID를 이용하여 객체를 리턴한다.
  45. <div id="div1"></div>
  46. var el = $("div1");
  47. // ID를 이용하여 여러개의 객체를 리턴한다.
  48. <div id="div1"></div>
  49. <div id="div2"></div>
  50. var els = $("div1","div2"); // [$("div1"),$("div2")]와 같은 결과를 리턴한다.
  51. // tagName과 같은 형식의 문자열을 이용하여 객체를 생성한다.
  52. var el = $("<DIV>");
  53. var els = $("<DIV id='div1'><SPAN>hello</SPAN></DIV>");
  54. //IE는 iframe에 추가할 엘리먼트를 생성하려고 할 때는 document를 반드시 지정해야 한다.(1.4.6 부터 지원)
  55. var els = $("<div>" , iframe.contentWindow.document);
  56. //위와 같을 경우 div태그가 iframe.contentWindow.document기준으로 생김.
  57. */
  58. jindo.$ = function(sID/*, id1, id2*/) {
  59. var ret = [], arg = arguments, nArgLeng = arg.length, lastArgument = arg[nArgLeng-1],doc = document,el = null;
  60. var reg = /^<([a-z]+|h[1-5])>$/i;
  61. var reg2 = /^<([a-z]+|h[1-5])(\s+[^>]+)?>/i;
  62. if (nArgLeng > 1 && typeof lastArgument != "string" && lastArgument.body) {
  63. /*
  64. 마지막 인자가 document일때.
  65. */
  66. arg = Array.prototype.slice.apply(arg,[0,nArgLeng-1]);
  67. doc = lastArgument;
  68. }
  69. for(var i=0; i < nArgLeng; i++) {
  70. el = arg[i];
  71. if (typeof el == "string") {
  72. el = el.replace(/^\s+|\s+$/g, "");
  73. if (el.indexOf("<")>-1) {
  74. if (reg.test(el)) {
  75. el = doc.createElement(RegExp.$1);
  76. }else if (reg2.test(el)) {
  77. var p = { thead:'table', tbody:'table', tr:'tbody', td:'tr', dt:'dl', dd:'dl', li:'ul', legend:'fieldset',option:"select" };
  78. var tag = RegExp.$1.toLowerCase();
  79. var ele = jindo._createEle(p[tag],el,doc);
  80. for (var i=0,leng = ele.length; i < leng ; i++) {
  81. ret.push(ele[i]);
  82. };
  83. el = null;
  84. }
  85. }else {
  86. el = doc.getElementById(el);
  87. }
  88. }
  89. if (el) ret[ret.length] = el;
  90. }
  91. return ret.length>1?ret:(ret[0] || null);
  92. }
  93. jindo._createEle = function(sParentTag,sHTML,oDoc,bWantParent){
  94. var sId = 'R' + new Date().getTime() + parseInt(Math.random() * 100000,10);
  95. var oDummy = oDoc.createElement("div");
  96. switch (sParentTag) {
  97. case 'select':
  98. case 'table':
  99. case 'dl':
  100. case 'ul':
  101. case 'fieldset':
  102. oDummy.innerHTML = '<' + sParentTag + ' class="' + sId + '">' + sHTML + '</' + sParentTag + '>';
  103. break;
  104. case 'thead':
  105. case 'tbody':
  106. case 'col':
  107. oDummy.innerHTML = '<table><' + sParentTag + ' class="' + sId + '">' + sHTML + '</' + sParentTag + '></table>';
  108. break;
  109. case 'tr':
  110. oDummy.innerHTML = '<table><tbody><tr class="' + sId + '">' + sHTML + '</tr></tbody></table>';
  111. break;
  112. default:
  113. oDummy.innerHTML = '<div class="' + sId + '">' + sHTML + '</div>';
  114. break;
  115. }
  116. var oFound;
  117. for (oFound = oDummy.firstChild; oFound; oFound = oFound.firstChild){
  118. if (oFound.className==sId) break;
  119. }
  120. return bWantParent? oFound : oFound.childNodes;
  121. }
  122. /**
  123. * 클래스 객체를 생성한다.
  124. * @extends core
  125. * @class $Class는 Jindo에서 객체 지향 프로그래밍(OOP)를 구현하는 객체이다. $Class.$init 메소드는 클래스를 생성할 때 클래스 인스턴스에 대한 생성자 함수를 정의한다.
  126. * @param {Object} oDef 클래스를 정의하는 객체. 메서드, 프로퍼티와 생성자를 정의한다. $staic 키워드는 인스턴스를 생성하지 않아도 사용할 수 있는 메서드의 집합이다.
  127. * @return {$Class} 클래스 객체
  128. * @description [Lite]
  129. * @example
  130. var CClass = $Class({
  131. prop : null,
  132. $init : function() {
  133. this.prop = $Ajax();
  134. ...
  135. },
  136. $static : {
  137. static_method : function(){ return 1;}
  138. }
  139. });
  140. var c1 = new CClass();
  141. var c2 = new CClass();
  142. // c1과 c2는 서로 다른 $Ajax 객체를 각각 가진다.
  143. CClass.static_method(); -> 1
  144. */
  145. jindo.$Class = function(oDef) {
  146. function typeClass() {
  147. var t = this;
  148. var a = [];
  149. var superFunc = function(m, superClass, func) {
  150. if(m!='constructor' && func.toString().indexOf("$super")>-1 ){
  151. var funcArg = func.toString().replace(/function\s*\(([^\)]*)[\w\W]*/g,"$1").split(",");
  152. // var funcStr = func.toString().replace(/function\s*\(.*\)\s*\{/,"").replace(/this\.\$super/g,"this.$super.$super");
  153. var funcStr = func.toString().replace(/function[^{]*{/,"").replace(/(\w|\.?)(this\.\$super|this)/g,function(m,m2,m3){
  154. if(!m2){
  155. return m3+".$super"
  156. }
  157. return m;
  158. });
  159. funcStr = funcStr.substr(0,funcStr.length-1);
  160. func = superClass[m] = eval("false||function("+funcArg.join(",")+"){"+funcStr+"}");
  161. }
  162. return function() {
  163. var f = this.$this[m];
  164. var t = this.$this;
  165. var r = (t[m] = func).apply(t, arguments);
  166. t[m] = f;
  167. return r;
  168. };
  169. }
  170. while(typeof t._$superClass != "undefined") {
  171. t.$super = new Object;
  172. t.$super.$this = this;
  173. for(var x in t._$superClass.prototype) {
  174. if (t._$superClass.prototype.hasOwnProperty(x)){
  175. if (typeof this[x] == "undefined" && x !="$init") this[x] = t._$superClass.prototype[x];
  176. if (x!='constructor' && x!='_$superClass' && typeof t._$superClass.prototype[x] == "function") {
  177. t.$super[x] = superFunc(x, t._$superClass, t._$superClass.prototype[x]);
  178. } else {
  179. t.$super[x] = t._$superClass.prototype[x];
  180. }
  181. }
  182. }
  183. if (typeof t.$super.$init == "function") a[a.length] = t;
  184. t = t.$super;
  185. }
  186. for(var i=a.length-1; i > -1; i--) a[i].$super.$init.apply(a[i].$super, arguments);
  187. if (typeof this.$init == "function") this.$init.apply(this,arguments);
  188. }
  189. if (typeof oDef.$static != "undefined") {
  190. var i=0, x;
  191. for(x in oDef){
  192. if (oDef.hasOwnProperty(x)) {
  193. x=="$static"||i++;
  194. }
  195. }
  196. for(x in oDef.$static){
  197. if (oDef.$static.hasOwnProperty(x)) {
  198. typeClass[x] = oDef.$static[x];
  199. }
  200. }
  201. if (!i) return oDef.$static;
  202. delete oDef.$static;
  203. }
  204. // if (typeof oDef.$destroy == "undefined") {
  205. // oDef.$destroy = function(){
  206. // if(this.$super&&(arguments.callee==this.$super.$destroy)){this.$super.$destroy();}
  207. // }
  208. // } else {
  209. // oDef.$destroy = eval("false||"+oDef.$destroy.toString().replace(/\}$/,"console.log(this.$super);console.log(arguments.callee!=this.$super.$destroy);if(this.$super&&(arguments.callee==this.$destroy)){this.$super.$destroy();}}"));
  210. // }
  211. //
  212. typeClass.prototype = oDef;
  213. typeClass.prototype.constructor = typeClass;
  214. typeClass.extend = jindo.$Class.extend;
  215. return typeClass;
  216. }
  217. /**
  218. * 클래스를 상속한다.
  219. * 하위 클래스는 this.$super.method 로 상위 클래스의 메서드에 접근할 수 있으나, this.$super.$super.method 와 같이 한 단계 이상의 상위 클래스는 접근할 수 없다.
  220. * @name $Class#extend
  221. * @type $Class
  222. * @function
  223. * @param {$Class} superClass 수퍼 클래스 객체
  224. * @return {$Class} 상속된 클래스
  225. * @description [Lite]
  226. * @example
  227. var ClassExt = $Class(classDefinition);
  228. ClassExt.extend(superClass);
  229. // ClassExt는 SuperClass를 상속받는다.
  230. */
  231. jindo.$Class.extend = function(superClass) {
  232. // superClass._$has_super = true;
  233. if (typeof superClass == "undefined" || superClass === null || !superClass.extend) {
  234. throw new Error("extend시 슈퍼 클래스는 Class여야 합니다.");
  235. }
  236. this.prototype._$superClass = superClass;
  237. // inherit static methods of parent
  238. for(var x in superClass) {
  239. if (superClass.hasOwnProperty(x)) {
  240. if (x == "prototype") continue;
  241. this[x] = superClass[x];
  242. }
  243. }
  244. return this;
  245. };
  246. /**
  247. 부모 클래스의 메서드에 접근할 때 사용한다. 부모 클래스와 자식 클래스가 같은 이름의 메서드를 가지고 있고 $super로 그 메서드를 호출하면, 자식 클래스의 메서드를 사용한다.
  248. @name $Class#$super
  249. @type $Class
  250. @example
  251. var Parent = $Class ({
  252. a: 100,
  253. b: 200,
  254. c: 300,
  255. sum2: function () {
  256. var init = this.sum();
  257. return init;
  258. },
  259. sum: function () {
  260. return this.a + this.b
  261. }
  262. });
  263. var Child = $Class ({
  264. a: 10,
  265. b: 20,
  266. sum2 : function () {
  267. var init = this.sum();
  268. return init;
  269. },
  270. sum: function () {
  271. return this.b;
  272. }
  273. }).extend (Parent);
  274. var oChild = new Child();
  275. var oParent = new Parent();
  276. oChild.sum(); // 20
  277. oChild.sum2(); // 20
  278. oChild.$super.sum(); // 30 -> 부모 클래스의 100(a)과 200(b)대신 자식 클래스의 10(a)과 20(b)을 더한다.
  279. oChild.$super.sum2(); // 20 -> 부모 클래스의 sum2 메서드에서 부모 클래스의 sum()이 아닌 자식 클래스의 sum()을 호출한다.
  280. */
  281. /**
  282. * @fileOverview CSS 셀렉터를 사용한 엘리먼트 선택 엔진
  283. * @name cssquery.js
  284. * @author Hooriza
  285. */
  286. /**
  287. * CSS 셀렉터를 사용하여 객체를 탐색한다.
  288. *
  289. * @function CSS 셀렉터를 사용하여 객체를 탐색한다.
  290. * @param {String} CSS셀렉터
  291. * @param {Element} 탐색 대상이 되는 요소, 요소의 하위 노드에서만 탐색한다.
  292. * @return {Array} 조건에 해당하는 요소의 배열을 반환한다.
  293. * @description [Lite]
  294. * @example
  295. // 문서에서 IMG 태그를 찾는다.
  296. var imgs = $$('IMG');
  297. // div 요소 하위에서 IMG 태그를 찾는다.
  298. var imgsInDiv = $$('IMG', $('div'));
  299. // 문서에서 IMG 태그 중 가장 첫 요소를 찾는다.
  300. var firstImg = $$.getSingle('IMG');
  301. */
  302. jindo.$$ = jindo.cssquery = (function() {
  303. /*
  304. querySelector 설정.
  305. */
  306. var sVersion = '3.0';
  307. var debugOption = { repeat : 1 };
  308. /*
  309. 빠른 처리를 위해 노드마다 유일키 값 셋팅
  310. */
  311. var UID = 1;
  312. var cost = 0;
  313. var validUID = {};
  314. var bSupportByClassName = document.getElementsByClassName ? true : false;
  315. var safeHTML = false;
  316. var getUID4HTML = function(oEl) {
  317. var nUID = safeHTML ? (oEl._cssquery_UID && oEl._cssquery_UID[0]) : oEl._cssquery_UID;
  318. if (nUID && validUID[nUID] == oEl) return nUID;
  319. nUID = UID++;
  320. oEl._cssquery_UID = safeHTML ? [ nUID ] : nUID;
  321. validUID[nUID] = oEl;
  322. return nUID;
  323. };
  324. var getUID4XML = function(oEl) {
  325. var oAttr = oEl.getAttribute('_cssquery_UID');
  326. var nUID = safeHTML ? (oAttr && oAttr[0]) : oAttr;
  327. if (!nUID) {
  328. nUID = UID++;
  329. oEl.setAttribute('_cssquery_UID', safeHTML ? [ nUID ] : nUID);
  330. }
  331. return nUID;
  332. };
  333. var getUID = getUID4HTML;
  334. var uniqid = function(sPrefix) {
  335. return (sPrefix || '') + new Date().getTime() + parseInt(Math.random() * 100000000,10);
  336. };
  337. function getElementsByClass(searchClass,node,tag) {
  338. var classElements = new Array();
  339. if ( node == null )
  340. node = document;
  341. if ( tag == null )
  342. tag = '*';
  343. var els = node.getElementsByTagName(tag);
  344. var elsLen = els.length;
  345. var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
  346. for (i = 0, j = 0; i < elsLen; i++) {
  347. if ( pattern.test(els[i].className) ) {
  348. classElements[j] = els[i];
  349. j++;
  350. }
  351. }
  352. return classElements;
  353. }
  354. var getChilds_dontShrink = function(oEl, sTagName, sClassName) {
  355. if (bSupportByClassName && sClassName) {
  356. if(oEl.getElementsByClassName)
  357. return oEl.getElementsByClassName(sClassName);
  358. if(oEl.querySelectorAll)
  359. return oEl.querySelectorAll(sClassName);
  360. return getElementsByClass(sClassName, oEl, sTagName);
  361. }else if (sTagName == '*') {
  362. return oEl.all || oEl.getElementsByTagName(sTagName);
  363. }
  364. return oEl.getElementsByTagName(sTagName);
  365. };
  366. var clearKeys = function() {
  367. backupKeys._keys = {};
  368. };
  369. var oDocument_dontShrink = document;
  370. var bXMLDocument = false;
  371. /*
  372. 따옴표, [] 등 파싱에 문제가 될 수 있는 부분 replace 시켜놓기
  373. */
  374. var backupKeys = function(sQuery) {
  375. var oKeys = backupKeys._keys;
  376. /*
  377. 작은 따옴표 걷어내기
  378. */
  379. sQuery = sQuery.replace(/'(\\'|[^'])*'/g, function(sAll) {
  380. var uid = uniqid('QUOT');
  381. oKeys[uid] = sAll;
  382. return uid;
  383. });
  384. /*
  385. 큰 따옴표 걷어내기
  386. */
  387. sQuery = sQuery.replace(/"(\\"|[^"])*"/g, function(sAll) {
  388. var uid = uniqid('QUOT');
  389. oKeys[uid] = sAll;
  390. return uid;
  391. });
  392. /*
  393. [ ] 형태 걷어내기
  394. */
  395. sQuery = sQuery.replace(/\[(.*?)\]/g, function(sAll, sBody) {
  396. if (sBody.indexOf('ATTR') == 0) return sAll;
  397. var uid = '[' + uniqid('ATTR') + ']';
  398. oKeys[uid] = sAll;
  399. return uid;
  400. });
  401. /*
  402. ( ) 형태 걷어내기
  403. */
  404. var bChanged;
  405. do {
  406. bChanged = false;
  407. sQuery = sQuery.replace(/\(((\\\)|[^)|^(])*)\)/g, function(sAll, sBody) {
  408. if (sBody.indexOf('BRCE') == 0) return sAll;
  409. var uid = '_' + uniqid('BRCE');
  410. oKeys[uid] = sAll;
  411. bChanged = true;
  412. return uid;
  413. });
  414. } while(bChanged);
  415. return sQuery;
  416. };
  417. /*
  418. replace 시켜놓은 부분 복구하기
  419. */
  420. var restoreKeys = function(sQuery, bOnlyAttrBrace) {
  421. var oKeys = backupKeys._keys;
  422. var bChanged;
  423. var rRegex = bOnlyAttrBrace ? /(\[ATTR[0-9]+\])/g : /(QUOT[0-9]+|\[ATTR[0-9]+\])/g;
  424. do {
  425. bChanged = false;
  426. sQuery = sQuery.replace(rRegex, function(sKey) {
  427. if (oKeys[sKey]) {
  428. bChanged = true;
  429. return oKeys[sKey];
  430. }
  431. return sKey;
  432. });
  433. } while(bChanged);
  434. /*
  435. ( ) 는 한꺼풀만 벗겨내기
  436. */
  437. sQuery = sQuery.replace(/_BRCE[0-9]+/g, function(sKey) {
  438. return oKeys[sKey] ? oKeys[sKey] : sKey;
  439. });
  440. return sQuery;
  441. };
  442. /*
  443. replace 시켜놓은 문자열에서 Quot 을 제외하고 리턴
  444. */
  445. var restoreString = function(sKey) {
  446. var oKeys = backupKeys._keys;
  447. var sOrg = oKeys[sKey];
  448. if (!sOrg) return sKey;
  449. return eval(sOrg);
  450. };
  451. var wrapQuot = function(sStr) {
  452. return '"' + sStr.replace(/"/g, '\\"') + '"';
  453. };
  454. var getStyleKey = function(sKey) {
  455. if (/^@/.test(sKey)) return sKey.substr(1);
  456. return null;
  457. };
  458. var getCSS = function(oEl, sKey) {
  459. if (oEl.currentStyle) {
  460. if (sKey == "float") sKey = "styleFloat";
  461. return oEl.currentStyle[sKey] || oEl.style[sKey];
  462. } else if (window.getComputedStyle) {
  463. return oDocument_dontShrink.defaultView.getComputedStyle(oEl, null).getPropertyValue(sKey.replace(/([A-Z])/g,"-$1").toLowerCase()) || oEl.style[sKey];
  464. }
  465. if (sKey == "float" && /MSIE/.test(window.navigator.userAgent)) sKey = "styleFloat";
  466. return oEl.style[sKey];
  467. };
  468. var oCamels = {
  469. 'accesskey' : 'accessKey',
  470. 'cellspacing' : 'cellSpacing',
  471. 'cellpadding' : 'cellPadding',
  472. 'class' : 'className',
  473. 'colspan' : 'colSpan',
  474. 'for' : 'htmlFor',
  475. 'maxlength' : 'maxLength',
  476. 'readonly' : 'readOnly',
  477. 'rowspan' : 'rowSpan',
  478. 'tabindex' : 'tabIndex',
  479. 'valign' : 'vAlign'
  480. };
  481. var getDefineCode = function(sKey) {
  482. var sVal;
  483. var sStyleKey;
  484. if (bXMLDocument) {
  485. sVal = 'oEl.getAttribute("' + sKey + '",2)';
  486. } else {
  487. if (sStyleKey = getStyleKey(sKey)) {
  488. sKey = '$$' + sStyleKey;
  489. sVal = 'getCSS(oEl, "' + sStyleKey + '")';
  490. } else {
  491. switch (sKey) {
  492. case 'checked':
  493. sVal = 'oEl.checked + ""';
  494. break;
  495. case 'disabled':
  496. sVal = 'oEl.disabled + ""';
  497. break;
  498. case 'enabled':
  499. sVal = '!oEl.disabled + ""';
  500. break;
  501. case 'readonly':
  502. sVal = 'oEl.readOnly + ""';
  503. break;
  504. case 'selected':
  505. sVal = 'oEl.selected + ""';
  506. break;
  507. default:
  508. if (oCamels[sKey]) {
  509. sVal = 'oEl.' + oCamels[sKey];
  510. } else {
  511. sVal = 'oEl.getAttribute("' + sKey + '",2)';
  512. }
  513. }
  514. }
  515. }
  516. return '_' + sKey + ' = ' + sVal;
  517. };
  518. var getReturnCode = function(oExpr) {
  519. var sStyleKey = getStyleKey(oExpr.key);
  520. var sVar = '_' + (sStyleKey ? '$$' + sStyleKey : oExpr.key);
  521. var sVal = oExpr.val ? wrapQuot(oExpr.val) : '';
  522. switch (oExpr.op) {
  523. case '~=':
  524. return '(' + sVar + ' && (" " + ' + sVar + ' + " ").indexOf(" " + ' + sVal + ' + " ") > -1)';
  525. case '^=':
  526. return '(' + sVar + ' && ' + sVar + '.indexOf(' + sVal + ') == 0)';
  527. case '$=':
  528. return '(' + sVar + ' && ' + sVar + '.substr(' + sVar + '.length - ' + oExpr.val.length + ') == ' + sVal + ')';
  529. case '*=':
  530. return '(' + sVar + ' && ' + sVar + '.indexOf(' + sVal + ') > -1)';
  531. case '!=':
  532. return '(' + sVar + ' != ' + sVal + ')';
  533. case '=':
  534. return '(' + sVar + ' == ' + sVal + ')';
  535. }
  536. return '(' + sVar + ')';
  537. };
  538. var getNodeIndex = function(oEl) {
  539. var nUID = getUID(oEl);
  540. var nIndex = oNodeIndexes[nUID] || 0;
  541. /*
  542. 노드 인덱스를 구할 수 없으면
  543. */
  544. if (nIndex == 0) {
  545. for (var oSib = (oEl.parentNode || oEl._IE5_parentNode).firstChild; oSib; oSib = oSib.nextSibling) {
  546. if (oSib.nodeType != 1){
  547. continue;
  548. }
  549. nIndex++;
  550. setNodeIndex(oSib, nIndex);
  551. }
  552. nIndex = oNodeIndexes[nUID];
  553. }
  554. return nIndex;
  555. };
  556. /*
  557. 몇번째 자식인지 설정하는 부분
  558. */
  559. var oNodeIndexes = {};
  560. var setNodeIndex = function(oEl, nIndex) {
  561. var nUID = getUID(oEl);
  562. oNodeIndexes[nUID] = nIndex;
  563. };
  564. var unsetNodeIndexes = function() {
  565. setTimeout(function() { oNodeIndexes = {}; }, 0);
  566. };
  567. /*
  568. 가상 클래스
  569. */
  570. var oPseudoes_dontShrink = {
  571. 'contains' : function(oEl, sOption) {
  572. return (oEl.innerText || oEl.textContent || '').indexOf(sOption) > -1;
  573. },
  574. 'last-child' : function(oEl, sOption) {
  575. for (oEl = oEl.nextSibling; oEl; oEl = oEl.nextSibling){
  576. if (oEl.nodeType == 1)
  577. return false;
  578. }
  579. return true;
  580. },
  581. 'first-child' : function(oEl, sOption) {
  582. for (oEl = oEl.previousSibling; oEl; oEl = oEl.previousSibling){
  583. if (oEl.nodeType == 1)
  584. return false;
  585. }
  586. return true;
  587. },
  588. 'only-child' : function(oEl, sOption) {
  589. var nChild = 0;
  590. for (var oChild = (oEl.parentNode || oEl._IE5_parentNode).firstChild; oChild; oChild = oChild.nextSibling) {
  591. if (oChild.nodeType == 1) nChild++;
  592. if (nChild > 1) return false;
  593. }
  594. return nChild ? true : false;
  595. },
  596. 'empty' : function(oEl, _) {
  597. return oEl.firstChild ? false : true;
  598. },
  599. 'nth-child' : function(oEl, nMul, nAdd) {
  600. var nIndex = getNodeIndex(oEl);
  601. return nIndex % nMul == nAdd;
  602. },
  603. 'nth-last-child' : function(oEl, nMul, nAdd) {
  604. var oLast = (oEl.parentNode || oEl._IE5_parentNode).lastChild;
  605. for (; oLast; oLast = oLast.previousSibling){
  606. if (oLast.nodeType == 1) break;
  607. }
  608. var nTotal = getNodeIndex(oLast);
  609. var nIndex = getNodeIndex(oEl);
  610. var nLastIndex = nTotal - nIndex + 1;
  611. return nLastIndex % nMul == nAdd;
  612. },
  613. 'checked' : function(oEl){
  614. return !!oEl.checked;
  615. },
  616. 'selected' : function(oEl){
  617. return !!oEl.selected;
  618. },
  619. 'enabled' : function(oEl){
  620. return !oEl.disabled;
  621. },
  622. 'disabled' : function(oEl){
  623. return !!oEl.disabled;
  624. }
  625. };
  626. /*
  627. 단일 part 의 body 에서 expression 뽑아냄
  628. */
  629. var getExpression = function(sBody) {
  630. var oRet = { defines : '', returns : 'true' };
  631. var sBody = restoreKeys(sBody, true);
  632. var aExprs = [];
  633. var aDefineCode = [], aReturnCode = [];
  634. var sId, sTagName;
  635. /*
  636. 유사클래스 조건 얻어내기
  637. */
  638. var sBody = sBody.replace(/:([\w-]+)(\(([^)]*)\))?/g, function(_1, sType, _2, sOption) {
  639. switch (sType) {
  640. case 'not':
  641. /*
  642. 괄호 안에 있는거 재귀파싱하기
  643. */
  644. var oInner = getExpression(sOption);
  645. var sFuncDefines = oInner.defines;
  646. var sFuncReturns = oInner.returnsID + oInner.returnsTAG + oInner.returns;
  647. aReturnCode.push('!(function() { ' + sFuncDefines + ' return ' + sFuncReturns + ' })()');
  648. break;
  649. case 'nth-child':
  650. case 'nth-last-child':
  651. sOption = restoreString(sOption);
  652. if (sOption == 'even'){
  653. sOption = '2n';
  654. }else if (sOption == 'odd') {
  655. sOption = '2n+1';
  656. }
  657. var nMul, nAdd;
  658. var matchstr = sOption.match(/([0-9]*)n([+-][0-9]+)*/);
  659. if (matchstr) {
  660. nMul = matchstr[1] || 1;
  661. nAdd = matchstr[2] || 0;
  662. } else {
  663. nMul = Infinity;
  664. nAdd = parseInt(sOption,10);
  665. }
  666. aReturnCode.push('oPseudoes_dontShrink[' + wrapQuot(sType) + '](oEl, ' + nMul + ', ' + nAdd + ')');
  667. break;
  668. case 'first-of-type':
  669. case 'last-of-type':
  670. sType = (sType == 'first-of-type' ? 'nth-of-type' : 'nth-last-of-type');
  671. sOption = 1;
  672. case 'nth-of-type':
  673. case 'nth-last-of-type':
  674. sOption = restoreString(sOption);
  675. if (sOption == 'even') {
  676. sOption = '2n';
  677. }else if (sOption == 'odd'){
  678. sOption = '2n+1';
  679. }
  680. var nMul, nAdd;
  681. if (/([0-9]*)n([+-][0-9]+)*/.test(sOption)) {
  682. nMul = parseInt(RegExp.$1,10) || 1;
  683. nAdd = parseInt(RegExp.$2,20) || 0;
  684. } else {
  685. nMul = Infinity;
  686. nAdd = parseInt(sOption,10);
  687. }
  688. oRet.nth = [ nMul, nAdd, sType ];
  689. break;
  690. default:
  691. sOption = sOption ? restoreString(sOption) : '';
  692. aReturnCode.push('oPseudoes_dontShrink[' + wrapQuot(sType) + '](oEl, ' + wrapQuot(sOption) + ')');
  693. break;
  694. }
  695. return '';
  696. });
  697. /*
  698. [key=value] 형태 조건 얻어내기
  699. */
  700. var sBody = sBody.replace(/\[(@?[\w-]+)(([!^~$*]?=)([^\]]*))?\]/g, function(_1, sKey, _2, sOp, sVal) {
  701. sKey = restoreString(sKey);
  702. sVal = restoreString(sVal);
  703. if (sKey == 'checked' || sKey == 'disabled' || sKey == 'enabled' || sKey == 'readonly' || sKey == 'selected') {
  704. if (!sVal) {
  705. sOp = '=';
  706. sVal = 'true';
  707. }
  708. }
  709. aExprs.push({ key : sKey, op : sOp, val : sVal });
  710. return '';
  711. });
  712. var sClassName = null;
  713. /*
  714. 클래스 조건 얻어내기
  715. */
  716. var sBody = sBody.replace(/\.([\w-]+)/g, function(_, sClass) {
  717. aExprs.push({ key : 'class', op : '~=', val : sClass });
  718. if (!sClassName) sClassName = sClass;
  719. return '';
  720. });
  721. /*
  722. id 조건 얻어내기
  723. */
  724. var sBody = sBody.replace(/#([\w-]+)/g, function(_, sIdValue) {
  725. if (bXMLDocument) {
  726. aExprs.push({ key : 'id', op : '=', val : sIdValue });
  727. }else{
  728. sId = sIdValue;
  729. }
  730. return '';
  731. });
  732. sTagName = sBody == '*' ? '' : sBody;
  733. /*
  734. match 함수 코드 만들어 내기
  735. */
  736. var oVars = {};
  737. for (var i = 0, oExpr; oExpr = aExprs[i]; i++) {
  738. var sKey = oExpr.key;
  739. if (!oVars[sKey]) aDefineCode.push(getDefineCode(sKey));
  740. /*
  741. 유사클래스 조건 검사가 맨 뒤로 가도록 unshift 사용
  742. */
  743. aReturnCode.unshift(getReturnCode(oExpr));
  744. oVars[sKey] = true;
  745. }
  746. if (aDefineCode.length) oRet.defines = 'var ' + aDefineCode.join(',') + ';';
  747. if (aReturnCode.length) oRet.returns = aReturnCode.join('&&');
  748. oRet.quotID = sId ? wrapQuot(sId) : '';
  749. oRet.quotTAG = sTagName ? wrapQuot(bXMLDocument ? sTagName : sTagName.toUpperCase()) : '';
  750. if (bSupportByClassName) oRet.quotCLASS = sClassName ? wrapQuot(sClassName) : '';
  751. oRet.returnsID = sId ? 'oEl.id == ' + oRet.quotID + ' && ' : '';
  752. oRet.returnsTAG = sTagName && sTagName != '*' ? 'oEl.tagName == ' + oRet.quotTAG + ' && ' : '';
  753. return oRet;
  754. };
  755. /*
  756. 쿼리를 연산자 기준으로 잘라냄
  757. */
  758. var splitToParts = function(sQuery) {
  759. var aParts = [];
  760. var sRel = ' ';
  761. var sBody = sQuery.replace(/(.*?)\s*(!?[+>~ ]|!)\s*/g, function(_, sBody, sRelative) {
  762. if (sBody) aParts.push({ rel : sRel, body : sBody });
  763. sRel = sRelative.replace(/\s+$/g, '') || ' ';
  764. return '';
  765. });
  766. if (sBody) aParts.push({ rel : sRel, body : sBody });
  767. return aParts;
  768. };
  769. var isNth_dontShrink = function(oEl, sTagName, nMul, nAdd, sDirection) {
  770. var nIndex = 0;
  771. for (var oSib = oEl; oSib; oSib = oSib[sDirection]){
  772. if (oSib.nodeType == 1 && (!sTagName || sTagName == oSib.tagName))
  773. nIndex++;
  774. }
  775. return nIndex % nMul == nAdd;
  776. };
  777. /*
  778. 잘라낸 part 를 함수로 컴파일 하기
  779. */
  780. var compileParts = function(aParts) {
  781. var aPartExprs = [];
  782. /*
  783. 잘라낸 부분들 조건 만들기
  784. */
  785. for (var i = 0, oPart; oPart = aParts[i]; i++)
  786. aPartExprs.push(getExpression(oPart.body));
  787. //////////////////// BEGIN
  788. var sFunc = '';
  789. var sPushCode = 'aRet.push(oEl); if (oOptions.single) { bStop = true; }';
  790. for (var i = aParts.length - 1, oPart; oPart = aParts[i]; i--) {
  791. var oExpr = aPartExprs[i];
  792. var sPush = (debugOption.callback ? 'cost++;' : '') + oExpr.defines;
  793. var sReturn = 'if (bStop) {' + (i == 0 ? 'return aRet;' : 'return;') + '}';
  794. if (oExpr.returns == 'true') {
  795. sPush += (sFunc ? sFunc + '(oEl);' : sPushCode) + sReturn;
  796. }else{
  797. sPush += 'if (' + oExpr.returns + ') {' + (sFunc ? sFunc + '(oEl);' : sPushCode ) + sReturn + '}';
  798. }
  799. var sCheckTag = 'oEl.nodeType != 1';
  800. if (oExpr.quotTAG) sCheckTag = 'oEl.tagName != ' + oExpr.quotTAG;
  801. var sTmpFunc =
  802. '(function(oBase' +
  803. (i == 0 ? ', oOptions) { var bStop = false; var aRet = [];' : ') {');
  804. if (oExpr.nth) {
  805. sPush =
  806. 'if (isNth_dontShrink(oEl, ' +
  807. (oExpr.quotTAG ? oExpr.quotTAG : 'false') + ',' +
  808. oExpr.nth[0] + ',' +
  809. oExpr.nth[1] + ',' +
  810. '"' + (oExpr.nth[2] == 'nth-of-type' ? 'previousSibling' : 'nextSibling') + '")) {' + sPush + '}';
  811. }
  812. switch (oPart.rel) {
  813. case ' ':
  814. if (oExpr.quotID) {
  815. sTmpFunc +=
  816. 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
  817. 'var oCandi = oEl;' +
  818. 'for (; oCandi; oCandi = (oCandi.parentNode || oCandi._IE5_parentNode)) {' +
  819. 'if (oCandi == oBase) break;' +
  820. '}' +
  821. 'if (!oCandi || ' + sCheckTag + ') return aRet;' +
  822. sPush;
  823. } else {
  824. sTmpFunc +=
  825. 'var aCandi = getChilds_dontShrink(oBase, ' + (oExpr.quotTAG || '"*"') + ', ' + (oExpr.quotCLASS || 'null') + ');' +
  826. 'for (var i = 0, oEl; oEl = aCandi[i]; i++) {' +
  827. (oExpr.quotCLASS ? 'if (' + sCheckTag + ') continue;' : '') +
  828. sPush +
  829. '}';
  830. }
  831. break;
  832. case '>':
  833. if (oExpr.quotID) {
  834. sTmpFunc +=
  835. 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
  836. 'if ((oEl.parentNode || oEl._IE5_parentNode) != oBase || ' + sCheckTag + ') return aRet;' +
  837. sPush;
  838. } else {
  839. sTmpFunc +=
  840. 'for (var oEl = oBase.firstChild; oEl; oEl = oEl.nextSibling) {' +
  841. 'if (' + sCheckTag + ') { continue; }' +
  842. sPush +
  843. '}';
  844. }
  845. break;
  846. case '+':
  847. if (oExpr.quotID) {
  848. sTmpFunc +=
  849. 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
  850. 'var oPrev;' +
  851. 'for (oPrev = oEl.previousSibling; oPrev; oPrev = oPrev.previousSibling) { if (oPrev.nodeType == 1) break; }' +
  852. 'if (!oPrev || oPrev != oBase || ' + sCheckTag + ') return aRet;' +
  853. sPush;
  854. } else {
  855. sTmpFunc +=
  856. 'for (var oEl = oBase.nextSibling; oEl; oEl = oEl.nextSibling) { if (oEl.nodeType == 1) break; }' +
  857. 'if (!oEl || ' + sCheckTag + ') { return aRet; }' +
  858. sPush;
  859. }
  860. break;
  861. case '~':
  862. if (oExpr.quotID) {
  863. sTmpFunc +=
  864. 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
  865. 'var oCandi = oEl;' +
  866. 'for (; oCandi; oCandi = oCandi.previousSibling) { if (oCandi == oBase) break; }' +
  867. 'if (!oCandi || ' + sCheckTag + ') return aRet;' +
  868. sPush;
  869. } else {
  870. sTmpFunc +=
  871. 'for (var oEl = oBase.nextSibling; oEl; oEl = oEl.nextSibling) {' +
  872. 'if (' + sCheckTag + ') { continue; }' +
  873. 'if (!markElement_dontShrink(oEl, ' + i + ')) { break; }' +
  874. sPush +
  875. '}';
  876. }
  877. break;
  878. case '!' :
  879. if (oExpr.quotID) {
  880. sTmpFunc +=
  881. 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
  882. 'for (; oBase; oBase = (oBase.parentNode || oBase._IE5_parentNode)) { if (oBase == oEl) break; }' +
  883. 'if (!oBase || ' + sCheckTag + ') return aRet;' +
  884. sPush;
  885. } else {
  886. sTmpFunc +=
  887. 'for (var oEl = (oBase.parentNode || oBase._IE5_parentNode); oEl; oEl = (oEl.parentNode || oEl._IE5_parentNode)) {'+
  888. 'if (' + sCheckTag + ') { continue; }' +
  889. sPush +
  890. '}';
  891. }
  892. break;
  893. case '!>' :
  894. if (oExpr.quotID) {
  895. sTmpFunc +=
  896. 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
  897. 'var oRel = (oBase.parentNode || oBase._IE5_parentNode);' +
  898. 'if (!oRel || oEl != oRel || (' + sCheckTag + ')) return aRet;' +
  899. sPush;
  900. } else {
  901. sTmpFunc +=
  902. 'var oEl = (oBase.parentNode || oBase._IE5_parentNode);' +
  903. 'if (!oEl || ' + sCheckTag + ') { return aRet; }' +
  904. sPush;
  905. }
  906. break;
  907. case '!+' :
  908. if (oExpr.quotID) {
  909. sTmpFunc +=
  910. 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
  911. 'var oRel;' +
  912. 'for (oRel = oBase.previousSibling; oRel; oRel = oRel.previousSibling) { if (oRel.nodeType == 1) break; }' +
  913. 'if (!oRel || oEl != oRel || (' + sCheckTag + ')) return aRet;' +
  914. sPush;
  915. } else {
  916. sTmpFunc +=
  917. 'for (oEl = oBase.previousSibling; oEl; oEl = oEl.previousSibling) { if (oEl.nodeType == 1) break; }' +
  918. 'if (!oEl || ' + sCheckTag + ') { return aRet; }' +
  919. sPush;
  920. }
  921. break;
  922. case '!~' :
  923. if (oExpr.quotID) {
  924. sTmpFunc +=
  925. 'var oEl = oDocument_dontShrink.getElementById(' + oExpr.quotID + ');' +
  926. 'var oRel;' +
  927. 'for (oRel = oBase.previousSibling; oRel; oRel = oRel.previousSibling) { ' +
  928. 'if (oRel.nodeType != 1) { continue; }' +
  929. 'if (oRel == oEl) { break; }' +
  930. '}' +
  931. 'if (!oRel || (' + sCheckTag + ')) return aRet;' +
  932. sPush;
  933. } else {
  934. sTmpFunc +=
  935. 'for (oEl = oBase.previousSibling; oEl; oEl = oEl.previousSibling) {' +
  936. 'if (' + sCheckTag + ') { continue; }' +
  937. 'if (!markElement_dontShrink(oEl, ' + i + ')) { break; }' +
  938. sPush +
  939. '}';
  940. }
  941. break;
  942. }
  943. sTmpFunc +=
  944. (i == 0 ? 'return aRet;' : '') +
  945. '})';
  946. sFunc = sTmpFunc;
  947. }
  948. eval('var fpCompiled = ' + sFunc + ';');
  949. return fpCompiled;
  950. };
  951. /*
  952. 쿼리를 match 함수로 변환
  953. */
  954. var parseQuery = function(sQuery) {
  955. var sCacheKey = sQuery;
  956. var fpSelf = arguments.callee;
  957. var fpFunction = fpSelf._cache[sCacheKey];
  958. if (!fpFunction) {
  959. sQuery = backupKeys(sQuery);
  960. var aParts = splitToParts(sQuery);
  961. fpFunction = fpSelf._cache[sCacheKey] = compileParts(aParts);
  962. fpFunction.depth = aParts.length;
  963. }
  964. return fpFunction;
  965. };
  966. parseQuery._cache = {};
  967. /*
  968. test 쿼리를 match 함수로 변환
  969. */
  970. var parseTestQuery = function(sQuery) {
  971. var fpSelf = arguments.callee;
  972. var aSplitQuery = backupKeys(sQuery).split(/\s*,\s*/);
  973. var aResult = [];
  974. var nLen = aSplitQuery.length;
  975. var aFunc = [];
  976. for (var i = 0; i < nLen; i++) {
  977. aFunc.push((function(sQuery) {
  978. var sCacheKey = sQuery;
  979. var fpFunction = fpSelf._cache[sCacheKey];
  980. if (!fpFunction) {
  981. sQuery = backupKeys(sQuery);
  982. var oExpr = getExpression(sQuery);
  983. eval('fpFunction = function(oEl) { ' + oExpr.defines + 'return (' + oExpr.returnsID + oExpr.returnsTAG + oExpr.returns + '); };');
  984. }
  985. return fpFunction;
  986. })(restoreKeys(aSplitQuery[i])));
  987. }
  988. return aFunc;
  989. };
  990. parseTestQuery._cache = {};
  991. var distinct = function(aList) {
  992. var aDistinct = [];
  993. var oDummy = {};
  994. for (var i = 0, oEl; oEl = aList[i]; i++) {
  995. var nUID = getUID(oEl);
  996. if (oDummy[nUID]) continue;
  997. aDistinct.push(oEl);
  998. oDummy[nUID] = true;
  999. }
  1000. return aDistinct;
  1001. };
  1002. var markElement_dontShrink = function(oEl, nDepth) {
  1003. var nUID = getUID(oEl);
  1004. if (cssquery._marked[nDepth][nUID]) return false;
  1005. cssquery._marked[nDepth][nUID] = true;
  1006. return true;
  1007. };
  1008. var oResultCache = null;
  1009. var bUseResultCache = false;
  1010. var bExtremeMode = false;
  1011. var old_cssquery = function(sQuery, oParent, oOptions) {
  1012. if (typeof sQuery == 'object') {
  1013. var oResult = {};
  1014. for (var k in sQuery){
  1015. if(sQuery.hasOwnProperty(k))
  1016. oResult[k] = arguments.callee(sQuery[k], oParent, oOptions);
  1017. }
  1018. return oResult;
  1019. }
  1020. cost = 0;
  1021. var executeTime = new Date().getTime();
  1022. var aRet;
  1023. for (var r = 0, rp = debugOption.repeat; r < rp; r++) {
  1024. aRet = (function(sQuery, oParent, oOptions) {
  1025. if(oOptions){
  1026. if(!oOptions.oneTimeOffCache){
  1027. oOptions.oneTimeOffCache = false;
  1028. }
  1029. }else{
  1030. oOptions = {oneTimeOffCache:false};
  1031. }
  1032. cssquery.safeHTML(oOptions.oneTimeOffCache);
  1033. if (!oParent) oParent = document;
  1034. /*
  1035. ownerDocument 잡아주기
  1036. */
  1037. oDocument_dontShrink = oParent.ownerDocument || oParent.document || oParent;
  1038. /*
  1039. 브라우저 버젼이 IE5.5 이하
  1040. */
  1041. if (/\bMSIE\s([0-9]+(\.[0-9]+)*);/.test(navigator.userAgent) && parseFloat(RegExp.$1) < 6) {
  1042. try { oDocument_dontShrink.location; } catch(e) { oDocument_dontShrink = document; }
  1043. oDocument_dontShrink.firstChild = oDocument_dontShrink.getElementsByTagName('html')[0];
  1044. oDocument_dontShrink.firstChild._IE5_parentNode = oDocument_dontShrink;
  1045. }
  1046. /*
  1047. XMLDocument 인지 체크
  1048. */
  1049. bXMLDocument = (typeof XMLDocument != 'undefined') ? (oDocument_dontShrink.constructor === XMLDocument) : (!oDocument_dontShrink.location);
  1050. getUID = bXMLDocument ? getUID4XML : getUID4HTML;
  1051. clearKeys();
  1052. /*
  1053. 쿼리를 쉼표로 나누기
  1054. */
  1055. var aSplitQuery = backupKeys(sQuery).split(/\s*,\s*/);
  1056. var aResult = [];
  1057. var nLen = aSplitQuery.length;
  1058. for (var i = 0; i < nLen; i++)
  1059. aSplitQuery[i] = restoreKeys(aSplitQuery[i]);
  1060. /*
  1061. 쉼표로 나눠진 쿼리 루프
  1062. */
  1063. for (var i = 0; i < nLen; i++) {
  1064. var sSingleQuery = aSplitQuery[i];
  1065. var aSingleQueryResult = null;
  1066. var sResultCacheKey = sSingleQuery + (oOptions.single ? '_single' : '');
  1067. /*
  1068. 결과 캐쉬 뒤짐
  1069. */
  1070. var aCache = bUseResultCache ? oResultCache[sResultCacheKey] : null;
  1071. if (aCache) {
  1072. /*
  1073. 캐싱되어 있는게 있으면 parent 가 같은건지 검사한후 aSingleQueryResult 에 대입
  1074. */
  1075. for (var j = 0, oCache; oCache = aCache[j]; j++) {
  1076. if (oCache.parent == oParent) {
  1077. aSingleQueryResult = oCache.result;
  1078. break;
  1079. }
  1080. }
  1081. }
  1082. if (!aSingleQueryResult) {
  1083. var fpFunction = parseQuery(sSingleQuery);
  1084. // alert(fpFunction);
  1085. cssquery._marked = [];
  1086. for (var j = 0, nDepth = fpFunction.depth; j < nDepth; j++)
  1087. cssquery._marked.push({});
  1088. // console.log(fpFunction.toSource());
  1089. aSingleQueryResult = distinct(fpFunction(oParent, oOptions));
  1090. /*
  1091. 결과 캐쉬를 사용중이면 캐쉬에 저장
  1092. */
  1093. if (bUseResultCache&&!oOptions.oneTimeOffCache) {
  1094. if (!(oResultCache[sResultCacheKey] instanceof Array)) oResultCache[sResultCacheKey] = [];
  1095. oResultCache[sResultCacheKey].push({ parent : oParent, result : aSingleQueryResult });
  1096. }
  1097. }
  1098. aResult = aResult.concat(aSingleQueryResult);
  1099. }
  1100. unsetNodeIndexes();
  1101. return aResult;
  1102. })(sQuery, oParent, oOptions);
  1103. }
  1104. executeTime = new Date().getTime() - executeTime;
  1105. if (debugOption.callback) debugOption.callback(sQuery, cost, executeTime);
  1106. return aRet;
  1107. };
  1108. var cssquery;
  1109. if (document.querySelectorAll) {
  1110. function _isNonStandardQueryButNotException(sQuery){
  1111. return /\[\s*(?:checked|selected|disabled)/.test(sQuery)
  1112. }
  1113. function _commaRevise (sQuery,sChange) {
  1114. return sQuery.replace(/\,/gi,sChange);
  1115. }
  1116. var protoSlice = Array.prototype.slice;
  1117. var _toArray = function(aArray){
  1118. return protoSlice.apply(aArray);
  1119. }
  1120. try{
  1121. protoSlice.apply(document.documentElement.childNodes);
  1122. }catch(e){
  1123. _toArray = function(aArray){
  1124. var returnArray = [];
  1125. var leng = aArray.length;
  1126. for ( var i = 0; i < leng; i++ ) {
  1127. returnArray.push( aArray[i] );
  1128. }
  1129. return returnArray;
  1130. }
  1131. }
  1132. /**
  1133. */
  1134. cssquery = function(sQuery, oParent, oOptions){
  1135. oParent = oParent || document ;
  1136. try{
  1137. if (_isNonStandardQueryButNotException(sQuery)) {
  1138. throw Error("None Standard Query");
  1139. }else{
  1140. var sReviseQuery = sQuery;
  1141. var oReviseParent = oParent;
  1142. if (oParent.nodeType != 9) {
  1143. if(bExtremeMode){
  1144. if(!oParent.id) oParent.id = "p"+ new Date().getTime() + parseInt(Math.random() * 100000000,10);
  1145. }else{
  1146. throw Error("Parent Element has not ID.or It is not document.or None Extreme Mode.");
  1147. }
  1148. sReviseQuery = _commaRevise("#"+oParent.id+" "+sQuery,", #"+oParent.id);
  1149. oReviseParent = oParent.ownerDocument||oParent.document||document;
  1150. }
  1151. if (oOptions&&oOptions.single) {
  1152. return [oReviseParent.querySelector(sReviseQuery)];
  1153. }else{
  1154. return _toArray(oReviseParent.querySelectorAll(sReviseQuery));
  1155. }
  1156. }
  1157. }catch(e){
  1158. return old_cssquery(sQuery, oParent, oOptions);
  1159. }
  1160. }
  1161. }else{
  1162. cssquery = old_cssquery;
  1163. }
  1164. /**
  1165. * 특정 엘리먼트가 해당 CSS 셀렉터에 부합하는 엘리먼트인지 판단한다
  1166. * @remark CSS 셀렉터에 연결자는 사용할 수 없음에 유의한다.
  1167. * @param {Element} element 검사하고자 하는 엘리먼트
  1168. * @param {String} selector CSS 셀렉터
  1169. * @return {Boolean} 셀렉터 조건에 부합하면 true, 부합하지 않으면 false
  1170. * @example
  1171. // oEl 이 div 태그 또는 p 태그, 또는 align=center 인 엘리먼트인지
  1172. if (cssquery.test(oEl, 'div, p, [align=center]')) alert('해당 조건 만족');// oEl 이 div 태그 또는 p 태그, 또는 align=center 인 엘리먼트인지
  1173. if (cssquery.test(oEl, 'div, p, [align=center]')) alert('해당 조건 만족');
  1174. */
  1175. cssquery.test = function(oEl, sQuery) {
  1176. clearKeys();
  1177. var aFunc = parseTestQuery(sQuery);
  1178. for (var i = 0, nLen = aFunc.length; i < nLen; i++){
  1179. if (aFunc[i](oEl)) return true;
  1180. }
  1181. return false;
  1182. };
  1183. /**
  1184. * cssquery 에 결과 캐쉬를 사용할 것인지 지정하거나 확인한다.
  1185. * @remark 결과 캐쉬를 사용하면 동일한 셀렉터를 사용했을 경우 새로 탐색을 하지 않고 기존 탐색 결과를 그대로 반환하기 때문에 사용자가 변수 캐쉬에 신경쓰지 않고 편하고 빠르게 쓸 수 있는 장점이 있지만 결과의 신뢰성을 위해 DOM 에 변화가 없다는 것이 확실할때만 사용해야 한다.
  1186. * @param {Boolean} flag 사용할 것 인지 여부 (생략시 사용 여부만 반환)
  1187. * @return {Boolean} 결과 캐쉬를 사용하는지 여부
  1188. */
  1189. cssquery.useCache = function(bFlag) {
  1190. if (typeof bFlag != 'undefined') {
  1191. bUseResultCache = bFlag;
  1192. cssquery.clearCache();
  1193. }
  1194. return bUseResultCache;
  1195. };
  1196. /**
  1197. * 결과 캐쉬를 사용 중에 DOM 의 변화가 생기는 등의 이유로 캐쉬를 모두 비워주고 싶을때 사용한다.
  1198. * @return {Void} 반환값 없음
  1199. */
  1200. cssquery.clearCache = function() {
  1201. oResultCache = {};
  1202. };
  1203. /**
  1204. * CSS 셀렉터를 사용하여 DOM 에서 원하는 엘리먼트를 하나만 얻어낸다. 반환하는 값은 배열이 아닌 객체 또는 null 이다.
  1205. * @remark 결과를 하나만 얻어내면 이후의 모든 탐색 작업을 중단하기 때문에 결과가 하나라는 보장이 있을때 빠른 속도로 결과를 얻어올 수 있다.
  1206. * @param {String} selector CSS 셀렉터
  1207. * @param {Document | Element} el 탐색을 진행하는 기준이 되는 엘리먼트 또는 문서 (생략시 현재 문서의 document 객체)
  1208. * @param {Object} 오브젝트에 onTimeOffCache를 true로 하면 해당 쿼리는 cache를 사용하지 않는다.
  1209. * @return {Element} 선택된 엘리먼트
  1210. */
  1211. cssquery.getSingle = function(sQuery, oParent, oOptions) {
  1212. return cssquery(sQuery, oParent, { single : true ,oneTimeOffCache:oOptions?(!!oOptions.oneTimeOffCache):false})[0] || null;
  1213. };
  1214. /**
  1215. * XPath 문법을 사용하여 엘리먼트를 얻어온다.
  1216. * @remark 지원하는 문법이 무척 제한적으로 특수한 경우에서만 사용하는 것을 권장한다.
  1217. * @param {String} xpath XPath
  1218. * @param {Document | Element} el 탐색을 진행하는 기준이 되는 엘리먼트 또는 문서 (생략시 현재 문서의 document 객체)
  1219. * @return {Array} 선택된 엘리먼트 목록의 배열
  1220. */
  1221. cssquery.xpath = function(sXPath, oParent) {
  1222. var sXPath = sXPath.replace(/\/(\w+)(\[([0-9]+)\])?/g, function(_1, sTag, _2, sTh) {
  1223. sTh = sTh || '1';
  1224. return '>' + sTag + ':nth-of-type(' + sTh + ')';
  1225. });
  1226. return old_cssquery(sXPath, oParent);
  1227. };
  1228. /**
  1229. * cssquery 를 사용할 때의 성능을 측정하기 위한 방법을 제공하는 함수이다.
  1230. * @param {Function} callback 셀렉터 실행에 소요된 비용과 시간을 받아들이는 함수 (false 인 경우 debug 옵션을 끔)
  1231. * @param {Number} repeat 하나의 셀렉터를 반복하여 수행하도록 해서 인위적으로 실행 속도를 늦춤
  1232. * @remark callback 함수의 형태는 아래와 같습니다.
  1233. * callback : function({String}query, {Number}cost, {Number}executeTime)
  1234. * <dl>
  1235. * <dt>query</dt>
  1236. * <dd>실행에 사용된 셀렉터</dd>
  1237. * <dt>cost</dt>
  1238. * <dd>탐색에 사용된 비용 (루프 횟수)</dd>
  1239. * <dt>executeTime</dt>
  1240. * <dd>탐색에 소요된 시간</dd>
  1241. * </dl>
  1242. * @return {Void} 반환값 없음
  1243. * @example
  1244. cssquery.debug(function(sQuery, nCost, nExecuteTime) {
  1245. if (nCost > 5000)
  1246. console.warn('5000 이 넘는 비용이?! 체크해보자 -> ' + sQuery + '/' + nCost);
  1247. else if (nExecuteTime > 200)
  1248. console.warn('0.2초가 넘게 실행을?! 체크해보자 -> ' + sQuery + '/' + nExecuteTime);
  1249. }, 20);
  1250. ....
  1251. cssquery.debug(false);
  1252. */
  1253. cssquery.debug = function(fpCallback, nRepeat) {
  1254. debugOption.callback = fpCallback;
  1255. debugOption.repeat = nRepeat || 1;
  1256. };
  1257. /**
  1258. * IE 에서 innerHTML 을 쓸때 _cssquery_UID 나오지 않도록 하는 함수이다.
  1259. * true 로 설정하면 그때부터 탐색하는 노드에 대해서는 innerHTML 에 _cssquery_UID 가 나오지 않도록 하지만 탐색속도는 다소 느려질 수 있다.
  1260. * @param {Boolean} flag true 로 셋팅하면 _cssquery_UID 가 나오지 않음
  1261. * @return {Boolean} _cssquery_UID 가 나오지 않는 상태이면 true 반환
  1262. */
  1263. cssquery.safeHTML = function(bFlag) {
  1264. var bIE = /MSIE/.test(window.navigator.userAgent);
  1265. if (arguments.length > 0)
  1266. safeHTML = bFlag && bIE;
  1267. return safeHTML || !bIE;
  1268. };
  1269. /**
  1270. * cssquery 의 버젼정보를 담고 있는 문자열이다.
  1271. */
  1272. cssquery.version = sVersion;
  1273. /**
  1274. * IE에서 validUID,cache를 사용했을때 메모리 닉이 발생하여 삭제하는 모듈 추가.
  1275. */
  1276. cssquery.release = function() {
  1277. if(/MSIE/.test(window.navigator.userAgent)){
  1278. delete validUID;
  1279. validUID = {};
  1280. if(bUseResultCache){
  1281. cssquery.clearCache();
  1282. }
  1283. }
  1284. };
  1285. /**
  1286. * cache가 삭제가 되는지 확인하기 위해 필요한 함수
  1287. * @ignore
  1288. */
  1289. cssquery._getCacheInfo = function(){
  1290. return {
  1291. uidCache : validUID,
  1292. eleCache : oResultCache
  1293. }
  1294. }
  1295. /**
  1296. * 테스트를 위해 필요한 함수
  1297. * @ignore
  1298. */
  1299. cssquery._resetUID = function(){
  1300. UID = 0
  1301. }
  1302. /**
  1303. * querySelector가 있는 브라우져에서 extreme을 실행시키면 querySelector을 사용할수 있는 커버리지가 높아져 전체적으로 속도가 빨리진다.
  1304. * 하지만 ID가 없는 엘리먼트를 기준 엘리먼트로 넣었을 때 기준 엘리먼트에 임의의 아이디가 들어간다.
  1305. * @param {Boolean} bExtreme true
  1306. */
  1307. cssquery.extreme = function(bExtreme){
  1308. if(arguments.length == 0){
  1309. bExtreme = true;
  1310. }
  1311. bExtremeMode = bExtreme;
  1312. }
  1313. return cssquery;
  1314. })();
  1315. /**
  1316. * @fileOverview $Agent의 생성자 및 메서드를 정의한 파일
  1317. */
  1318. /**
  1319. * Agent 객체를 반환한다. Agent 객체는 브라우저와 OS에 대한 정보를 가진다.
  1320. * @class Agent 객체는 운영체제, 브라우저를 비롯한 사용자 시스템의 정보를 가진다.
  1321. * @constructor
  1322. * @author Kim, Taegon
  1323. */
  1324. jindo.$Agent = function() {
  1325. var cl = arguments.callee;
  1326. var cc = cl._cached;
  1327. if (cc) return cc;
  1328. if (!(this instanceof cl)) return new cl;
  1329. if (!cc) cl._cached = this;
  1330. this._navigator = navigator;
  1331. }
  1332. /**
  1333. * navigator 메서드는 웹 브라우저의 정보 객체를 리턴한다.
  1334. * @return {Object} 웹 브라우저 정보를 저장하는 객체. <br>
  1335. * object는 브라우저 이름과 버전을 속성으로 가진다. 브라우저 이름은 영어 소문자로 표시하며, 사용자의 브라우저와 일치하는 브라우저 이름은 true를 가진다.
  1336. * @since 1.4.3 부터 mobile,msafari,mopera,mie 사용 가능.
  1337. * @since 1.4.5 부터 ipad에서 mobile은 false를 반환 한다.
  1338. * @example
  1339. oAgent = $Agent().navigator(); // 사용자가 파이어폭스 3를 사용한다고 가정한다.
  1340. oAgent.camino // false
  1341. oAgent.firefox // true
  1342. oAgent.konqueror // false
  1343. oAgent.mozilla //true
  1344. oAgent.netscape // false
  1345. oAgent.omniweb //false
  1346. oAgent.opera //false
  1347. oAgent.webkit /false
  1348. oAgent.safari //false
  1349. oAgent.ie //false
  1350. oAgent.chrome //false
  1351. oAgent.icab //false
  1352. oAgent.version //3
  1353. oAgent.nativeVersion //-1 (1.4.2부터 사용 가능, IE8에서 호환 모드 사용시 nativeVersion은 8로 나옴.)
  1354. oAgent.getName() // firefox
  1355. */
  1356. jindo.$Agent.prototype.navigator = function() {
  1357. var info = new Object;
  1358. var ver = -1;
  1359. var nativeVersion = -1;
  1360. var u = this._navigator.userAgent;
  1361. var v = this._navigator.vendor || "";
  1362. function f(s,h){ return ((h||"").indexOf(s) > -1) };
  1363. info.getName = function(){
  1364. var name = "";
  1365. for(x in info){
  1366. if(typeof info[x] == "boolean" && info[x]&&info.hasOwnProperty(x))
  1367. name = x;
  1368. }
  1369. return name;
  1370. }
  1371. info.webkit = f("WebKit",u);
  1372. info.opera = (typeof window.opera != "undefined") || f("Opera",u);
  1373. info.ie = !info.opera && f("MSIE",u);
  1374. info.chrome = info.webkit && f("Chrome",u);
  1375. info.safari = info.webkit && !info.chrome && f("Apple",v);
  1376. info.firefox = f("Firefox",u);
  1377. info.mozilla = f("Gecko",u) && !info.safari && !info.chrome && !info.firefox;
  1378. info.camino = f("Camino",v);
  1379. info.netscape = f("Netscape",u);
  1380. info.omniweb = f("OmniWeb",u);
  1381. info.icab = f("iCab",v);
  1382. info.konqueror = f("KDE",v);
  1383. info.mobile = (f("Mobile",u)||f("Android",u)||f("Nokia",u)||f("webOS",u)||f("Opera Mini",u)||f("BlackBerry",u)||(f("Windows",u)&&f("PPC",u))||f("Smartphone",u)||f("IEMobile",u))&&!f("iPad",u);
  1384. info.msafari = (!f("IEMobile",u) && f("Mobile",u))||(f("iPad",u)&&f("Safari",u));
  1385. info.mopera = f("Opera Mini",u);
  1386. info.mie = f("PPC",u)||f("Smartphone",u)||f("IEMobile",u);
  1387. try {
  1388. if (info.ie) {
  1389. ver = u.match(/(?:MSIE) ([0-9.]+)/)[1];
  1390. if (u.match(/(?:Trident)\/([0-9.]+)/)){
  1391. var nTridentNum = parseInt(RegExp.$1,10);
  1392. if(nTridentNum > 3){
  1393. nativeVersion = nTridentNum + 4;
  1394. }
  1395. }
  1396. } else if (info.safari||info.msafari) {
  1397. ver = parseFloat(u.match(/Safari\/([0-9.]+)/)[1]);
  1398. if (ver == 100) {
  1399. ver = 1.1;
  1400. } else {
  1401. if(u.match(/Version\/([0-9.]+)/)){
  1402. ver = RegExp.$1;
  1403. }else{
  1404. ver = [1.0,1.2,-1,1.3,2.0,3.0][Math.floor(ver/100)];
  1405. }
  1406. }
  1407. } else if(info.mopera){
  1408. ver = u.match(/(?:Opera\sMini)\/([0-9.]+)/)[1];
  1409. } else if (info.firefox||info.opera||info.omniweb) {
  1410. ver = u.match(/(?:Firefox|Opera|OmniWeb)\/([0-9.]+)/)[1];
  1411. } else if (info.mozilla) {
  1412. ver = u.match(/rv:([0-9.]+)/)[1];
  1413. } else if (info.icab) {
  1414. ver = u.match(/iCab[ \/]([0-9.]+)/)[1];
  1415. } else if (info.chrome) {
  1416. ver = u.match(/Chrome[ \/]([0-9.]+)/)[1];
  1417. }
  1418. info.version = parseFloat(ver);
  1419. info.nativeVersion = parseFloat(nativeVersion);
  1420. if (isNaN(info.version)) info.version = -1;
  1421. } catch(e) {
  1422. info.version = -1;
  1423. }
  1424. this.navigator = function() {
  1425. return info;
  1426. };
  1427. return info;
  1428. };
  1429. /**
  1430. * os 메서드는 운영체제에 대한 정보 객체를 리턴한다.
  1431. * @return {Object} 운영체제 정보 객체. 운영체제의 영문 이름을 속성으로 가지며, 사용자가 사용하는 운영체제와 동일한 이름의 속성은 true를 가진다.
  1432. * @since 1.4.3 부터 iphone,android,nokia,webos,blackberry,mwin 사용 가능.
  1433. * @since 1.4.5 부터 ipad 사용가능.
  1434. * @example
  1435. oOS = $Agent().os(); // 사용자의 운영체제가 Windows XP라고 가정한다.
  1436. oOS.linux // false
  1437. oOS.mac // false
  1438. oOS.vista // false
  1439. oOS.win // true
  1440. oOS.win2000 // false
  1441. oOS.winxp // true
  1442. oOS.xpsp2 // false
  1443. oOS.win7 // false
  1444. oOS.getName() // winxp
  1445. */
  1446. jindo.$Agent.prototype.os = function() {
  1447. var info = new Object;
  1448. var u = this._navigator.userAgent;
  1449. var p = this._navigator.platform;
  1450. var f = function(s,h){ return (h.indexOf(s) > -1) };
  1451. info.getName = function(){
  1452. var name = "";
  1453. for(x in info){
  1454. if(typeof info[x] == "boolean" && info[x]&&info.hasOwnProperty(x))
  1455. name = x;
  1456. }
  1457. return name;
  1458. }
  1459. info.win = f("Win",p)
  1460. info.mac = f("Mac",p);
  1461. info.linux = f("Linux",p);
  1462. info.win2000 = info.win && (f("NT 5.0",u) || f("2000",u));
  1463. info.winxp = info.win && f("NT 5.1",u);
  1464. info.xpsp2 = info.winxp && f("SV1",u);
  1465. info.vista = info.win && f("NT 6.0",u);
  1466. info.win7 = info.win && f("NT 6.1",u);
  1467. info.ipad = f("iPad",u);
  1468. info.iphone = f("iPhone",u) && !info.ipad;
  1469. info.android = f("Android",u);
  1470. info.nokia = f("Nokia",u);
  1471. info.webos = f("webOS",u);
  1472. info.blackberry = f("BlackBerry",u);
  1473. info.mwin = f("PPC",u)||f("Smartphone",u)||f("IEMobile",u);
  1474. this.os = function() {
  1475. return info;
  1476. };
  1477. return info;
  1478. };
  1479. /**
  1480. * flash 메서드는 플래시에 대한 정보 객체를 리턴한다.
  1481. * @return {Object} Flash 정보 객체. <br>
  1482. * object.installed는 플래시 플레이어 설치 여부를 boolean 값으로 가지고 object.version은 플래시 플레이어의 버전을 가진다. 플래시 버전을 탐지하지 못하면 flash.version은 -1의 값을 가진다.
  1483. * @example
  1484. var oFlash = $Agent.flash();
  1485. oFlash.installed // 플래시 플레이어를 설치했다면 true
  1486. oFlash.version // 플래시 플레이어의 버전.
  1487. */
  1488. jindo.$Agent.prototype.flash = function() {
  1489. var info = new Object;
  1490. var p = this._navigator.plugins;
  1491. var m = this._navigator.mimeTypes;
  1492. var f = null;
  1493. info.installed = false;
  1494. info.version = -1;
  1495. if (typeof p != "undefined" && p.length) {
  1496. f = p["Shockwave Flash"];
  1497. if (f) {
  1498. info.installed = true;
  1499. if (f.description) {
  1500. info.version = parseFloat(f.description.match(/[0-9.]+/)[0]);
  1501. }
  1502. }
  1503. if (p["Shockwave Flash 2.0"]) {
  1504. info.installed = true;
  1505. info.version = 2;
  1506. }
  1507. } else if (typeof m != "undefined" && m.length) {
  1508. f = m["application/x-shockwave-flash"];
  1509. info.installed = (f && f.enabledPlugin);
  1510. } else {
  1511. for(var i=10; i > 1; i--) {
  1512. try {
  1513. f = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
  1514. info.installed = true;
  1515. info.version = i;
  1516. break;
  1517. } catch(e) {}
  1518. }
  1519. }
  1520. this.flash = function() {
  1521. return info;
  1522. };
  1523. /*
  1524. 하위호환을 위해 일단 남겨둔다.
  1525. */
  1526. this.info = this.flash;
  1527. return info;
  1528. };
  1529. /**
  1530. * silverlight 메서드는 실버라이트(Silverlight)에 대한 정보 객체를 리턴한다.
  1531. * @returns {Object} Silverlight 정보 객체. <br>
  1532. * object.installed은 실버라이트 플레이어 설치 여부를 boolean 값으로 가지고 object.version은 실버라이트 플레이어의 버전을 가진다. 플레이어의 버전을 탐지하지 못하면 object.version의 값은 -1이 된다.
  1533. * @example
  1534. var oSilver = $Agent.silverlight();
  1535. oSilver.installed // Silverlight 플레이어를 설치했다면 true
  1536. oSilver.version // Silverlight 플레이어의 버전.
  1537. */
  1538. jindo.$Agent.prototype.silverlight = function() {
  1539. var info = new Object;
  1540. var p = this._navigator.plugins;
  1541. var s = null;
  1542. info.installed = false;
  1543. info.version = -1;
  1544. if (typeof p != "undefined" && p.length) {
  1545. s = p["Silverlight Plug-In"];
  1546. if (s) {
  1547. info.installed = true;
  1548. info.version = parseInt(s.description.split(".")[0],10);
  1549. if (s.description == "1.0.30226.2") info.version = 2;
  1550. }
  1551. } else {
  1552. try {
  1553. s = new ActiveXObject("AgControl.AgControl");
  1554. info.installed = true;
  1555. if(s.isVersionSupported("3.0")){
  1556. info.version = 3;
  1557. }else if (s.isVersionSupported("2.0")) {
  1558. info.version = 2;
  1559. } else if (s.isVersionSupported("1.0")) {
  1560. info.version = 1;
  1561. }
  1562. } catch(e) {}
  1563. }
  1564. this.silverlight = function() {
  1565. return info;
  1566. };
  1567. return info;
  1568. };
  1569. /**
  1570. * @fileOverview $A의 생성자 및 메서드를 정의한 파일
  1571. * @name array.js
  1572. */
  1573. /**
  1574. * $A 객체를 생성하여 반환한다.
  1575. * @extends core
  1576. * @class $A 클래스는 배열(Array)을 래핑(wrapping)하여 배열을 다루기 위한 여러가지 메서드를 제공한다.<br>
  1577. * 여기서 래핑이란 자바스크립트의 함수를 감싸 본래 함수의 기능에 새로운 확장 속성을 추가하는 것을 말한다.
  1578. * @param {Array|$A} array 배열. 만약 매개 변수를 생략하면 빈 배열을 가진 새로운 $A 객체를 리턴한다.
  1579. * @constructor
  1580. * @description [Lite]
  1581. * @author Kim, Taegon
  1582. *
  1583. * @example
  1584. var zoo = ["zebra", "giraffe", "bear", "monkey"];
  1585. var waZoo = $A(zoo); // ["zebra", "giraffe", "bear", "monkey"]를 래핑한 $A 객체를 생성하여 반환
  1586. */
  1587. jindo.$A = function(array) {
  1588. var cl = arguments.callee;
  1589. if (typeof array == "undefined" || array == null) array = [];
  1590. if (array instanceof cl) return array;
  1591. if (!(this instanceof cl)) return new cl(array);
  1592. this._array = []
  1593. if (array.constructor != String) {
  1594. this._array = [];
  1595. for(var i=0; i < array.length; i++) {
  1596. this._array[this._array.length] = array[i];
  1597. }
  1598. }
  1599. };
  1600. /**
  1601. * toString 메서드는 내부 배열을 문자열로 변환한다. 자바스크립트의 Array.toString 을 사용한다.
  1602. * @return {String} 내부 배열을 변환한 문자열.
  1603. * @description [Lite]
  1604. *
  1605. * @example
  1606. var zoo = ["zebra", "giraffe", "bear", "monkey"];
  1607. $A(zoo).toString();
  1608. // 결과 : zebra,giraffe,bear,monkey
  1609. */
  1610. jindo.$A.prototype.toString = function() {
  1611. return this._array.toString();
  1612. };
  1613. /**
  1614. * 인덱스로 배열의 원소 값을 조회한다.
  1615. * @param {Number} nIndex 조회할 배열의 인덱스. 인덱스는 0부터 시작한다.
  1616. * @return {Value} 배열에서의 해당 인덱스의 원소 값.
  1617. * @description [Lite]
  1618. * @since 1.4.2 부터 지원
  1619. *
  1620. * @example
  1621. var zoo = ["zebra", "giraffe", "bear", "monkey"];
  1622. var waZoo = $A(zoo);
  1623. // 원소 값 조회
  1624. waZoo.get(1); // 결과 : giraffe
  1625. waZoo.get(3); // 결과 : monkey
  1626. */
  1627. jindo.$A.prototype.get = function(nIndex){
  1628. return this._array[nIndex];
  1629. };
  1630. /**
  1631. * 내부 배열의 크기를 지정하거나 리턴한다.
  1632. * @param {Number} [nLen] 지정할 배열의 크기.<br>
  1633. * nLen 이 기존 배열의 크기보다 크면 oValue 매개 변수의 값을 배열의 마지막에 덧붙인다.<br>
  1634. * nLen 이 기존 배열의 크기보다 작으면 nLen 번째 이후의 원소는 제거한다.
  1635. * @param {Value} [oValue] 새로운 원소를 추가할 때 사용할 초기값
  1636. * @return {Number|$A} 매개 변수를 모두 생략하면 현재 내부 배열의 크기를 리턴하고,<br>
  1637. * 매개 변수를 지정한 경우에는 내부 배열을 변경한 $A 객체를 리턴한다.
  1638. *
  1639. * @example
  1640. var zoo = ["zebra", "giraffe", "bear", "monkey"];
  1641. var birds = ["parrot", "sparrow", "dove"];
  1642. // 배열의 크기 조회
  1643. $A(zoo).length(); // 결과 : 4
  1644. // 배열의 크기 지정 (원소가 삭제되는 경우)
  1645. $A(zoo).length(2);
  1646. // 결과 : ["zebra", "giraffe"]
  1647. // 배열의 크기 지정 (원소가 추가되는 경우)
  1648. $A(zoo).length(6, "(Empty)");
  1649. // 결과 : ["zebra", "giraffe", "bear", "monkey", "(Empty)", "(Empty)"]
  1650. $A(zoo).length(5, birds);
  1651. // 결과 : ["zebra", "giraffe", "bear", "monkey", ["parrot", "sparrow", "dove"]]
  1652. */
  1653. jindo.$A.prototype.length = function(nLen, oValue) {
  1654. if (typeof nLen == "number") {
  1655. var l = this._array.length;
  1656. this._array.length = nLen;
  1657. if (typeof oValue != "undefined") {
  1658. for(var i=l; i < nLen; i++) {
  1659. this._array[i] = oValue;
  1660. }
  1661. }
  1662. return this;
  1663. } else {
  1664. return this._array.length;
  1665. }
  1666. };
  1667. /**
  1668. * 배열에서 특정 값을 검색한다.
  1669. * @param {Value} oValue 검색할 값
  1670. * @return {Boolean} 배열에서 매개 변수의 값과 동일한 원소를 찾으면 true를, 찾지 못하면 false를 리턴한다.
  1671. * @see $A#indexOf
  1672. * @description [Lite]
  1673. *
  1674. * @example
  1675. var arr = $A([1,2,3]);
  1676. // 값 검색
  1677. arr.has(3); // 결과 : true
  1678. arr.has(4); // 결과 : false
  1679. */
  1680. jindo.$A.prototype.has = function(oValue) {
  1681. return (this.indexOf(oValue) > -1);
  1682. };
  1683. /**
  1684. * 배열에서 특정 값을 검색하고 검색한 원소의 인덱스를 리턴한다.
  1685. * @param {Value} oValue 검색할 값
  1686. * @return {Number} 찾은 원소의 인덱스. 인덱스는 0 부터 시작한다. 매개 변수와 동일한 원소를 찾지 못하면 -1 을 리턴한다.
  1687. * @see $A#has
  1688. * @description [Lite]
  1689. *
  1690. * @example
  1691. var zoo = ["zebra", "giraffe", "bear"];
  1692. va r waZoo = $A(zoo);
  1693. // 값 검색 후 인덱스 리턴
  1694. waZoo.indexOf("giraffe"); // 1
  1695. waZoo.indexOf("monkey"); // -1
  1696. */
  1697. jindo.$A.prototype.indexOf = function(oValue) {
  1698. if (typeof this._array.indexOf != 'undefined') {
  1699. jindo.$A.prototype.indexOf = function(oValue) {
  1700. return this._array.indexOf(oValue);
  1701. }
  1702. }else{
  1703. jindo.$A.prototype.indexOf = function(oValue) {
  1704. for(var i=0; i < this._array.length; i++) {
  1705. if (this._array[i] == oValue) return i;
  1706. }
  1707. return -1;
  1708. }
  1709. }
  1710. return this.indexOf(oValue);
  1711. };
  1712. /**
  1713. * 내부의 원본 배열을 리턴한다.
  1714. * @return {Array} 배열
  1715. * @description [Lite]
  1716. *
  1717. * @example
  1718. var waNum = $A([1, 2, 3]);
  1719. waNum.$value(); // 원래의 배열인 [1, 2, 3]이 반환된다
  1720. */
  1721. jindo.$A.prototype.$value = function() {
  1722. return this._array;
  1723. };
  1724. /**
  1725. * 내부 배열에 하나 이상의 원소를 추가한다.
  1726. * @param {oValue1, ..., oValueN} oValueN 추가할 N 개의 값
  1727. * @return {Number} 하나 이상의 원소를 추가한 내부 배열의 크기
  1728. * @description [Lite]
  1729. *
  1730. * @example
  1731. var arr = $A([1,2,3]);
  1732. // 원소 추가
  1733. arr.push(4); // 결과 : 4 반환, 내부 배열은 [1,2,3,4]로 변경 됨
  1734. arr.push(5,6); // 결과 : 6 반환, 내부 배열은 [1,2,3,4,5,6]로 변경 됨
  1735. */
  1736. jindo.$A.prototype.push = function(oValue1/*, ...*/) {
  1737. return this._array.push.apply(this._array, Array.prototype.slice.apply(arguments));
  1738. };
  1739. /**
  1740. * 내부 배열의 마지막 원소를 삭제한다.
  1741. * @return {Value} 삭제한 원소
  1742. * @description [Lite]
  1743. *
  1744. * @example
  1745. var arr = $A([1,2,3,4,5]);
  1746. arr.pop(); // 결과 : 5 반환, 내부 배열은 [1,2,3,4]로 변경 됨
  1747. */
  1748. jindo.$A.prototype.pop = function() {
  1749. return this._array.pop();
  1750. };
  1751. /**
  1752. * 내부 배열의 모든 원소를 앞으로 한 칸씩 이동한다. 내부 배열의 첫 번째 원소는 삭제된다.
  1753. * @return {Value} 삭제한 첫 번째 원소.
  1754. * @see $A#pop
  1755. * @see $A#unshift
  1756. * @description [Lite]
  1757. * @example
  1758. var arr = $A(['Melon','Grape','Apple','Kiwi']);
  1759. arr.shift(); // 결과 : 'Melon' 반환, 내부 배열은 ["Grape", "Apple", "Kiwi"]로 변경 됨.
  1760. */
  1761. jindo.$A.prototype.shift = function() {
  1762. return this._array.shift();
  1763. };
  1764. /**
  1765. * 내부 배열의 맨 앞에 하나 이상의 원소를 삽입한다.
  1766. * @param {oValue1, ..., oValueN} oValueN 삽입할 하나 이상의 값
  1767. * @return {Number} 원소를 추가한 후의 배열의 크기
  1768. * @description [Lite]
  1769. * @example
  1770. var arr = $A([4,5]);
  1771. arr.unshift('c'); // 결과 : 3 반환, 내부 배열은 ["c", 4, 5]로 변경 됨.
  1772. arr.unshift('a', 'b'); // 결과 : 5 반환, 내부 배열은 ["a", "b", "c", 4, 5]로 변경 됨.
  1773. */
  1774. jindo.$A.prototype.unshift = function(oValue1/*, ...*/) {
  1775. this._array.unshift.apply(this._array, Array.prototype.slice.apply(arguments));
  1776. return this._array.length;
  1777. };
  1778. /**
  1779. * 내부 배열의 모든 원소를 순회하면서 콜백 함수를 실행한다.
  1780. *
  1781. * @param {Function} fCallback 순회하면서 실행할 콜백 함수.<br>
  1782. * <br>
  1783. * 콜백 함수는 fCallback(value, index, array) 의 형식을 가진다. <br>
  1784. * value 는 배열이 가진 원소의 값을 가지고,<br>
  1785. * index 는 해당 원소의 인덱스를 가지고,<br>
  1786. * array 는 배열 그 자체를 가리킨다.
  1787. * @param {Object} [oThis] 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 사용할 this
  1788. * @return {$A} $A 객체
  1789. * @import core.$A[Break, Continue]
  1790. * @see $A#map
  1791. * @see $A#filter
  1792. * @description [Lite]
  1793. *
  1794. * @example
  1795. var waZoo = $A(["zebra", "giraffe", "bear", "monkey"]);
  1796. waZoo.forEach(function(value, index, array) {
  1797. document.writeln((index+1) + ". " + value);
  1798. });
  1799. // 결과 :
  1800. // 1. zebra
  1801. // 2. giraffe
  1802. // 3. bear
  1803. // 4. monkey
  1804. * @example
  1805. var waArray = $A([1, 2, 3]);
  1806. waArray.forEach(function(value, index, array) {
  1807. array[index] += 10;
  1808. });
  1809. document.write(waArray.$value());
  1810. // 결과 : 11, 12, 13 (내부 배열에 10씩 더해짐)
  1811. */
  1812. jindo.$A.prototype.forEach = function(fCallback, oThis) {
  1813. if (typeof this._array.forEach == "function") {
  1814. jindo.$A.prototype.forEach = function(fCallback, oThis) {
  1815. var arr = this._array;
  1816. var errBreak = this.constructor.Break;
  1817. var errContinue = this.constructor.Continue;
  1818. function f(v,i,a) {
  1819. try {
  1820. fCallback.call(oThis, v, i, a);
  1821. } catch(e) {
  1822. if (!(e instanceof errContinue)) throw e;
  1823. }
  1824. };
  1825. try {
  1826. this._array.forEach(f);
  1827. } catch(e) {
  1828. if (!(e instanceof errBreak)) throw e;
  1829. }
  1830. return this;
  1831. }
  1832. }else{
  1833. jindo.$A.prototype.forEach = function(fCallback, oThis) {
  1834. var arr = this._array;
  1835. var errBreak = this.constructor.Break;
  1836. var errContinue = this.constructor.Continue;
  1837. function f(v,i,a) {
  1838. try {
  1839. fCallback.call(oThis, v, i, a);
  1840. } catch(e) {
  1841. if (!(e instanceof errContinue)) throw e;
  1842. }
  1843. };
  1844. for(var i=0; i < arr.length; i++) {
  1845. try {
  1846. f(arr[i], i, arr);
  1847. } catch(e) {
  1848. if (e instanceof errBreak) break;
  1849. throw e;
  1850. }
  1851. }
  1852. return this;
  1853. }
  1854. }
  1855. return this.forEach(fCallback, oThis);
  1856. };
  1857. /**
  1858. * 배열의 일부를 추출한다.
  1859. * @param {Number} nStart 잘라낼 부분의 시작 인덱스. 인덱스는 0부터 시작한다.
  1860. * @param {Number} nEnd 잘라낼 부분의 바로 뒤 인덱스
  1861. * @return {$A} 내부 배열의 일부를 추출한 새로운 $A 객체.<br>
  1862. * nStart 값이 0 보다 작거나 혹은 nStart 값이 nEnd 값 보다 크거나 같으면 빈 배열을 가지는 $A 객체를 리턴한다.
  1863. * @description [Lite]
  1864. *
  1865. * @example
  1866. var arr = $A([12, 5, 8, 130, 44]);
  1867. var newArr = arr.slice(1,3);
  1868. // 잘라낸 배열인 [5, 8]를 래핑한 $A 객체를 리턴한다. (원래의 배열은 변화 없음)
  1869. * @example
  1870. var arr = $A([12, 5, 8, 130, 44]);
  1871. var newArr = arr.slice(3,3);
  1872. // []를 래핑한 $A 객체를 리턴한다.
  1873. */
  1874. jindo.$A.prototype.slice = function(nStart, nEnd) {
  1875. var a = this._array.slice.call(this._array, nStart, nEnd);
  1876. return jindo.$A(a);
  1877. };
  1878. /**
  1879. * 배열의 일부를 삭제한다.
  1880. * @param {Number} nIndex 삭제할 부분의 시작 인덱스. 인덱스는 0부터 시작한다.
  1881. * @param {Number} [nHowMany] 삭제할 원소의 개수.<br>
  1882. * 이 값과 oValueN 를 생략하면 nIndex 번째 원소부터 배열의 마지막 원소까지 삭제한다.<br>
  1883. * 이 값을 0 혹은 지정하지 않고 oValueN 에 값을 지정하면 nIndex 번째 위치에 oValueN 값이 추가된다.
  1884. * @param {Value1, ...,ValueN} [oValueN] 삭제한 배열에 추가할 하나 이상의 값. nIndex 값의 인덱스부터 추가된다.
  1885. * @returns {$A} 삭제한 원소를 래핑하는 새로운 $A 객체
  1886. * @description [Lite]
  1887. *
  1888. * @example
  1889. var arr = $A(["angel", "clown", "mandarin", "surgeon"]);
  1890. var removed = arr.splice(2, 0, "drum");
  1891. // arr의 내부 배열은 ["angel", "clown", "drum", "mandarin", "surgeon"]로 인덱스 2에 drum이 추가 됨
  1892. // removed의 내부 배열은 []로 삭제된 원소가 없음
  1893. removed = arr.splice(3, 1);
  1894. // arr의 내부 배열은 ["angel", "clown", "drum", "surgeon"]로 mandarin이 삭제 됨
  1895. // removed의 내부 배열은 삭제된 원소 ["mandarin"]를 가짐
  1896. removed = arr.splice(2, 1, "trumpet", "parrot");
  1897. // arr의 내부 배열은 ["angel", "clown", "trumpet", "parrot", "surgeon"]로 drum이 삭제되고 새로운 원소가 추가 됨
  1898. // removed의 내부 배열은 삭제된 원소 ["drum"]을 가짐
  1899. removed = arr.splice(3);
  1900. // arr의 내부 배열은 ["angel", "clown", "trumpet"]로 인덱스 3부터 마지막 원소가 삭제되었음
  1901. // removed의 내부 배열은 삭제된 원소 ["parrot", "surgeon"]을 가짐
  1902. */
  1903. jindo.$A.prototype.splice = function(nIndex, nHowMany/*, oValue1,...*/) {
  1904. var a = this._array.splice.apply(this._array, Array.prototype.slice.apply(arguments));
  1905. return jindo.$A(a);
  1906. };
  1907. /**
  1908. * 배열의 원소를 무작위로 섞는다.
  1909. * @return {$A} 배열이 섞여진 $A 객체
  1910. * @description [Lite]
  1911. *
  1912. * @example
  1913. var dice = $A([1,2,3,4,5,6]);
  1914. dice.shuffle();
  1915. document.write("You get the number " + dice.get(0));
  1916. // 결과 : 1부터 6까지의 숫자 중 랜덤한 숫자
  1917. */
  1918. jindo.$A.prototype.shuffle = function() {
  1919. this._array.sort(function(a,b){ return Math.random()>Math.random()?1:-1 });
  1920. return this;
  1921. };
  1922. /**
  1923. * 배열 원소의 순서를 거꾸로 뒤집는다.
  1924. * @return {$A} 원소 순서를 뒤집은 $A 객체
  1925. * @description [Lite]
  1926. *
  1927. * @example
  1928. var arr = $A([1, 2, 3, 4, 5]);
  1929. arr.reverse(); // 결과 : [5, 4, 3, 2, 1]
  1930. */
  1931. jindo.$A.prototype.reverse = function() {
  1932. this._array.reverse();
  1933. return this;
  1934. };
  1935. /**
  1936. * 배열의 모든 원소를 제거하고, 빈 배열로 만든다.
  1937. * @return {$A} 배열의 원소가 제거된 $A 객체
  1938. * @description [Lite]
  1939. *
  1940. * @example
  1941. var arr = $A([1, 2, 3]);
  1942. arr.empty(); // 결과 : []
  1943. */
  1944. jindo.$A.prototype.empty = function() {
  1945. return this.length(0);
  1946. };
  1947. /**
  1948. * Break 메서드는 forEach, filter, map 메서드의 순회 루프를 중단한다.
  1949. * @remark 내부적으로는 강제로 예외를 발생시키는 구조이므로, try ~ catch 영역에서 이 메소드를 실행하면 정상적으로 동작하지 않을 수 있다.
  1950. *
  1951. * @description [Lite]
  1952. * @see $A#Continue
  1953. * @see $A#forEach
  1954. * @see $A#filter
  1955. * @see $A#map
  1956. * @example
  1957. $A([1,2,3,4,5]).forEach(function(value,index,array) {
  1958. // 값이 4보다 크면 종료
  1959. if (value > 4) $A.Break();
  1960. ...
  1961. });
  1962. */
  1963. jindo.$A.Break = function() {
  1964. if (!(this instanceof arguments.callee)) throw new arguments.callee;
  1965. };
  1966. /**
  1967. * Continue 메서드는 forEach, filter, map 메서드의 순회 루프에서 나머지 명령을 실행하지 않고 다음 루프로 건너뛴다.
  1968. * @remark 내부적으로는 강제로 예외를 발생시키는 구조이므로, try ~ catch 영역에서 이 메소드를 실행하면 정상적으로 동작하지 않을 수 있다.
  1969. *
  1970. * @description [Lite]
  1971. * @see $A#Break
  1972. * @see $A#forEach
  1973. * @see $A#filter
  1974. * @see $A#map
  1975. * @example
  1976. $A([1,2,3,4,5]).forEach(function(value,index,array) {
  1977. // 값이 짝수면 처리를 하지 않음
  1978. if (value%2 == 0) $A.Continue();
  1979. ...
  1980. });
  1981. */
  1982. jindo.$A.Continue = function() {
  1983. if (!(this instanceof arguments.callee)) throw new arguments.callee;
  1984. };
  1985. /**
  1986. * @fileOverview $A의 확장 메서드를 정의한 파일
  1987. * @name array.extend.js
  1988. */
  1989. /**
  1990. * 배열의 모든 원소를 순회하면서 콜백 함수를 실행한다.<br>
  1991. * 콜백 함수의 실행 결과를 배열의 원소에 설정한다.
  1992. *
  1993. * @param {Function} fCallback 순회하면서 실행할 콜백 함수.<br>
  1994. * <br>
  1995. * 콜백 함수는 fCallback(value, index, array) 의 형식을 가진다. <br>
  1996. * value 는 배열이 가진 원소의 값을 가지고,<br>
  1997. * index 는 해당 원소의 인덱스를 가지고,<br>
  1998. * array 는 배열 그 자체를 가리킨다.<br>
  1999. * <br>
  2000. * 콜백 함수에서 리턴하는 값을 원소의 값으로 설정한다.
  2001. *
  2002. * @param {Object} [oThis] 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 사용할 this
  2003. * @return {$A} 콜백 함수의 수행 결과를 반영한 $A 객체
  2004. * @see $A#forEach
  2005. * @see $A#filter
  2006. *
  2007. * @example
  2008. var waZoo = $A(["zebra", "giraffe", "bear", "monkey"]);
  2009. waZoo.map(function(value, index, array) {
  2010. return (index+1) + ". " + value;
  2011. });
  2012. // 결과 : [1. zebra, 2. giraffe, 3. bear, 4. monkey]
  2013. * @example
  2014. var waArray = $A([1, 2, 3]);
  2015. waArray.map(function(value, index, array) {
  2016. return value + 10;
  2017. });
  2018. document.write(waArray.$value());
  2019. // 결과 : 11, 12, 13 (내부 배열에 10씩 더해짐)
  2020. */
  2021. jindo.$A.prototype.map = function(fCallback, oThis) {
  2022. if (typeof this._array.map == "function") {
  2023. jindo.$A.prototype.map = function(fCallback, oThis) {
  2024. var arr = this._array;
  2025. var errBreak = this.constructor.Break;
  2026. var errContinue = this.constructor.Continue;
  2027. function f(v,i,a) {
  2028. try {
  2029. return fCallback.call(oThis, v, i, a);
  2030. } catch(e) {
  2031. if (e instanceof errContinue){
  2032. return v;
  2033. } else{
  2034. throw e;
  2035. }
  2036. }
  2037. };
  2038. try {
  2039. this._array = this._array.map(f);
  2040. } catch(e) {
  2041. if(!(e instanceof errBreak)) throw e;
  2042. }
  2043. return this;
  2044. }
  2045. }else{
  2046. jindo.$A.prototype.map = function(fCallback, oThis) {
  2047. var arr = this._array;
  2048. var returnArr = [];
  2049. var errBreak = this.constructor.Break;
  2050. var errContinue = this.constructor.Continue;
  2051. function f(v,i,a) {
  2052. try {
  2053. return fCallback.call(oThis, v, i, a);
  2054. } catch(e) {
  2055. if (e instanceof errContinue){
  2056. return v;
  2057. } else{
  2058. throw e;
  2059. }
  2060. }
  2061. };
  2062. for(var i=0; i < this._array.length; i++) {
  2063. try {
  2064. returnArr[i] = f(arr[i], i, arr);
  2065. } catch(e) {
  2066. if (e instanceof errBreak){
  2067. return this;
  2068. }else{
  2069. throw e;
  2070. }
  2071. }
  2072. }
  2073. this._array = returnArr;
  2074. return this;
  2075. }
  2076. }
  2077. return this.map(fCallback, oThis);
  2078. };
  2079. /**
  2080. * 배열의 모든 원소를 순회하면서 콜백 함수를 실행한다. 실행이 끝나면 filter 메서드는 콜박 함수를 만족하는 원소로 이루어진 새로운 $A 객체를 반환한다.
  2081. * @param {Function} fCallback 순회하면서 실행할 콜백 함수.<br>
  2082. * <br>
  2083. * 콜백 함수는 fCallback(value, index, array)의 형식으로 작성해야 한다. 여기서
  2084. * value 는 배열이 가진 원소의 값, index 는 해당 원소의 인덱스, array 는 원본 배열이다.<br>
  2085. * <br>
  2086. * 콜백 함수는 Boolean 을 리턴해야한다. 만약 리턴 값이 true 인 원소는 새로운 배열의 원소가 된다.
  2087. *
  2088. * @param {Object} oThis 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 사용할 this
  2089. * @return {$A} 콜백 함수의 리턴 값이 true 인 원소로 이루어진 새로운 $A 객체
  2090. * @see $A#forEach
  2091. * @see $A#map
  2092. *
  2093. * @example
  2094. var arr = $A([1,2,3,4,5]);
  2095. // 필터링 함수
  2096. function filterFunc(value, index, array) {
  2097. if (value > 2) {
  2098. return true;
  2099. } else {
  2100. return false;
  2101. }
  2102. }
  2103. var newArr = arr.filter(filterFunc);
  2104. document.write(arr.$value()); // 결과 : [1,2,3,4,5]
  2105. document.write(newArr.$value()); // 결과 : [3,4,5]
  2106. */
  2107. jindo.$A.prototype.filter = function(fCallback, oThis) {
  2108. if (typeof this._array.filter != "undefined") {
  2109. jindo.$A.prototype.filter = function(fCallback, oThis) {
  2110. return jindo.$A(this._array.filter(fCallback, oThis));
  2111. }
  2112. }else{
  2113. jindo.$A.prototype.filter = function(fCallback, oThis) {
  2114. var ar = [];
  2115. this.forEach(function(v,i,a) {
  2116. if (fCallback.call(oThis, v, i, a) === true) {
  2117. ar[ar.length] = v;
  2118. }
  2119. });
  2120. return jindo.$A(ar);
  2121. }
  2122. }
  2123. return this.filter(fCallback, oThis);
  2124. };
  2125. /**
  2126. * 배열의 모든 원소를 순회하면서 콜백 함수를 실행한다. 동시에 배열의 모든 원소가 콜백 함수를 만족하는지(콜백 함수가 true를 리턴하는지) 검사한다. <br>
  2127. * 만약 모든 원소가 콜백 함수를 만족하면 every 메서드는 true를 리턴한다.
  2128. *
  2129. * @param {Function} fCallback 순회하면서 실행할 콜백 함수.<br>
  2130. * <br>
  2131. * 콜백 함수는 fCallback(value, index, array) 의 형식으로 작성해야 한다. 여기서
  2132. * value 는 배열이 가진 원소의 값, index 는 해당 원소의 인덱스, array 는 원본 배열이다.<br>
  2133. * <br>
  2134. * 콜백 함수는 Boolean 을 리턴해야한다.<br>
  2135. *
  2136. * @param {Object} oThis 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 사용할 this
  2137. * @return {Boolean} 콜백 함수의 리턴 값이 모두 true 이면 true 를, 그렇지 않으면 false 를 리턴한다.
  2138. * @see $A#some
  2139. *
  2140. * @example
  2141. function isBigEnough(value, index, array) {
  2142. return (value >= 10);
  2143. }
  2144. var try1 = $A([12, 5, 8, 130, 44]).every(isBigEnough); // 결과 : false
  2145. var try2 = $A([12, 54, 18, 130, 44]).every(isBigEnough); // 결과 : true
  2146. */
  2147. jindo.$A.prototype.every = function(fCallback, oThis) {
  2148. if (typeof this._array.every != "undefined"){
  2149. jindo.$A.prototype.every = function(fCallback, oThis) {
  2150. return this._array.every(fCallback, oThis);
  2151. }
  2152. }else{
  2153. jindo.$A.prototype.every = function(fCallback, oThis) {
  2154. var result = true;
  2155. this.forEach(function(v, i, a) {
  2156. if (fCallback.call(oThis, v, i, a) === false) {
  2157. result = false;
  2158. jindo.$A.Break();
  2159. }
  2160. });
  2161. return result;
  2162. }
  2163. }
  2164. return this.every(fCallback, oThis);
  2165. };
  2166. /**
  2167. * 배열의 모든 원소를 순회하면서 콜백 함수를 실행한다.<br>
  2168. * 콜백 함수를 만족하는 원소가 있는지 검사한다.
  2169. *
  2170. * @param {Function} fCallback 순회하면서 실행할 콜백 함수.<br>
  2171. * <br>
  2172. * 콜백 함수는 fCallback(value, index, array) 의 형식으로 작성해야 한다. 여기서
  2173. * value 는 배열이 가진 원소, index 는 해당 원소의 인덱스, array 는 원본 배열이다.<br>
  2174. * <br>
  2175. * 콜백 함수는 Boolean 을 리턴해야한다.<br>
  2176. *
  2177. * @param {Object} oThis 콜백 함수가 객체의 메서드일 때 콜백 함수 내부에서 사용할 this
  2178. * @return {Boolean} 콜백 함수의 리턴 값이 true 인 원소가 있으면 true 를, 하나도 없으면 false 를 리턴한다.
  2179. * @see $A#every
  2180. *
  2181. * @example
  2182. function twoDigitNumber(value, index, array) {
  2183. return (value >= 10 && value < 100);
  2184. }
  2185. var try1 = $A([12, 5, 8, 130, 44]).some(twoDigitNumber); // 결과 : true
  2186. var try2 = $A([1, 5, 8, 130, 4]).some(twoDigitNumber); // 결과 : false
  2187. */
  2188. jindo.$A.prototype.some = function(fCallback, oThis) {
  2189. if (typeof this._array.some != "undefined"){
  2190. jindo.$A.prototype.some = function(fCallback, oThis) {
  2191. return this._array.some(fCallback, oThis);
  2192. }
  2193. }else{
  2194. jindo.$A.prototype.some = function(fCallback, oThis) {
  2195. var result = false;
  2196. this.forEach(function(v, i, a) {
  2197. if (fCallback.call(oThis, v, i, a) === true) {
  2198. result = true;
  2199. jindo.$A.Break();
  2200. }
  2201. });
  2202. return result;
  2203. }
  2204. }
  2205. return this.some(fCallback, oThis);
  2206. };
  2207. /**
  2208. * 배열에서 매개 변수와 같은 값을 제외하여 새로운 $A 객체를 만든다.
  2209. *
  2210. * @param {Value, ..., ValueN} oValueN 배열에서 제외할 값
  2211. * @return {$A} 배열에서 특정 값을 제외한 새로운 $A 객체
  2212. *
  2213. * @example
  2214. var arr = $A([12, 5, 8, 130, 44]);
  2215. var newArr1 = arr.refuse(12);
  2216. document.write(arr); // 결과 : [12, 5, 8, 130, 44]
  2217. document.write(newArr1); // 결과 : [5, 8, 130, 44]
  2218. var newArr2 = newArr1.refuse(8, 44, 130);
  2219. document.write(newArr1); // 결과 : [5, 8, 130, 44]
  2220. document.write(newArr2); // 결과 : [5]
  2221. */
  2222. jindo.$A.prototype.refuse = function(oValue1/*, ...*/) {
  2223. var a = jindo.$A(Array.prototype.slice.apply(arguments));
  2224. return this.filter(function(v,i) { return !a.has(v) });
  2225. };
  2226. /**
  2227. * 배열에서 중복되는 원소를 삭제한다.
  2228. *
  2229. * @return {$A} 중복되는 원소를 제거한 $A 객체
  2230. *
  2231. * @example
  2232. var arr = $A([10, 3, 76, 5, 4, 3]);
  2233. arr.unique(); // 결과 : [10, 3, 76, 5, 4]
  2234. */
  2235. jindo.$A.prototype.unique = function() {
  2236. var a = this._array, b = [], l = a.length;
  2237. var i, j;
  2238. /*
  2239. 중복되는 원소 제거
  2240. */
  2241. for(i = 0; i < l; i++) {
  2242. for(j = 0; j < b.length; j++) {
  2243. if (a[i] == b[j]) break;
  2244. }
  2245. if (j >= b.length) b[j] = a[i];
  2246. }
  2247. this._array = b;
  2248. return this;
  2249. };
  2250. /**
  2251. * @fileOverview $Ajax의 생성자 및 메서드를 정의한 파일
  2252. * @name Ajax.js
  2253. */
  2254. /**
  2255. * $Ajax는 서버와 브라우저 사이의 비동기 통신, 즉 Ajax 통신을 지원한다. $Ajax는 XHR(XMLHTTPRequest)을 사용한 기본적인 방식과 함께 다른 호스트(Host) 사이의 통신을 위한 여러 방식을 제공한다.
  2256. * $Ajax 객체의 기본적인 초기화 방식은 다음과 같다.
  2257. * <textarea name="code" class="js:nocontrols">
  2258. * var oAjax = new $Ajax('server.php', {
  2259. type : 'xhr',
  2260. method : 'get', // GET 방식으로 통신
  2261. onload : function(res){ // 요청이 완료되면 실행될 콜백 함수
  2262. $('list').innerHTML = res.text();
  2263. },
  2264. timeout : 3, // 3초 이내에 요청이 완료되지 않으면 ontimeout 실행 (생략 시 0)
  2265. ontimeout : function(){ // 타임 아웃이 발생하면 실행될 콜백 함수, 생략 시 타임 아웃이 되면 아무 처리도 하지 않음
  2266. alert("Timeout!");
  2267. },
  2268. async : true // 비동기로 호출하는 경우, 생략하면 true
  2269. });
  2270. oAjax.request();
  2271. }
  2272. * </textarea>
  2273. *
  2274. * @extends core
  2275. * @class $Ajax 클래스는 다양한 개발 환경에서 Ajax 요청과 응답을 쉽게 구현하기 위한 메서드를 제공한다.<br>
  2276. *
  2277. * $Ajax를 초기화할 때 사용하는 매개 변수는 다음과 같다.
  2278. *
  2279. * @param {String} url Ajax 요청을 보낼 서버 측 URL.<br>
  2280. * @param {Object} option $Ajax 에서 사용하는 콜백 함수, 통신 방식 등과 같은 다양한 정보를 정의한다.<br>
  2281. * <br>
  2282. * option 객체의 프로퍼티와 사용법은 아래에서 설명한다.<br>
  2283. <table>
  2284. <thead style="background-color:#D2E0E6;">
  2285. <th>프로퍼티 명</th>
  2286. <th>타입</th>
  2287. <th>설명</th>
  2288. </thead>
  2289. <tbody>
  2290. <tr>
  2291. <td style="font-weight:bold;">type</td>
  2292. <td>String</td>
  2293. <td>
  2294. Ajax 구현 방식. 생략 시 기본 값은 "xhr"
  2295. <ul>
  2296. <li><strong>xhr</strong>
  2297. 브라우저에 내장된 XMLHttpRequest 객체를 이용하여 Ajax 요청을 처리한다.<br>
  2298. 응답으로는 text, xml, json 방식 모두 사용이 가능하며, 요청 실패 시 HTTP 응답코드를 통해 원인 파악이 가능하다.<br>
  2299. 단, Cross-Domain 에서는 사용할 수 없다.
  2300. </li>
  2301. <li><strong>iframe</strong>
  2302. iframe 을 프록시로 사용하여 Ajax 요청을 처리한다. Cross-Domain 에서 사용한다.<br>
  2303. 로컬(요청 하는 쪽)과 원격(요청 받는 쪽)에 모두 프록시용 HTML 파일을 만들어<br>
  2304. iframe 에서 원격 프록시에 요청하면, 원격 프록시에서 원격 도메인의 페이지에 XHR 로 Ajax 요청을 한다.<br>
  2305. 응답을 받은 원격 프록시에서 로컬 프록시로 응답을 전달하면 로컬 프록시에서 최종적으로 콜백 함수(onload)를 호출하여 처리된다.<br>
  2306. <ul type="disc">
  2307. <li>원격 프록시 파일 : ajax_remote_callback.html</li>
  2308. <li>로컬 프록시 파일 : ajax_local_callback.html</li>
  2309. </ul>
  2310. ※ IE 에서는 "딱.딱." 하는 페이지 이동음이 들릴 수도 있다 (요청당 2회).
  2311. </li>
  2312. <li><strong>jsonp</strong>
  2313. JSON 과 &lt;script&gt; 태그를 사용하여 사용하여 Ajax 요청을 처리한다. Cross-Domain 에서 사용한다.<br>
  2314. &lt;script&gt; 태그를 동적으로 생성하여, 요청할 원격 페이지를 스크립트에 삽입하여 GET 방식으로 요청을 전송한다.<br>
  2315. 요청 시에 콜백 함수를 매개 변수로 넘기면, 원격 페이지에서 전달받은 콜백 함수명으로 아래와 같이 응답을 보낸다.<br>
  2316. <ul type="disc"><li>function_name(...결과 값...)</li></ul>
  2317. 응답은 콜백 함수(onload)에서 처리된다.<br>
  2318. ※ GET 방식만 가능하므로, 전송 데이터 길이는 URL 에 허용하는 길이로 제한된다.
  2319. </li>
  2320. <li><strong>flash</strong>
  2321. 플래시 객체를 사용하여 Ajax 요청을 처리한다. Cross-Domain 에서 사용한다.<br>
  2322. 서버의 루트에 crossdomain.xml 이 존재해야 하며 접근 권한을 설정해야 사용할 수 있다.<br>
  2323. 모든 통신은 플래시 객체를 통하여 주고 받으며 Ajax 호출을 하기 전에 반드시 플래시 객체를 초기화해야 한다.<br>
  2324. $Ajax.SWFRequest.write 메서드 사용하여 초기화하며 해당 메서드는 &lt;body&gt; 태그 내에 작성한다.
  2325. </li>
  2326. <li><strong>get/post/put/delete</strong> : 내부적으로 xhr 로 처리한다.</li>
  2327. </ul>
  2328. </td>
  2329. </tr>
  2330. <tr>
  2331. <td style="font-weight:bold;">method</td>
  2332. <td>String</td>
  2333. <td>
  2334. HTTP 통신 방법
  2335. <ul>
  2336. <li><strong>post</strong> : 생략 시 기본 값.</li>
  2337. <li><strong>get</strong> : type 이 "jsonp" 이면 "get" 으로 설정된다.</li>
  2338. <li><strong>put</strong> : 1.4.2 부터 사용 가능</li>
  2339. <li><strong>delete</strong> : 1.4.2 부터 사용 가능</li>
  2340. </ul>
  2341. </td>
  2342. </tr>
  2343. <tr>
  2344. <td style="font-weight:bold;">timeout</td>
  2345. <td>Number</td>
  2346. <td>
  2347. 요청 타임아웃 시간. 생략 시 0 (단위는 초).<br>
  2348. 타임아웃 시간 내에 요청이 완료되지 않으면 중지시킨다.<br>
  2349. 비동기 호출인 경우에만 사용 가능하다.
  2350. </td>
  2351. </tr>
  2352. <tr>
  2353. <td style="font-weight:bold;">onload</td>
  2354. <td>Function</td>
  2355. <td>
  2356. 요청이 완료되면 실행할 콜백 함수. 반드시 지정해야 한다.<br>
  2357. 매개 변수로 응답 객체인 $Ajax.Response 객체가 전달 된다.
  2358. </td>
  2359. </tr>
  2360. <tr>
  2361. <td style="font-weight:bold;">onerror</td>
  2362. <td>Function</td>
  2363. <td>
  2364. 요청이 실패하면 실행할 콜백 함수.<br>
  2365. 생략하면 에러가 발생해도 onload 를 실행한다.
  2366. </td>
  2367. </tr>
  2368. <tr>
  2369. <td style="font-weight:bold;">ontimeout</td>
  2370. <td>Function</td>
  2371. <td>
  2372. 타임아웃이 되었을 때 실행할 콜백 함수.<br>
  2373. 생략하면 타임아웃 발생 후에 아무런 처리를 하지 않는다.
  2374. </td>
  2375. </tr>
  2376. <tr>
  2377. <td style="font-weight:bold;">proxy</td>
  2378. <td>String</td>
  2379. <td>
  2380. 로컬 프록시 파일(ajax_local_callback.html)의 경로.<br>
  2381. type 이 "iframe" 일 때 사용하며 반드시 지정해야 한다.
  2382. </td>
  2383. </tr>
  2384. <tr>
  2385. <td style="font-weight:bold;">jsonp_charset</td>
  2386. <td>String</td>
  2387. <td>
  2388. 요청 시 사용할 &lt;script&gt; 인코딩 방식.<br>
  2389. type 이 "jsonp" 일 때 사용한다. 생략하면 "utf-8" 이 기본값이다. (0.4.2 부터 지원)
  2390. </td>
  2391. </tr>
  2392. <tr>
  2393. <td style="font-weight:bold;">callbackid</td>
  2394. <td>String</td>
  2395. <td>
  2396. 콜백 함수 이름에 사용할 아이디 값.<br>
  2397. type 이 "jsonp" 일 때 사용한다. (1.3.0 부터 지원)<br>
  2398. 생략하면 자동으로 랜덤한 아이디 값을 생성하여 사용한다.
  2399. <br>
  2400. jsonp 방식에서 Ajax 요청 시, 콜백 함수 이름에 랜덤한 아이디 값을 덧붙여 만든 콜백 함수 이름을 서버로 전달한다.<br>
  2401. 이 때 랜덤한 값을 아이디로 사용하여 넘기므로 요청 URL이 매번 새롭게 생성되어 캐쉬 서버가 아닌 서버로 직접 데이터를 요청하게 된다.<br>
  2402. 아이디 값을 지정하면 랜덤한 아이디 값으로 콜백 함수 이름을 생성하지 않으므로<br>
  2403. 캐쉬 서버를 사용하여 그에 대한 히트율을 높이고자 할 때 아이디를 지정하여 사용할 수 있다.
  2404. </td>
  2405. </tr>
  2406. <tr>
  2407. <td style="font-weight:bold;">callbackname</td>
  2408. <td>String</td>
  2409. <td>
  2410. 콜백 함수 이름을 가지는 매개변수 이름.<br>
  2411. type 이 "jsonp" 일 때 사용한다. 기본 값은 "_callback" 이다. (1.3.8 부터 지원)
  2412. </td>
  2413. </tr>
  2414. <tr>
  2415. <td style="font-weight:bold;">sendheader</td>
  2416. <td>Boolean</td>
  2417. <td>
  2418. 요청 헤더를 전송할지 여부.<br>
  2419. type 이 "flash" 일 때 사용하며, 서버에서 접근 권한을 설정하는 crossdomain.xml 에<br>
  2420. allow-header 가 없는 경우에 false 로 설정해야 한다.<br>
  2421. 플래시 9에서는 allow-header가 false인 경우 get만 ajax가 되면 post는 ajax가 안된다.<br>
  2422. 플래시 10에서는 allow-header가 false인 경우 get,post 둘다 ajax가 안된다.<br>
  2423. 그래서 allow-header가 설정되어 있지 않다면 반드시 false로 셋팅해야 한다.<br>
  2424. 기본 값은 true 이다. (1.3.4부터 지원)
  2425. </td>
  2426. </tr>
  2427. <tr>
  2428. <td style="font-weight:bold;">async</td>
  2429. <td>Boolean</td>
  2430. <td>
  2431. 비동기 호출 여부.<br>
  2432. type 이 "xhr" 일 때만 유효하다. 기본 값은 true 이다. (1.3.7부터 지원)
  2433. </td>
  2434. </tr>
  2435. <tr>
  2436. <td style="font-weight:bold;">decode</td>
  2437. <td>Boolean</td>
  2438. <td>
  2439. type 이 "flash" 일 때 사용하며, 요청한 데이터 안에 utf-8 이 아닌 다른 인코딩이 되어 있을때 false 로 지정한다.<br>
  2440. 기본 값은 true 이다. (1.4.0부터 지원)
  2441. </td>
  2442. </tr>
  2443. <tr>
  2444. <td style="font-weight:bold;">postBody</td>
  2445. <td>Boolean</td>
  2446. <td>
  2447. 요청 시 서버로 전달할 데이터를 Body 영역에 전달할 지의 여부.<br>
  2448. type 이 "xhr" 이고 method 가 "get"이 아니어야 유효하며 REST 환경에서 사용된다.<br>
  2449. 기본값은 false 이다. (1.4.2부터 지원)
  2450. </td>
  2451. </tr>
  2452. </tbody>
  2453. </table>
  2454. * @constructor
  2455. * @description [Lite]
  2456. * @see <a href="http://dev.naver.com/projects/jindo/wiki/cross%20domain%20ajax">Cross Domain Ajax 이해</a>
  2457. * @author Kim, Taegon
  2458. *
  2459. * @example
  2460. // 'Get List' 버튼 클릭 시, 서버에서 데이터를 받아와 리스트를 구성하는 예제
  2461. // (1) 서버 페이지와 서비스 페이지가 같은 도메인에 있는 경우 - xhr
  2462. // [client.html]
  2463. <!DOCTYPE html>
  2464. <html>
  2465. <head>
  2466. <title>Ajax Sample</title>
  2467. <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  2468. <script type="text/javascript" language="javascript" src="lib/jindo.all.js"></script>
  2469. <script type="text/javascript" language="javascript">
  2470. function getList() {
  2471. var oAjax = new $Ajax('server.php', {
  2472. type : 'xhr',
  2473. method : 'get', // GET 방식으로 통신
  2474. onload : function(res){ // 요청이 완료되면 실행될 콜백 함수
  2475. $('list').innerHTML = res.text();
  2476. },
  2477. timeout : 3, // 3초 이내에 요청이 완료되지 않으면 ontimeout 실행 (생략 시 0)
  2478. ontimeout : function(){ // 타임 아웃이 발생하면 실행될 콜백 함수, 생략 시 타임 아웃이 되면 아무 처리도 하지 않음
  2479. alert("Timeout!");
  2480. },
  2481. async : true // 비동기로 호출하는 경우, 생략하면 true
  2482. });
  2483. oAjax.request();
  2484. }
  2485. </script>
  2486. </head>
  2487. <body>
  2488. <button onclick="getList(); return false;">Get List</button>
  2489. <ul id="list">
  2490. </ul>
  2491. </body>
  2492. </html>
  2493. // [server.php]
  2494. <?php
  2495. echo "<li>첫번째</li><li>두번째</li><li>세번째</li>";
  2496. ?>
  2497. * @example
  2498. // 'Get List' 버튼 클릭 시, 서버에서 데이터를 받아와 리스트를 구성하는 예제
  2499. // (2) 서버 페이지와 서비스 페이지가 같은 도메인에 있는 경우 - iframe
  2500. // [http://local.com/some/client.html]
  2501. <!DOCTYPE html>
  2502. <html>
  2503. <head>
  2504. <title>Ajax Sample</title>
  2505. <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  2506. <script type="text/javascript" language="javascript" src="lib/jindo.all.js"></script>
  2507. <script type="text/javascript" language="javascript">
  2508. function getList() {
  2509. var oAjax = new $Ajax('http://server.com/some/some.php', {
  2510. type : 'iframe',
  2511. method : 'get', // GET 방식으로 통신
  2512. // POST로 지정하면 원격 프록시 파일에서 some.php 로 요청 시에 POST 방식으로 처리
  2513. onload : function(res){ // 요청이 완료되면 실행될 콜백 함수
  2514. $('list').innerHTML = res.text();
  2515. },
  2516. // 로컬 프록시 파일의 경로.
  2517. // 반드시 정확한 경로를 지정해야 하며, 로컬 도메인의 경로라면 어디에 두어도 상관 없음
  2518. // (※ 원격 프록시 파일은 반드시 원격 도메인 서버의 도메인 루트 상에 두어야 함)
  2519. proxy : 'http://local.naver.com/some/ajax_local_callback.html'
  2520. });
  2521. oAjax.request();
  2522. }
  2523. </script>
  2524. </head>
  2525. <body>
  2526. <button onclick="getList(); return false;">Get List</button>
  2527. <ul id="list">
  2528. </ul>
  2529. </body>
  2530. </html>
  2531. // [http://server.com/some/some.php]
  2532. <?php
  2533. echo "<li>첫번째</li><li>두번째</li><li>세번째</li>";
  2534. ?>
  2535. * @example
  2536. // 'Get List' 버튼 클릭 시, 서버에서 데이터를 받아와 리스트를 구성하는 예제
  2537. // (3) 서버 페이지와 서비스 페이지가 같은 도메인에 있는 경우 - jsonp
  2538. // [http://local.com/some/client.html]
  2539. <!DOCTYPE html>
  2540. <html>
  2541. <head>
  2542. <title>Ajax Sample</title>
  2543. <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  2544. <script type="text/javascript" language="javascript" src="lib/jindo.all.js"></script>
  2545. <script type="text/javascript" language="javascript">
  2546. function getList(){
  2547. var oAjax = new $Ajax('http://server.com/some/some.php', {
  2548. type: 'jsonp',
  2549. method: 'get', // type 이 jsonp 이면 get 으로 지정하지 않아도 자동으로 get 으로 처리함 (생략가능)
  2550. jsonp_charset: 'utf-8', // 요청 시 사용할 <script> 인코딩 방식 (생략 시 utf-8)
  2551. onload: function(res){ // 요청이 완료되면 실행될 콜백 함수
  2552. var response = res.json();
  2553. var welList = $Element('list').empty();
  2554. for (var i = 0, nLen = response.length; i < nLen; i++) {
  2555. welList.append($("<li>" + response[i] + "</li>"));
  2556. }
  2557. },
  2558. callbackid: '12345', // 콜백 함수 이름에 사용할 아이디 값 (생략가능)
  2559. callbackname: 'ajax_callback_fn' // 서버에서 사용할 콜백 함수이름을 가지는 매개 변수 이름 (생략 시 '_callback')
  2560. });
  2561. oAjax.request();
  2562. }
  2563. </script>
  2564. </head>
  2565. <body>
  2566. <button onclick="getList(); return false;">Get List</button>
  2567. <ul id="list">
  2568. </ul>
  2569. </body>
  2570. </html>
  2571. // [http://server.com/some/some.php]
  2572. <?php
  2573. $callbackName = $_GET['ajax_callback_fn'];
  2574. echo $callbackName."(['첫번째','두번째','세번째'])";
  2575. ?>
  2576. * @example
  2577. // 'Get List' 버튼 클릭 시, 서버에서 데이터를 받아와 리스트를 구성하는 예제
  2578. // (4) 서버 페이지와 서비스 페이지가 같은 도메인에 있는 경우 - flash
  2579. // [http://local.com/some/client.html]
  2580. <!DOCTYPE html>
  2581. <html>
  2582. <head>
  2583. <title>Ajax Sample</title>
  2584. <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  2585. <script type="text/javascript" language="javascript" src="lib/jindo.all.js"></script>
  2586. <script type="text/javascript" language="javascript">
  2587. function getList(){
  2588. var oAjax = new $Ajax('http://server.com/some/some.php', {
  2589. type : 'flash',
  2590. method : 'get', // GET 방식으로 통신
  2591. sendheader : false, // 요청 헤더를 전송할지 여부. (생략 시 true)
  2592. decode : true, // 요청한 데이터 안에 utf-8 이 아닌 다른 인코딩이 되어 있을때 false. (생략 시 true)
  2593. onload : function(res){ // 요청이 완료되면 실행될 콜백 함수
  2594. $('list').innerHTML = res.text();
  2595. },
  2596. });
  2597. oAjax.request();
  2598. }
  2599. </script>
  2600. </head>
  2601. <body>
  2602. <script type="text/javascript">
  2603. $Ajax.SWFRequest.write("swf/ajax.swf"); // Ajax 호출을 하기 전에 반드시 플래시 객체를 초기화
  2604. </script>
  2605. <button onclick="getList(); return false;">Get List</button>
  2606. <ul id="list">
  2607. </ul>
  2608. </body>
  2609. </html>
  2610. // [http://server.com/some/some.php]
  2611. <?php
  2612. echo "<li>첫번째</li><li>두번째</li><li>세번째</li>";
  2613. ?>
  2614. */
  2615. jindo.$Ajax = function (url, option) {
  2616. var cl = arguments.callee;
  2617. if (!(this instanceof cl)) return new cl(url, option);
  2618. function _getXHR() {
  2619. if (window.XMLHttpRequest) {
  2620. return new XMLHttpRequest();
  2621. } else if (ActiveXObject) {
  2622. try {
  2623. return new ActiveXObject('MSXML2.XMLHTTP');
  2624. }catch(e) {
  2625. return new ActiveXObject('Microsoft.XMLHTTP');
  2626. }
  2627. return null;
  2628. }
  2629. }
  2630. var loc = location.toString();
  2631. var domain = '';
  2632. try { domain = loc.match(/^https?:\/\/([a-z0-9_\-\.]+)/i)[1]; } catch(e) {}
  2633. this._status = 0;
  2634. this._url = url;
  2635. this._options = new Object;
  2636. this._headers = new Object;
  2637. this._options = {
  2638. type :"xhr",
  2639. method :"post",
  2640. proxy :"",
  2641. timeout:0,
  2642. onload :function(req){},
  2643. onerror :null,
  2644. ontimeout:function(req){},
  2645. jsonp_charset : "utf-8",
  2646. callbackid : "",
  2647. callbackname : "",
  2648. sendheader : true,
  2649. async : true,
  2650. decode :true,
  2651. postBody :false
  2652. };
  2653. this.option(option);
  2654. /*
  2655. 테스트를 위해 우선 적용가능한 설정 객체가 존재하면 적용
  2656. */
  2657. if(jindo.$Ajax.CONFIG){
  2658. this.option(jindo.$Ajax.CONFIG);
  2659. }
  2660. var _opt = this._options;
  2661. _opt.type = _opt.type.toLowerCase();
  2662. _opt.method = _opt.method.toLowerCase();
  2663. if (typeof window.__jindo2_callback == "undefined") {
  2664. window.__jindo2_callback = new Array();
  2665. }
  2666. switch (_opt.type) {
  2667. case "put":
  2668. case "delete":
  2669. case "get":
  2670. case "post":
  2671. _opt.method = _opt.type;
  2672. _opt.type = "xhr";
  2673. case "xhr":
  2674. this._request = _getXHR();
  2675. break;
  2676. case "flash":
  2677. if(!jindo.$Ajax.SWFRequest) throw Error('Require jindo.$Ajax.SWFRequest');
  2678. this._request = new jindo.$Ajax.SWFRequest(jindo.$Fn(this.option,this).bind());
  2679. break;
  2680. case "jsonp":
  2681. if(!jindo.$Ajax.JSONPRequest) throw Error('Require jindo.$Ajax.JSONPRequest');
  2682. _opt.method = "get";
  2683. this._request = new jindo.$Ajax.JSONPRequest(jindo.$Fn(this.option,this).bind());
  2684. break;
  2685. case "iframe":
  2686. if(!jindo.$Ajax.FrameRequest) throw Error('Require jindo.$Ajax.FrameRequest');
  2687. this._request = new jindo.$Ajax.FrameRequest(jindo.$Fn(this.option,this).bind());
  2688. break;
  2689. }
  2690. };
  2691. /**
  2692. * @ignore
  2693. */
  2694. jindo.$Ajax.prototype._onload = (function(isIE) {
  2695. if(isIE){
  2696. return function(){
  2697. var bSuccess = this._request.readyState == 4 && this._request.status == 200;
  2698. var oResult;
  2699. if (this._request.readyState == 4) {
  2700. try {
  2701. if (this._request.status != 200 && typeof this._options.onerror == 'function'){
  2702. if(!this._request.status == 0){
  2703. this._options.onerror(jindo.$Ajax.Response(this._request));
  2704. }
  2705. }else{
  2706. if(!this._is_abort){
  2707. oResult = this._options.onload(jindo.$Ajax.Response(this._request));
  2708. }
  2709. }
  2710. }finally{
  2711. if(typeof this._oncompleted == 'function'){
  2712. this._oncompleted(bSuccess, oResult);
  2713. }
  2714. if (this._options.type == "xhr" ){
  2715. this.abort();
  2716. try { delete this._request.onload; } catch(e) { this._request.onload =undefined;}
  2717. }
  2718. delete this._request.onreadystatechange;
  2719. }
  2720. }
  2721. }
  2722. }else{
  2723. return function(){
  2724. var bSuccess = this._request.readyState == 4 && this._request.status == 200;
  2725. var oResult;
  2726. if (this._request.readyState == 4) {
  2727. try {
  2728. if (this._request.status != 200 && typeof this._options.onerror == 'function'){
  2729. this._options.onerror(jindo.$Ajax.Response(this._request));
  2730. }else{
  2731. oResult = this._options.onload(jindo.$Ajax.Response(this._request));
  2732. }
  2733. }finally{
  2734. this._status--;
  2735. if(typeof this._oncompleted == 'function'){
  2736. this._oncompleted(bSuccess, oResult);
  2737. }
  2738. }
  2739. }
  2740. }
  2741. }
  2742. })(/MSIE/.test(window.navigator.userAgent));
  2743. /**
  2744. * request 메서드는 Ajax 요청을 서버에 전송한다.<br>
  2745. * 요청에 사용할 매개 변수는 $Ajax 생성자에서 설정하거나 option 메서드에서 변경할 수 있다.<br>
  2746. *
  2747. * @remark 요청 타입(type)이 "flash" 이면 이 메소드를 실행하기 전에 body 태그 내부에서 $Ajax.SWFRequest.write() 명령어를 반드시 실행해야 한다.
  2748. *
  2749. * @param {Object} oData 서버로 전송할 데이터.
  2750. * @return {$Ajax} $Ajax 객체
  2751. * @description [Lite]
  2752. * @example
  2753. *
  2754. *
  2755. var ajax = $Ajax("http://www.remote.com", {
  2756. onload : function(res) {
  2757. // onload 핸들러
  2758. }
  2759. });
  2760. ajax.request( {key1:"value1", key2:"value2"} ); // 서버에 전송할 데이터를 매개변수로 넘긴다.
  2761. */
  2762. jindo.$Ajax.prototype.request = function(oData) {
  2763. this._status++;
  2764. var t = this;
  2765. var req = this._request;
  2766. var opt = this._options;
  2767. var data, v,a = [], data = "";
  2768. var _timer = null;
  2769. var url = this._url;
  2770. this._is_abort = false;
  2771. if( opt.postBody && opt.type.toUpperCase()=="XHR" && opt.method.toUpperCase()!="GET"){
  2772. if(typeof oData == 'string'){
  2773. data = oData;
  2774. }else{
  2775. data = jindo.$Json(oData).toString();
  2776. }
  2777. }else if (typeof oData == "undefined" || !oData) {
  2778. data = null;
  2779. } else {
  2780. for(var k in oData) {
  2781. if(oData.hasOwnProperty(k)){
  2782. v = oData[k];
  2783. if (typeof v == "function") v = v();
  2784. if (v instanceof Array || v instanceof jindo.$A) {
  2785. jindo.$A(v).forEach(function(value,index,array) {
  2786. a[a.length] = k+"="+encodeURIComponent(value);
  2787. });
  2788. } else {
  2789. a[a.length] = k+"="+encodeURIComponent(v);
  2790. }
  2791. }
  2792. }
  2793. data = a.join("&");
  2794. }
  2795. /*
  2796. XHR GET 방식 요청인 경우 URL에 파라미터 추가
  2797. */
  2798. if(data && opt.type.toUpperCase()=="XHR" && opt.method.toUpperCase()=="GET"){
  2799. if(url.indexOf('?')==-1){
  2800. url += "?";
  2801. } else {
  2802. url += "&";
  2803. }
  2804. url += data;
  2805. data = null;
  2806. }
  2807. req.open(opt.method.toUpperCase(), url, opt.async);
  2808. if(opt.type.toUpperCase()=="XHR"&&opt.method.toUpperCase()=="GET"&&/MSIE/.test(window.navigator.userAgent)){
  2809. /*
  2810. xhr인 경우 IE에서는 GET으로 보낼 때 브라우져에서 자체 cache하여 cache을 안되게 수정.
  2811. */
  2812. req.setRequestHeader("If-Modified-Since", "Thu, 1 Jan 1970 00:00:00 GMT");
  2813. }
  2814. if (opt.sendheader) {
  2815. if(!this._headers["Content-Type"]){
  2816. req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
  2817. }
  2818. req.setRequestHeader("charset", "utf-8");
  2819. for (var x in this._headers) {
  2820. if(this._headers.hasOwnProperty(x)){
  2821. if (typeof this._headers[x] == "function")
  2822. continue;
  2823. req.setRequestHeader(x, String(this._headers[x]));
  2824. }
  2825. }
  2826. }
  2827. var navi = navigator.userAgent;
  2828. if(req.addEventListener&&!(navi.indexOf("Opera") > -1)&&!(navi.indexOf("MSIE") > -1)){
  2829. /*
  2830. * opera 10.60에서 XMLHttpRequest에 addEventListener기 추가되었지만 정상적으로 동작하지 않아 opera는 무조건 dom1방식으로 지원함.
  2831. * IE9에서도 opera와 같은 문제가 있음.
  2832. */
  2833. if(this._loadFunc){ req.removeEventListener("load", this._loadFunc, false); }
  2834. this._loadFunc = function(rq){
  2835. clearTimeout(_timer);
  2836. _timer = undefined;
  2837. t._onload(rq);
  2838. }
  2839. req.addEventListener("load", this._loadFunc, false);
  2840. }else{
  2841. if (typeof req.onload != "undefined") {
  2842. req.onload = function(rq){
  2843. if(req.readyState == 4 && !t._is_abort){
  2844. clearTimeout(_timer);
  2845. _timer = undefined;
  2846. t._onload(rq);
  2847. }
  2848. };
  2849. } else {
  2850. /*
  2851. * IE6에서는 onreadystatechange가 동기적으로 실행되어 timeout이벤트가 발생안됨.
  2852. * 그래서 interval로 체크하여 timeout이벤트가 정상적으로 발생되도록 수정. 비동기 방식일때만
  2853. */
  2854. if(window.navigator.userAgent.match(/(?:MSIE) ([0-9.]+)/)[1]==6&&opt.async){
  2855. var onreadystatechange = function(rq){
  2856. if(req.readyState == 4 && !t._is_abort){
  2857. if(_timer){
  2858. clearTimeout(_timer);
  2859. _timer = undefined;
  2860. }
  2861. t._onload(rq);
  2862. clearInterval(t._interval);
  2863. t._interval = undefined;
  2864. }
  2865. };
  2866. this._interval = setInterval(onreadystatechange,300);
  2867. }else{
  2868. req.onreadystatechange = function(rq){
  2869. if(req.readyState == 4){
  2870. clearTimeout(_timer);
  2871. _timer = undefined;
  2872. t._onload(rq);
  2873. }
  2874. };
  2875. }
  2876. }
  2877. }
  2878. if (opt.timeout > 0) {
  2879. // if(this._interval)clearInterval(this._interval);
  2880. if(this._timer) clearTimeout(this._timer);
  2881. _timer = setTimeout(function(){
  2882. t._is_abort = true;
  2883. if(t._interval){
  2884. clearInterval(t._interval);
  2885. t._interval = undefined;
  2886. }
  2887. try{ req.abort(); }catch(e){};
  2888. opt.ontimeout(req);
  2889. if(typeof t._oncompleted == 'function') t._oncompleted(false);
  2890. }, opt.timeout * 1000 );
  2891. this._timer = _timer;
  2892. }
  2893. /*
  2894. * test을 하기 위한 url
  2895. */
  2896. this._test_url = url;
  2897. req.send(data);
  2898. return this;
  2899. };
  2900. /**
  2901. * isIdle 메서드는 Ajax 객체가 현재 요청 대기 상태인지 확인한다.
  2902. * @return {Boolean} 현재 대기 중이면 true 를, 그렇지 않으면 false를 리턴한다.
  2903. * @since 1.3.5 부터 사용 가능
  2904. * @description [Lite]
  2905. * @example
  2906. var ajax = $Ajax("http://www.remote.com",{
  2907. onload : function(res){
  2908. // onload 핸들러
  2909. }
  2910. });
  2911. if(ajax.isIdle()) ajax.request();
  2912. */
  2913. jindo.$Ajax.prototype.isIdle = function(){
  2914. return this._status==0;
  2915. }
  2916. /**
  2917. * abort 메서드는 서버로 전송한 Ajax 요청을 취소한다. Ajax 요청의 응답 시간이 길거나 강제로 Ajax 요청을 취소할 경우 사용한다.
  2918. * @return {$Ajax} 전송을 취소한 $Ajax 객체
  2919. * @description [Lite]
  2920. * @example
  2921. var ajax = $Ajax("http://www.remote.com", {
  2922. timeout : 3,
  2923. ontimeout : function() {
  2924. stopRequest();
  2925. }
  2926. onload : function(res) {
  2927. // onload 핸들러
  2928. }
  2929. }).request( {key1:"value1", key2:"value2"} );
  2930. function stopRequest() {
  2931. ajax.abort();
  2932. }
  2933. */
  2934. jindo.$Ajax.prototype.abort = function() {
  2935. try {
  2936. if(this._interval) clearInterval(this._interval);
  2937. if(this._timer) clearTimeout(this._timer);
  2938. this._interval = undefined;
  2939. this._timer = undefined;
  2940. this._is_abort = true;
  2941. this._request.abort();
  2942. }finally{
  2943. this._status--;
  2944. }
  2945. return this;
  2946. };
  2947. /**
  2948. * option 메서드는 Ajax 요청에서 사용한 정보를 가져오거나 혹은 설정한다.<br>
  2949. * 설정하려면 이름과 값을, 혹은 이름과 값을 원소로 가지는 하나의 객체를 매개 변수로 사용한다.<br>
  2950. * 이름과 값을 원소로 가지는 객체를 사용하면 두 개 이상의 정보를 한 번에 설정할 수 있다.
  2951. *
  2952. * @param {String | Object} name <br>
  2953. * 매개 변수의 타입은 문자열 혹은 객체를 사용한다.<br>
  2954. * <br>
  2955. * 문자열을 매개 변수로 사용하면 다음과 같이 동작한다..<br>
  2956. * 1. value 매개 변수를 생략하면 이름에 해당하는 $Ajax의 속성 값을 리턴한다.<br>
  2957. * 2. value 매개 변수를 설정하면 이름에 해당하는 $Ajax의 속성에 value를 값으로 설정한다.<br>
  2958. * <br>
  2959. * 객체인 경우에는 속성 이름으로 정보를 찾아 속성의 값으로 설정한다. 객체에 두 개 이상의 속성을 지정하면 여러 속성 값을 한 번에 설정할 수 있다.
  2960. * @param {String} [value] 새로 설정할 정보의 값. name 매개 변수가 문자열인 경우에만 사용된다.
  2961. * @return {String|$Ajax} 정보의 값을 가져올 때는 문자열을, 값을 설정할 때는 $Ajax 객체를 리턴한다.
  2962. * @description [Lite]
  2963. * @example
  2964. var ajax = $Ajax("http://www.remote.com", {
  2965. type : "xhr",
  2966. method : "get",
  2967. onload : function(res) {
  2968. // onload 핸들러
  2969. }
  2970. });
  2971. var request_type = ajax.option("type"); // type 인 xhr 을 리턴한다.
  2972. ajax.option("method", "post"); // method 를 post 로 설정한다.
  2973. ajax.option( { timeout : 0, onload : handler_func } ); // timeout 을 으로, onload 를 handler_func 로 설정한다.
  2974. */
  2975. jindo.$Ajax.prototype.option = function(name, value) {
  2976. if (typeof name == "undefined") return "";
  2977. if (typeof name == "string") {
  2978. if (typeof value == "undefined") return this._options[name];
  2979. this._options[name] = value;
  2980. return this;
  2981. }
  2982. try {
  2983. for(var x in name){
  2984. if(name.hasOwnProperty(x))
  2985. this._options[x] = name[x]
  2986. }
  2987. } catch(e) {};
  2988. return this;
  2989. };
  2990. /**
  2991. * header 메서드는 Ajax 요청에서 사용할 HTTP 요청 헤더를 가져오거나 설정한다.<br>
  2992. * 헤더를 설정하려면 헤더의 이름과 값을 각각 매개 변수로 사용하거나, 헤더의 이름과 값을 원소로 가지는 객체를 매개 변수로 사용한다. 만약 여러 개의 속성을 가진 객체를 사용하면 두 개 이상의 헤더를 한 번에 설정할 수 있다.<br>
  2993. * 헤더에서 특정 속성의 값을 가져오려면 속성의 이름을 매개 변수로 사용한다.
  2994. *
  2995. * @param {String|Object} name <br>
  2996. * 매개 변수의 타입은 문자열 혹은 객체를 사용한다.<br>
  2997. * <br>
  2998. * 문자열을 매개 변수로 사용하면 다음과 같이 동작한다. <br>
  2999. * 1. value 매개 변수를 생략하면 HTTP 요청 헤더에서 문자열과 일치하는 속성값을 찾는다.<br>
  3000. * 2. value 매개 변수를 설정하면 HTTP 요청 헤더에서 문자열과 일치하는 속성에 value를 값으로 설정한다.<br>
  3001. * <br>
  3002. * 객체인 경우에는 속성 이름으로 정보를 찾아 속성의 값으로 설정한다. 객체에 두 개 이상의 속성을 지정하면 HTTP 요청 헤더에서 여러 속성 값을 한 번에 설정할 수 있다.
  3003. * @param {Value} [value] 설정할 헤더 값. name 매개 변수가 문자열인 경우에만 사용된다.
  3004. * @return {String|$Ajax} 정보의 값을 가져올 때는 문자열을, 값을 설정할 때는 $Ajax 객체를 리턴한다.
  3005. * @description [Lite]
  3006. * @example
  3007. var customheader = ajax.header("myHeader"); // HTTP 요청 헤더에서 myHeader 의 값
  3008. ajax.header( "myHeader", "someValue" ); // HTTP 요청 헤더의 myHeader 를 someValue 로 설정한다.
  3009. ajax.header( { anotherHeader : "someValue2" } ); // HTTP 요청 헤더의 anotherHeader 를 someValue2 로 설정한다.
  3010. */
  3011. jindo.$Ajax.prototype.header = function(name, value) {
  3012. if (typeof name == "undefined") return "";
  3013. if (typeof name == "string") {
  3014. if (typeof value == "undefined") return this._headers[name];
  3015. this._headers[name] = value;
  3016. return this;
  3017. }
  3018. try {
  3019. for (var x in name) {
  3020. if (name.hasOwnProperty(x))
  3021. this._headers[x] = name[x]
  3022. }
  3023. } catch(e) {};
  3024. return this;
  3025. };
  3026. /**
  3027. * Ajax 응답 객체를 래핑하여 응답을 가져오는데 유용한 메서드를 제공한다.
  3028. * @class $Ajax.Response 객체를 생성하여 리턴한다.<br>
  3029. * $Ajax 객체에서 request 요청 처리 완료 후, 생성되며 $Ajax 생성 시에 설정한 onload 콜백 함수의 매개 변수로 전달된다.
  3030. * @constructor
  3031. * @param {Object} req 요청 객체
  3032. * @description [Lite]
  3033. */
  3034. jindo.$Ajax.Response = function(req) {
  3035. if (this === jindo.$Ajax) return new jindo.$Ajax.Response(req);
  3036. this._response = req;
  3037. };
  3038. /**
  3039. * 응답을 XML 객체로 리턴한다.
  3040. * @return {Object} 응답 XML 객체. XHR의 responseXML 과 유사하다.
  3041. * @description [Lite]
  3042. *
  3043. * @example
  3044. // some.xml
  3045. <?xml version="1.0" encoding="utf-8"?>
  3046. <data>
  3047. <li>첫번째</li>
  3048. <li>두번째</li>
  3049. <li>세번째</li>
  3050. </data>
  3051. // client.html
  3052. var oAjax = new $Ajax('some.xml', {
  3053. type : 'xhr',
  3054. method : 'get',
  3055. onload : function(res){
  3056. var elData = cssquery.getSingle('data', res.xml()); // 응답을 XML 객체로 리턴한다
  3057. $('list').innerHTML = elData.firstChild.nodeValue;
  3058. },
  3059. }).request();
  3060. */
  3061. jindo.$Ajax.Response.prototype.xml = function() {
  3062. return this._response.responseXML;
  3063. };
  3064. /**
  3065. * 응답을 문자열로 리턴한다.
  3066. * @return {String} 응답 문자열. XHR의 responseText 와 유사하다.
  3067. * @description [Lite]
  3068. *
  3069. * @example
  3070. // some.php
  3071. <?php
  3072. echo "<li>첫번째</li><li>두번째</li><li>세번째</li>";
  3073. ?>
  3074. // client.html
  3075. var oAjax = new $Ajax('some.xml', {
  3076. type : 'xhr',
  3077. method : 'get',
  3078. onload : function(res){
  3079. $('list').innerHTML = res.text(); // 응답을 문자열로 리턴한다
  3080. },
  3081. }).request();
  3082. */
  3083. jindo.$Ajax.Response.prototype.text = function() {
  3084. return this._response.responseText;
  3085. };
  3086. /**
  3087. * HTTP 응답 코드를 리턴한다.
  3088. * @return {Number} 응답 코드. http 응답 코드표를 참고한다.
  3089. * @description [Lite]
  3090. *
  3091. * @example
  3092. var oAjax = new $Ajax('some.php', {
  3093. type : 'xhr',
  3094. method : 'get',
  3095. onload : function(res){
  3096. if(res.status() == 200){ // HTTP 응답 코드를 확인한다.
  3097. $('list').innerHTML = res.text();
  3098. }
  3099. },
  3100. }).request();
  3101. */
  3102. jindo.$Ajax.Response.prototype.status = function() {
  3103. return this._response.status;
  3104. };
  3105. /**
  3106. * 응답의 readyState 를 리턴한다.
  3107. * @return {Number} readyState.
  3108. * @description [Lite]
  3109. *
  3110. * @example
  3111. var oAjax = new $Ajax('some.php', {
  3112. type : 'xhr',
  3113. method : 'get',
  3114. onload : function(res){
  3115. if(res.readyState() == 4){ // 응답의 readyState 를 확인한다.
  3116. $('list').innerHTML = res.text();
  3117. }
  3118. },
  3119. }).request();
  3120. */
  3121. jindo.$Ajax.Response.prototype.readyState = function() {
  3122. return this._response.readyState;
  3123. };
  3124. /**
  3125. * 응답을 JSON 객체로 리턴한다.
  3126. * @return {Object} 응답 JSON 객체. <br>
  3127. * 응답 문자열을 자동으로 JSON 객체로 변환하여 리턴한다. 변환 과정에서 오류가 발생하면 빈 객체를 리턴한다.
  3128. * @description [Lite]
  3129. *
  3130. * @example
  3131. // some.php
  3132. <?php
  3133. echo "['첫번째', '두번째', '세번째']";
  3134. ?>
  3135. // client.html
  3136. var oAjax = new $Ajax('some.php', {
  3137. type : 'xhr',
  3138. method : 'get',
  3139. onload : function(res){
  3140. var welList = $Element('list').empty();
  3141. var jsonData = res.json(); // 응답을 JSON 객체로 리턴한다
  3142. for(var i = 0, nLen = jsonData.length; i < nLen; i++){
  3143. welList.append($("<li>" + jsonData[i] + "</li>"));
  3144. }
  3145. },
  3146. }).request();
  3147. */
  3148. jindo.$Ajax.Response.prototype.json = function() {
  3149. if (this._response.responseJSON) {
  3150. return this._response.responseJSON;
  3151. } else if (this._response.responseText) {
  3152. try {
  3153. return eval("("+this._response.responseText+")");
  3154. } catch(e) {
  3155. return {};
  3156. }
  3157. }
  3158. return {};
  3159. };
  3160. /**
  3161. * 응답 헤더를 가져온다. 매개 변수를 전달하지 않으면 헤더 전체를 리턴한다.
  3162. * @param {String} name 가져올 응답 헤더의 이름
  3163. * @return {String|Object} 매개 변수가 있을 때는 해당하는 헤더 값을, 그렇지 않으면 헤더 전체를 리턴한다.
  3164. * @description [Lite]
  3165. *
  3166. * @example
  3167. var oAjax = new $Ajax('some.php', {
  3168. type : 'xhr',
  3169. method : 'get',
  3170. onload : function(res){
  3171. res.header(); // 응답 헤더 전체를 리턴한다.
  3172. res.header("Content-Length") // 응답 헤더에서 "Content-Length" 의 값을 리턴한다.
  3173. },
  3174. }).request();
  3175. */
  3176. jindo.$Ajax.Response.prototype.header = function(name) {
  3177. if (typeof name == "string") return this._response.getResponseHeader(name);
  3178. return this._response.getAllResponseHeaders();
  3179. };
  3180. /**
  3181. * @fileOverview $Ajax의 확장 메서드를 정의한 파일
  3182. * @name Ajax.extend.js
  3183. */
  3184. /**
  3185. * Ajax 요청 타입 별로 요청 객체를 생성하기 위한 상위 객체로 사용한다.
  3186. * @class Ajax 요청 객체의 기본 객체이다.
  3187. */
  3188. jindo.$Ajax.RequestBase = jindo.$Class({
  3189. _respHeaderString : "",
  3190. callbackid:"",
  3191. callbackname:"",
  3192. responseXML : null,
  3193. responseJSON : null,
  3194. responseText : "",
  3195. status : 404,
  3196. readyState : 0,
  3197. $init : function(fpOption){},
  3198. onload : function(){},
  3199. abort : function(){},
  3200. open : function(){},
  3201. send : function(){},
  3202. setRequestHeader : function(sName, sValue) {
  3203. this._headers[sName] = sValue;
  3204. },
  3205. getResponseHeader : function(sName) {
  3206. return this._respHeaders[sName] || "";
  3207. },
  3208. getAllResponseHeaders : function() {
  3209. return this._respHeaderString;
  3210. },
  3211. _getCallbackInfo : function() {
  3212. var id = "";
  3213. if(this.option("callbackid")!="") {
  3214. var idx = 0;
  3215. do {
  3216. id = "_" + this.option("callbackid") + "_"+idx;
  3217. idx++;
  3218. } while (window.__jindo2_callback[id]);
  3219. }else{
  3220. do {
  3221. id = "_" + Math.floor(Math.random() * 10000);
  3222. } while (window.__jindo2_callback[id]);
  3223. }
  3224. if(this.option("callbackname") == ""){
  3225. this.option("callbackname","_callback");
  3226. }
  3227. return {callbackname:this.option("callbackname"),id:id,name:"window.__jindo2_callback."+id};
  3228. }
  3229. });
  3230. /**
  3231. * $Ajax.JSONPRequest 객체를 생성하여 리턴한다.
  3232. * @extends $Ajax.RequestBase
  3233. * @class Ajax 요청 타입(type)이 jsonp 인 요청 객체를 생성하며, jindo.$Ajax 생성자에서 요청 객체 생성 시 사용한다.
  3234. */
  3235. jindo.$Ajax.JSONPRequest = jindo.$Class({
  3236. _headers : {},
  3237. _respHeaders : {},
  3238. _script : null,
  3239. _onerror : null,
  3240. $init : function(fpOption){
  3241. this.option = fpOption;
  3242. },
  3243. _callback : function(data) {
  3244. if (this._onerror) {
  3245. clearTimeout(this._onerror);
  3246. this._onerror = null;
  3247. }
  3248. var self = this;
  3249. this.responseJSON = data;
  3250. this.onload(this);
  3251. setTimeout(function(){ self.abort() }, 10);
  3252. },
  3253. abort : function() {
  3254. if (this._script) {
  3255. try {
  3256. this._script.parentNode.removeChild(this._script);
  3257. }catch(e){
  3258. };
  3259. }
  3260. },
  3261. open : function(method, url) {
  3262. this.responseJSON = null;
  3263. this._url = url;
  3264. },
  3265. send : function(data) {
  3266. var t = this;
  3267. var info = this._getCallbackInfo();
  3268. var head = document.getElementsByTagName("head")[0];
  3269. this._script = jindo.$("<script>");
  3270. this._script.type = "text/javascript";
  3271. this._script.charset = this.option("jsonp_charset");
  3272. if (head) {
  3273. head.appendChild(this._script);
  3274. } else if (document.body) {
  3275. document.body.appendChild(this._script);
  3276. }
  3277. window.__jindo2_callback[info.id] = function(data){
  3278. try {
  3279. t.readyState = 4;
  3280. t.status = 200;
  3281. t._callback(data);
  3282. } finally {
  3283. delete window.__jindo2_callback[info.id];
  3284. }
  3285. };
  3286. var agent = jindo.$Agent(navigator);
  3287. if (agent.navigator().ie || agent.navigator().opera) {
  3288. this._script.onreadystatechange = function(){
  3289. if (this.readyState == 'loaded'){
  3290. if (!t.responseJSON) {
  3291. t.readyState = 4;
  3292. t.status = 500;
  3293. t._onerror = setTimeout(function(){t._callback(null);}, 200);
  3294. }
  3295. this.onreadystatechange = null;
  3296. }
  3297. };
  3298. } else {
  3299. this._script.onload = function(){
  3300. if (!t.responseJSON) {
  3301. t.readyState = 4;
  3302. t.status = 500;
  3303. t._onerror = setTimeout(function(){t._callback(null);}, 200);
  3304. }
  3305. this.onload = null;
  3306. this.onerror = null;
  3307. };
  3308. this._script.onerror = function(){
  3309. if (!t.responseJSON) {
  3310. t.readyState = 4;
  3311. t.status = 404;
  3312. t._onerror = setTimeout(function(){t._callback(null);}, 200);
  3313. }
  3314. this.onerror = null;
  3315. this.onload = null;
  3316. };
  3317. }
  3318. var delimiter = "&";
  3319. if(this._url.indexOf('?')==-1){
  3320. delimiter = "?";
  3321. }
  3322. if (data) {
  3323. data = "&" + data;
  3324. }else{
  3325. data = "";
  3326. }
  3327. //test url for spec.
  3328. this._test_url = this._url+delimiter+info.callbackname+"="+info.name+data;
  3329. this._script.src = this._url+delimiter+info.callbackname+"="+info.name+data;
  3330. }
  3331. }).extend(jindo.$Ajax.RequestBase);
  3332. /**
  3333. * $Ajax.SWFRequest 객체를 생성하여 리턴한다.
  3334. * @extends $Ajax.RequestBase
  3335. * @class Ajax 요청 타입(type)이 flash 인 요청 객체를 생성하며, jindo.$Ajax 생성자에서 요청 객체 생성 시 사용한다.
  3336. */
  3337. jindo.$Ajax.SWFRequest = jindo.$Class({
  3338. $init : function(fpOption){
  3339. this.option = fpOption;
  3340. },
  3341. _headers : {},
  3342. _respHeaders : {},
  3343. _getFlashObj : function(){
  3344. var navi = jindo.$Agent(window.navigator).navigator();
  3345. var obj;
  3346. if (navi.ie&&navi.version==9) {
  3347. obj = document.getElementById(jindo.$Ajax.SWFRequest._tmpId);
  3348. }else{
  3349. obj = window.document[jindo.$Ajax.SWFRequest._tmpId];
  3350. }
  3351. return(this._getFlashObj = function(){
  3352. return obj;
  3353. })();
  3354. },
  3355. _callback : function(status, data, headers){
  3356. this.readyState = 4;
  3357. /*
  3358. 하위 호환을 위해 status가 boolean 값인 경우도 처리
  3359. */
  3360. if( (typeof status).toLowerCase() == 'number'){
  3361. this.status = status;
  3362. }else{
  3363. if(status==true) this.status=200;
  3364. }
  3365. if (this.status==200) {
  3366. if (typeof data == "string") {
  3367. try {
  3368. this.responseText = this.option("decode")?decodeURIComponent(data):data;
  3369. if(!this.responseText || this.responseText=="") {
  3370. this.responseText = data;
  3371. }
  3372. } catch(e) {
  3373. /*
  3374. 데이터 안에 utf-8이 아닌 다른 인코딩일때 디코딩을 안하고 바로 text에 저장.
  3375. */
  3376. if(e.name == "URIError"){
  3377. this.responseText = data;
  3378. if(!this.responseText || this.responseText=="") {
  3379. this.responseText = data;
  3380. }
  3381. }
  3382. }
  3383. }
  3384. /*
  3385. 콜백코드는 넣었지만, 아직 SWF에서 응답헤더 지원 안함
  3386. */
  3387. if(typeof headers == "object"){
  3388. this._respHeaders = headers;
  3389. }
  3390. }
  3391. this.onload(this);
  3392. },
  3393. open : function(method, url) {
  3394. var re = /https?:\/\/([a-z0-9_\-\.]+)/i;
  3395. this._url = url;
  3396. this._method = method;
  3397. },
  3398. send : function(data) {
  3399. this.responseXML = false;
  3400. this.responseText = "";
  3401. var t = this;
  3402. var dat = {};
  3403. var info = this._getCallbackInfo();
  3404. var swf = this._getFlashObj()
  3405. function f(arg) {
  3406. switch(typeof arg){
  3407. case "string":
  3408. return '"'+arg.replace(/\"/g, '\\"')+'"';
  3409. break;
  3410. case "number":
  3411. return arg;
  3412. break;
  3413. case "object":
  3414. var ret = "", arr = [];
  3415. if (arg instanceof Array) {
  3416. for(var i=0; i < arg.length; i++) {
  3417. arr[i] = f(arg[i]);
  3418. }
  3419. ret = "["+arr.join(",")+"]";
  3420. } else {
  3421. for(var x in arg) {
  3422. if(arg.hasOwnProperty(x)){
  3423. arr[arr.length] = f(x)+":"+f(arg[x]);
  3424. }
  3425. }
  3426. ret = "{"+arr.join(",")+"}";
  3427. }
  3428. return ret;
  3429. default:
  3430. return '""';
  3431. }
  3432. }
  3433. data = (data || "").split("&");
  3434. for(var i=0; i < data.length; i++) {
  3435. pos = data[i].indexOf("=");
  3436. key = data[i].substring(0,pos);
  3437. val = data[i].substring(pos+1);
  3438. dat[key] = decodeURIComponent(val);
  3439. }
  3440. this._current_callback_id = info.id
  3441. window.__jindo2_callback[info.id] = function(success, data){
  3442. try {
  3443. t._callback(success, data);
  3444. } finally {
  3445. delete window.__jindo2_callback[info.id];
  3446. }
  3447. };
  3448. var oData = {
  3449. url : this._url,
  3450. type : this._method,
  3451. data : dat,
  3452. charset : "UTF-8",
  3453. callback : info.name,
  3454. header_json : this._headers
  3455. };
  3456. swf.requestViaFlash(f(oData));
  3457. },
  3458. abort : function(){
  3459. if(this._current_callback_id){
  3460. window.__jindo2_callback[this._current_callback_id] = function(){
  3461. delete window.__jindo2_callback[info.id];
  3462. }
  3463. }
  3464. }
  3465. }).extend(jindo.$Ajax.RequestBase);
  3466. /**
  3467. * Ajax 요청 타입(type)이 flash 일 때, request 메소드가 호출되기 전에 반드시 한 번 실행해야 한다.<br>
  3468. * <br>
  3469. * 요청 타입이 flash 이면 모든 통신은 플래시 객체를 통하여 주고 받으며 Ajax 호출을 하기 전에 반드시 플래시 객체를 초기화해야한다.<br>
  3470. * $Ajax.SWFRequest.write 메서드를 호출하면 통신을 위한 플래시 객체를 문서 내에 추가한다.
  3471. *
  3472. * @param {String} [swf_path] 통신을 담당할 플래시 파일의 경로. 생략하면 기본 값은 "./ajax.swf" 이다.
  3473. *
  3474. * @remark 해당 메서드는 <body> 태그 내에 작성되어야 한다.
  3475. * @remark 반드시 한 번 실행해야 한다. 두 번 이상 실행해도 문제가 발생한다.
  3476. *
  3477. * @see $Ajax#request
  3478. */
  3479. jindo.$Ajax.SWFRequest.write = function(swf_path) {
  3480. if(typeof swf_path == "undefined") swf_path = "./ajax.swf";
  3481. jindo.$Ajax.SWFRequest._tmpId = 'tmpSwf'+(new Date()).getMilliseconds()+Math.floor(Math.random()*100000);
  3482. var activeCallback = "jindo.$Ajax.SWFRequest.loaded";
  3483. jindo.$Ajax._checkFlashLoad();
  3484. document.write('<div style="position:absolute;top:-1000px;left:-1000px"><object id="'+jindo.$Ajax.SWFRequest._tmpId+'" width="1" height="1" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"><param name="movie" value="'+swf_path+'"><param name = "FlashVars" value = "activeCallback='+activeCallback+'" /><param name = "allowScriptAccess" value = "always" /><embed name="'+jindo.$Ajax.SWFRequest._tmpId+'" src="'+swf_path+'" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" width="1" height="1" allowScriptAccess="always" swLiveConnect="true" FlashVars="activeCallback='+activeCallback+'"></embed></object></div>');
  3485. };
  3486. /**
  3487. * @ignore
  3488. */
  3489. jindo.$Ajax._checkFlashLoad = function(){
  3490. jindo.$Ajax._checkFlashKey = setTimeout(function(){
  3491. // throw new Error("Check your flash file!. Unload flash on a page.");
  3492. // [SMARTEDITORSUS-334] Flash 를 지원하지 않는 환경(ex. iOS)에서 경고창을 띄우지 않도록 임시적으로 주석 처리함
  3493. // alert("Check your flash file!. Unload flash on a page.");
  3494. },5000);
  3495. jindo.$Ajax._checkFlashLoad = function(){}
  3496. }
  3497. /**
  3498. * flash가 로딩 되었는지 확인 하는 변수.
  3499. */
  3500. jindo.$Ajax.SWFRequest.activeFlash = false;
  3501. /**
  3502. * flash에서 로딩 후 실행 시키는 함수.
  3503. * @ignore
  3504. */
  3505. jindo.$Ajax.SWFRequest.loaded = function(){
  3506. clearTimeout(jindo.$Ajax._checkFlashKey);
  3507. jindo.$Ajax.SWFRequest.activeFlash = true;
  3508. }
  3509. /**
  3510. * $Ajax.FrameRequest 객체를 생성하여 리턴한다.
  3511. * @extends $Ajax.RequestBase
  3512. * @class Ajax 요청 타입(type)이 iframe 인 요청 객체를 생성하며, jindo.$Ajax 생성자에서 요청 객체 생성 시 사용한다.
  3513. */
  3514. jindo.$Ajax.FrameRequest = jindo.$Class({
  3515. _headers : {},
  3516. _respHeaders : {},
  3517. _frame : null,
  3518. _domain : "",
  3519. $init : function(fpOption){
  3520. this.option = fpOption;
  3521. },
  3522. _callback : function(id, data, header) {
  3523. var self = this;
  3524. this.readyState = 4;
  3525. this.status = 200;
  3526. this.responseText = data;
  3527. this._respHeaderString = header;
  3528. header.replace(/^([\w\-]+)\s*:\s*(.+)$/m, function($0,$1,$2) {
  3529. self._respHeaders[$1] = $2;
  3530. });
  3531. this.onload(this);
  3532. setTimeout(function(){ self.abort() }, 10);
  3533. },
  3534. abort : function() {
  3535. if (this._frame) {
  3536. try {
  3537. this._frame.parentNode.removeChild(this._frame);
  3538. } catch(e) {
  3539. }
  3540. }
  3541. },
  3542. open : function(method, url) {
  3543. var re = /https?:\/\/([a-z0-9_\-\.]+)/i;
  3544. var dom = document.location.toString().match(re);
  3545. this._method = method;
  3546. this._url = url;
  3547. this._remote = String(url).match(/(https?:\/\/[a-z0-9_\-\.]+)(:[0-9]+)?/i)[0];
  3548. this._frame = null;
  3549. this._domain = (dom[1] != document.domain)?document.domain:"";
  3550. },
  3551. send : function(data) {
  3552. this.responseXML = "";
  3553. this.responseText = "";
  3554. var t = this;
  3555. var re = /https?:\/\/([a-z0-9_\-\.]+)/i;
  3556. var info = this._getCallbackInfo();
  3557. var url;
  3558. var _aStr = [];
  3559. _aStr.push(this._remote+"/ajax_remote_callback.html?method="+this._method);
  3560. var header = new Array;
  3561. window.__jindo2_callback[info.id] = function(id, data, header){
  3562. try {
  3563. t._callback(id, data, header);
  3564. } finally {
  3565. delete window.__jindo2_callback[info.id];
  3566. }
  3567. };
  3568. for(var x in this._headers) {
  3569. if(this._headers.hasOwnProperty(x)){
  3570. header[header.length] = "'"+x+"':'"+this._headers[x]+"'";
  3571. }
  3572. }
  3573. header = "{"+header.join(",")+"}";
  3574. _aStr.push("&id="+info.id);
  3575. _aStr.push("&header="+encodeURIComponent(header));
  3576. _aStr.push("&proxy="+encodeURIComponent(this.option("proxy")));
  3577. _aStr.push("&domain="+this._domain);
  3578. _aStr.push("&url="+encodeURIComponent(this._url.replace(re, "")));
  3579. _aStr.push("#"+encodeURIComponent(data));
  3580. var fr = this._frame = jindo.$("<iframe>");
  3581. fr.style.position = "absolute";
  3582. fr.style.visibility = "hidden";
  3583. fr.style.width = "1px";
  3584. fr.style.height = "1px";
  3585. var body = document.body || document.documentElement;
  3586. if (body.firstChild){
  3587. body.insertBefore(fr, body.firstChild);
  3588. }else{
  3589. body.appendChild(fr);
  3590. }
  3591. fr.src = _aStr.join("");
  3592. }
  3593. }).extend(jindo.$Ajax.RequestBase);
  3594. /**
  3595. * $Ajax 객체를 순서대로 호출할 수 있는 기능을 제공한다.
  3596. * @class $Ajax.Queue는 Ajax 요청을 큐에 담아 큐에 들어온 순서대로 처리한다.
  3597. * @param {Object} option $Ajax.Queue 에서 서버에 요청할 때 사용하는 다양한 정보를 정의한다.
  3598. <ul>
  3599. <li>
  3600. async : 비동기/동기 요청 여부를 설정한다. 비동기인 경우 true 이며, 기본 값은 false 이다.
  3601. </li>
  3602. <li>
  3603. useResultAsParam : 이전에 처리된 요청의 결과를 다음 요청에 매개 변수로 넘길지 여부를 설정한다. 요청 결과를 넘기면 true 이며, 기본 값은 false 이다.
  3604. </li>
  3605. <li>
  3606. stopOnFailure : 이전 요청이 실패하는 경우 다음 요청을 멈출지 여부를 설정한다. 멈춘다면 true 이며, 기본 값은 false 이다.
  3607. </li>
  3608. </ul>
  3609. * @constructor
  3610. * @since 1.3.7
  3611. *
  3612. * @example
  3613. // $Ajax 요청 큐를 생성한다.
  3614. var oAjaxQueue = new $Ajax.Queue({
  3615. useResultAsParam : true
  3616. });
  3617. */
  3618. jindo.$Ajax.Queue = function (option) {
  3619. var cl = arguments.callee;
  3620. if (!(this instanceof cl)){ return new cl(option);}
  3621. this._options = {
  3622. async : false,
  3623. useResultAsParam : false,
  3624. stopOnFailure : false
  3625. };
  3626. this.option(option);
  3627. this._queue = [];
  3628. }
  3629. /**
  3630. * $Ajax.Queue 의 옵션을 가져오거나 설정한다.
  3631. * @param {Object} name 옵션의 이름
  3632. * @param {Object} [value] 옵션의 값. 옵션을 설정하는 경우에는 값을 지정한다.
  3633. * @return {Value | $Ajax.Queue} 값을 가져오는 경우 해당 값을, 설정하는 경우 $Ajax.Queue 객체를 리턴한다.
  3634. * @example
  3635. var oAjaxQueue = new $Ajax.Queue({
  3636. useResultAsParam : true
  3637. });
  3638. oAjaxQueue.option("useResultAsParam"); // useResultAsParam 옵션 값인 true 를 리턴한다.
  3639. oAjaxQueue.option("async", true); // async 옵션을 true 로 설정한다.
  3640. */
  3641. jindo.$Ajax.Queue.prototype.option = function(name, value) {
  3642. if (typeof name == "undefined"){ return "";}
  3643. if (typeof name == "string") {
  3644. if (typeof value == "undefined"){ return this._options[name];}
  3645. this._options[name] = value;
  3646. return this;
  3647. }
  3648. try {
  3649. for(var x in name) {
  3650. if(name.hasOwnProperty(x))
  3651. this._options[x] = name[x]
  3652. }
  3653. } catch(e) {
  3654. };
  3655. return this;
  3656. };
  3657. /**
  3658. * Ajax 요청 큐에 요청을 추가한다.
  3659. * @param {$Ajax} 추가할 $Ajax 객체
  3660. * @param {Object} 요청 시 전송할 매개 변수 객체
  3661. *
  3662. * @example
  3663. var oAjax1 = new $Ajax('ajax_test.php',{
  3664. onload : function(res){
  3665. // onload 핸들러
  3666. }
  3667. });
  3668. var oAjax2 = new $Ajax('ajax_test.php',{
  3669. onload : function(res){
  3670. // onload 핸들러
  3671. }
  3672. });
  3673. var oAjax3 = new $Ajax('ajax_test.php',{
  3674. onload : function(res){
  3675. // onload 핸들러
  3676. }
  3677. });
  3678. var oAjaxQueue = new $Ajax.Queue({
  3679. async : true,
  3680. useResultAsParam : true,
  3681. stopOnFailure : false
  3682. });
  3683. // Ajax 요청 큐에 추가한다.
  3684. oAjaxQueue.add(oAjax1,{seq:1});
  3685. oAjaxQueue.add(oAjax2,{seq:2,foo:99});
  3686. oAjaxQueue.add(oAjax3,{seq:3});
  3687. oAjaxQueue.request();
  3688. */
  3689. jindo.$Ajax.Queue.prototype.add = function (oAjax, oParam) {
  3690. this._queue.push({obj:oAjax, param:oParam});
  3691. }
  3692. /**
  3693. * Ajax Queue를 요청한다.
  3694. *
  3695. * @example
  3696. var oAjaxQueue = new $Ajax.Queue({
  3697. useResultAsParam : true
  3698. });
  3699. oAjaxQueue.add(oAjax1,{seq:1});
  3700. oAjaxQueue.add(oAjax2,{seq:2,foo:99});
  3701. oAjaxQueue.add(oAjax3,{seq:3});
  3702. // 서버에 Ajax 요청을 보낸다.
  3703. oAjaxQueue.request();
  3704. */
  3705. jindo.$Ajax.Queue.prototype.request = function () {
  3706. if(this.option('async')){
  3707. this._requestAsync();
  3708. } else {
  3709. this._requestSync(0);
  3710. }
  3711. }
  3712. jindo.$Ajax.Queue.prototype._requestSync = function (nIdx, oParam) {
  3713. var t = this;
  3714. if (this._queue.length > nIdx+1) {
  3715. this._queue[nIdx].obj._oncompleted = function(bSuccess, oResult){
  3716. if(!t.option('stopOnFailure') || bSuccess) t._requestSync(nIdx + 1, oResult);
  3717. };
  3718. }
  3719. var _oParam = this._queue[nIdx].param||{};
  3720. if(this.option('useResultAsParam') && oParam){
  3721. try { for(var x in oParam) if(typeof _oParam[x] == 'undefined' && oParam.hasOwnProperty(x)) _oParam[x] = oParam[x] } catch(e) {};
  3722. }
  3723. this._queue[nIdx].obj.request(_oParam);
  3724. }
  3725. jindo.$Ajax.Queue.prototype._requestAsync = function () {
  3726. for( var i=0; i<this._queue.length; i++)
  3727. this._queue[i].obj.request(this._queue[i].param);
  3728. }
  3729. /**
  3730. * @fileOverview $H의 생성자 및 메서드를 정의한 파일
  3731. * @name hash.js
  3732. */
  3733. /**
  3734. * $H 해시 객체를 리턴한다
  3735. * @class $H 클래스는 키와 값을 원소로 가지는 열거형 배열인 해시를 구현하고, 해시를 다루기 위한 여러 가지 위한 메서드를 제공한다.
  3736. * @param {Object} hashObject 해시로 만들 객체.
  3737. * @return {$H} 해시 객체
  3738. * @constructor
  3739. * @example
  3740. var h = $H({one:"first", two:"second", three:"third"})
  3741. * @author Kim, Taegon
  3742. */
  3743. jindo.$H = function(hashObject) {
  3744. var cl = arguments.callee;
  3745. if (typeof hashObject == "undefined") hashObject = new Object;
  3746. if (hashObject instanceof cl) return hashObject;
  3747. if (!(this instanceof cl)) return new cl(hashObject);
  3748. this._table = {};
  3749. for(var k in hashObject) {
  3750. if(hashObject.hasOwnProperty(k)){
  3751. this._table[k] = hashObject[k];
  3752. }
  3753. }
  3754. };
  3755. /**
  3756. * $value 메서드는 해싱 대상인 객체를 반환한다.
  3757. * @return {Object} 해싱 대상 객체
  3758. */
  3759. jindo.$H.prototype.$value = function() {
  3760. return this._table;
  3761. };
  3762. /**
  3763. * $ 메서드는 키와 값을 설정하거나 키에 해당하는 값을 반환한다.
  3764. * @param {String} key 키
  3765. * @param {void} [value] 값
  3766. * @return {void|$H} 키에 해당하는 값 혹은 $H 객체
  3767. * @example
  3768. * var hash = $H({one:"first", two:"second"});
  3769. *
  3770. * // 값을 설정할 때
  3771. * hash.$("three", "third");
  3772. *
  3773. * // hash => {one:"first", two:"second", three:"third"}
  3774. *
  3775. * // 값을 반환할 때
  3776. * var three = hash.$("three");
  3777. *
  3778. * // three => "third"
  3779. */
  3780. jindo.$H.prototype.$ = function(key, value) {
  3781. if (typeof value == "undefined") {
  3782. return this._table[key];
  3783. }
  3784. this._table[key] = value;
  3785. return this;
  3786. };
  3787. /**
  3788. * length 메서드는 해시 객체의 크기를 반환한다.
  3789. * @return {Number} 해시의 크기
  3790. */
  3791. jindo.$H.prototype.length = function() {
  3792. var i = 0;
  3793. for(var k in this._table) {
  3794. if(this._table.hasOwnProperty(k)){
  3795. if (typeof Object.prototype[k] != "undeifned" && Object.prototype[k] === this._table[k]) continue;
  3796. i++;
  3797. }
  3798. }
  3799. return i;
  3800. };
  3801. /**
  3802. * forEach 메서드는 해시 객체의 키와 값을 인수로 지정한 콜백 함수를 실행한다.
  3803. * @param {Function} callback 실행할 콜백 함수
  3804. * @param {Object} thisObject 콜백 함수의 this
  3805. * @example
  3806. function printIt(value, key) {
  3807. document.write(key+" => "+value+" <br>");
  3808. }
  3809. $H({one:"first", two:"second", three:"third"}).forEach(printIt);
  3810. */
  3811. jindo.$H.prototype.forEach = function(callback, thisObject) {
  3812. var t = this._table;
  3813. var h = this.constructor;
  3814. for(var k in t) {
  3815. if (t.hasOwnProperty(k)) {
  3816. if (!t.propertyIsEnumerable(k)) continue;
  3817. try {
  3818. callback.call(thisObject, t[k], k, t);
  3819. } catch(e) {
  3820. if (e instanceof h.Break) break;
  3821. if (e instanceof h.Continue) continue;
  3822. throw e;
  3823. }
  3824. }
  3825. }
  3826. return this;
  3827. };
  3828. /**
  3829. * filter 메서드는 해시 객체에서 필터 콜백 함수를 만족하는 원소를 수집한다. 수집한 원소는 새로운 $H 객체의 원소가 된다.
  3830. * 콜백함수는 Boolean 값을 반환해야 한다.
  3831. * @param {Function} callback 필터 콜백 함수
  3832. * @param {Object} thisObject 콜백 함수의 this
  3833. * @return {$H} 수집한 원소로 새로 만든 해시 객체
  3834. * @remark 필터 콜백 함수의 결과가 true인 원소만 수집한다. 콜백 함수는 형식은 예제를 참고한다.
  3835. * @example
  3836. function callback(value, key, object) {
  3837. // value 해시의 값
  3838. // key 해시의 고유한 키 혹은 이름
  3839. // object JavaScript Core Object 객체
  3840. }
  3841. */
  3842. jindo.$H.prototype.filter = function(callback, thisObject) {
  3843. var h = jindo.$H();
  3844. this.forEach(function(v,k,o) {
  3845. if(callback.call(thisObject, v, k, o) === true) {
  3846. h.add(k,v);
  3847. }
  3848. });
  3849. return h;
  3850. };
  3851. /**
  3852. * map 메서드는 해시 객체의 원소를 인수로 콜백 함수를 실행하고, 함수의 리턴 값을 해당 원소의 값으로 지정한다.
  3853. * @param {Function} callback 콜백 함수
  3854. * @param {Object} thisObject 콜백 함수의 this
  3855. * @return {$H} 값을 변경한 해시 객체
  3856. * @remark 콜백 함수는 형식은 예제를 참고한다.
  3857. * @example
  3858. function callback(value, key, object ) {
  3859. // value 해시의 값
  3860. // key 해시의 고유한 키 혹은 이름
  3861. // object JavaScript Core Object 객체
  3862. var r = key+"_"+value;
  3863. document.writeln (r + "<br />");
  3864. return r;
  3865. }
  3866. $H({one:"first", two:"second", three:"third"}).map(callback);
  3867. */
  3868. jindo.$H.prototype.map = function(callback, thisObject) {
  3869. var t = this._table;
  3870. this.forEach(function(v,k,o) {
  3871. t[k] = callback.call(thisObject, v, k, o);
  3872. });
  3873. return this;
  3874. };
  3875. /**
  3876. * 해시 테이블에 값을 추가한다.
  3877. * @param {String} key 추가한 값을 위한 키
  3878. * @param {String} value 해시 테이블에 추가할 값
  3879. * @return {$H} 값을 추가한 해시 객체
  3880. */
  3881. jindo.$H.prototype.add = function(key, value) {
  3882. //if (this.hasKey(key)) return null;
  3883. this._table[key] = value;
  3884. return this;
  3885. };
  3886. /**
  3887. * remove 메서드는 해시 테이블의 원소를 제거한다.
  3888. * @param {String} key 제거할 원소의 키
  3889. * @return {void} 제거한 키 값
  3890. * @example
  3891. var h = $H({one:"first", two:"second", three:"third"});
  3892. h.remove ("two");
  3893. // h의 해시 테이블은 {one:"first", three:"third"}
  3894. */
  3895. jindo.$H.prototype.remove = function(key) {
  3896. if (typeof this._table[key] == "undefined") return null;
  3897. var val = this._table[key];
  3898. delete this._table[key];
  3899. return val;
  3900. };
  3901. /**
  3902. * search 메서드는 해시 테이블에서 인수로 지정한 값을 찾는다.
  3903. * @param {String} value 검색할 값
  3904. * @returns {String | Boolean} 값을 찾았다면 값에 대한 키. 값을 찾지 못했다면 false.
  3905. * @example
  3906. var h = $H({one:"first", two:"second", three:"third"});
  3907. h.search ("second");
  3908. // two
  3909. h.search ("fist");
  3910. // false
  3911. */
  3912. jindo.$H.prototype.search = function(value) {
  3913. var result = false;
  3914. this.forEach(function(v,k,o) {
  3915. if (v === value) {
  3916. result = k;
  3917. jindo.$H.Break();
  3918. }
  3919. });
  3920. return result;
  3921. };
  3922. /**
  3923. * hasKey 메서드는 해시 테이블에 인수로 지정한 키가 있는지 찾는다.
  3924. * @param {String} key 해시 테이블에서 검색할 키
  3925. * @return {Boolean} 키의 존재 여부
  3926. * @example
  3927. var h = $H({one:"first", two:"second", three:"third"});
  3928. h.hasKey("four"); // false
  3929. h.hasKey("one"); // true
  3930. */
  3931. jindo.$H.prototype.hasKey = function(key) {
  3932. var result = false;
  3933. return (typeof this._table[key] != "undefined");
  3934. };
  3935. /**
  3936. * hasValue 메서드는 해시 테이블에 인수로 지정한 값이 있는지 확인한다.
  3937. * @param {String} value 해시 테이블에서 검색할 값
  3938. * @return {Boolean} 값의 존재 여부
  3939. */
  3940. jindo.$H.prototype.hasValue = function(value) {
  3941. return (this.search(value) !== false);
  3942. };
  3943. /**
  3944. * sort 메서드는 값을 기준으로 원소를 오름차순 정렬한다.
  3945. * @return {$H} 원소를 정렬한 해시 객체.
  3946. * @see $H#ksort
  3947. * @example
  3948. var h = $H({one:"하나", two:"둘", three:"셋"});
  3949. h.sort ();
  3950. // {two:"둘", three:"셋", one:"하나"}
  3951. */
  3952. jindo.$H.prototype.sort = function() {
  3953. var o = new Object;
  3954. var a = this.values();
  3955. var k = false;
  3956. a.sort();
  3957. for(var i=0; i < a.length; i++) {
  3958. k = this.search(a[i]);
  3959. o[k] = a[i];
  3960. delete this._table[k];
  3961. }
  3962. this._table = o;
  3963. return this;
  3964. };
  3965. /**
  3966. * ksort 메서드는 키를 기준으로 원소를 오름차순 정렬한다.
  3967. * @return {$H} 원소를 정렬한 해시 객체
  3968. * @see $H#sort
  3969. * @example
  3970. var h = $H({one:"하나", two:"둘", three:"셋"});
  3971. h.sort ();
  3972. // h => {one:"하나", three:"셋", two:"둘"}
  3973. */
  3974. jindo.$H.prototype.ksort = function() {
  3975. var o = new Object;
  3976. var a = this.keys();
  3977. a.sort();
  3978. for(var i=0; i < a.length; i++) {
  3979. o[a[i]] = this._table[a[i]];
  3980. }
  3981. this._table = o;
  3982. return this;
  3983. };
  3984. /**
  3985. * keys 메서드는 해시 키의 배열을 반환한다.
  3986. * @return {Array} 해시 키의 배열
  3987. * @example
  3988. var h = $H({one:"first", two:"second", three:"third"});
  3989. h.keys ();
  3990. // ["one", "two", "three"]
  3991. * @see $H#values
  3992. */
  3993. jindo.$H.prototype.keys = function() {
  3994. var keys = new Array;
  3995. for(var k in this._table) {
  3996. if(this._table.hasOwnProperty(k))
  3997. keys.push(k);
  3998. }
  3999. return keys;
  4000. };
  4001. /**
  4002. * values 메서드는 해시 값의 배열을 반환한다.
  4003. * @return {Array} 해시 값의 배열
  4004. * @example
  4005. var h = $H({one:"first", two:"second", three:"third"});
  4006. h.values();
  4007. // ["first", "second", "third"]
  4008. * @see $H#keys
  4009. */
  4010. jindo.$H.prototype.values = function() {
  4011. var values = [];
  4012. for(var k in this._table) {
  4013. if(this._table.hasOwnProperty(k))
  4014. values[values.length] = this._table[k];
  4015. }
  4016. return values;
  4017. };
  4018. /**
  4019. * toQueryString은 해시 객체를 쿼리 스트링 형태로 만든다.
  4020. * @return {String}
  4021. * @example
  4022. var h = $H({one:"first", two:"second", three:"third"});
  4023. h.toQueryString();
  4024. // "one=first&two=second&three=third"
  4025. */
  4026. jindo.$H.prototype.toQueryString = function() {
  4027. var buf = [], val = null, idx = 0;
  4028. for(var k in this._table) {
  4029. if (this._table.hasOwnProperty(k)) {
  4030. if (typeof(val = this._table[k]) == "object" && val.constructor == Array) {
  4031. for(i=0; i < val.length; i++) {
  4032. buf[buf.length] = encodeURIComponent(k)+"[]="+encodeURIComponent(val[i]+"");
  4033. }
  4034. } else {
  4035. buf[buf.length] = encodeURIComponent(k)+"="+encodeURIComponent(this._table[k]+"");
  4036. }
  4037. }
  4038. }
  4039. return buf.join("&");
  4040. };
  4041. /**
  4042. * empty는 해시 객체를 빈 객체로 만든다.
  4043. * @return {$H} 비워진 해시 객체
  4044. * @example
  4045. var hash = $H({a:1, b:2, c:3});
  4046. // hash => {a:1, b:2, c:3}
  4047. hash.empty();
  4048. // hash => {}
  4049. */
  4050. jindo.$H.prototype.empty = function() {
  4051. var keys = this.keys();
  4052. for(var i=0; i < keys.length; i++) {
  4053. delete this._table[keys[i]];
  4054. }
  4055. return this;
  4056. };
  4057. /**
  4058. * Break 메서드는 반복문의 실행을 중단할 때 사용한다.
  4059. * @remark forEach, filter, map와 같은 루프를 중단한다. 강제로 exception을 발생시키므로 try ~ catch 영역에서 이 메소드를 실행하면 정상적으로 동작하지 않을 수 있다.
  4060. * @example
  4061. $H({a:1, b:2, c:3}).forEach(function(v,k,o) {
  4062. ...
  4063. if (k == "b") $H.Break();
  4064. ...
  4065. });
  4066. * @see $H.Continue
  4067. */
  4068. jindo.$H.Break = function() {
  4069. if (!(this instanceof arguments.callee)) throw new arguments.callee;
  4070. };
  4071. /**
  4072. * Continue 메서드는 루프를 실행하다 다음 단계로 넘어갈 때 사용한다.
  4073. * @remark forEach, filter, map와 같은 루프 실행 도중에 현재 루프를 중단하고 다음으로 넘어간다. 강제로 exception을 발생시키므로 try ~ catch 영역에서 이 메소드를 실행하면 정상적으로 동작하지 않을 수 있다.
  4074. * @example
  4075. $H({a:1, b:2, c:3}).forEach(function(v,k,o) {
  4076. ...
  4077. if (v % 2 == 0) $H.Continue();
  4078. ...
  4079. });
  4080. * @see $H.Break
  4081. */
  4082. jindo.$H.Continue = function() {
  4083. if (!(this instanceof arguments.callee)) throw new arguments.callee;
  4084. };
  4085. /**
  4086. * @fileOverview $Json의 생성자 및 메서드를 정의한 파일
  4087. * @name json.js
  4088. */
  4089. /**
  4090. * $Json 객체를 리턴한다.
  4091. * @class $Json 객체는 자바스크립트에서 JSON(JavaScript Object Notation)을 다루기 위한 다양한 메서드를 제공한다.
  4092. * @param {Object | String} sObject 객체, 혹은 JSON으로 인코딩 가능한 문자열.
  4093. * @return {$Json} 인수를 인코딩한 $Json 객체.
  4094. * @remark XML 형태의 문자열을 사용하여 $Json 객체를 생성하려면 $Json#fromXML 메서드를 사용한다.
  4095. * @example
  4096. var oStr = $Json ('{ zoo: "myFirstZoo", tiger: 3, zebra: 2}');
  4097. var d = {name : 'nhn', location: 'Bundang-gu'}
  4098. var oObj = $Json (d);
  4099. * @constructor
  4100. * @author Kim, Taegon
  4101. */
  4102. jindo.$Json = function (sObject) {
  4103. var cl = arguments.callee;
  4104. if (typeof sObject == "undefined") sObject = {};
  4105. if (sObject instanceof cl) return sObject;
  4106. if (!(this instanceof cl)) return new cl(sObject);
  4107. if (typeof sObject == "string") {
  4108. this._object = jindo.$Json._oldMakeJSON(sObject);
  4109. }else{
  4110. this._object = sObject;
  4111. }
  4112. }
  4113. /*
  4114. native json의 parse의 성능이 보다 좋지 못해 native json은 사용하지 않음.
  4115. jindo.$Json._makeJson = function(sObject){
  4116. if (window.JSON&&window.JSON.parse) {
  4117. jindo.$Json._makeJson = function(sObject){
  4118. if (typeof sObject == "string") {
  4119. try{
  4120. return JSON.parse(sObject);
  4121. }catch(e){
  4122. return jindo.$Json._oldMakeJSON(sObject);
  4123. }
  4124. }
  4125. return sObject;
  4126. }
  4127. }else{
  4128. jindo.$Json._makeJson = function(sObject){
  4129. if (typeof sObject == "string") {
  4130. return jindo.$Json._oldMakeJSON(sObject);
  4131. }
  4132. return sObject;
  4133. }
  4134. }
  4135. return jindo.$Json._makeJson(sObject);
  4136. }
  4137. */
  4138. jindo.$Json._oldMakeJSON = function(sObject){
  4139. try {
  4140. if(/^(?:\s*)[\{\[]/.test(sObject)){
  4141. sObject = eval("("+sObject+")");
  4142. }else{
  4143. sObject = sObject;
  4144. }
  4145. } catch(e) {
  4146. sObject = {};
  4147. }
  4148. return sObject;
  4149. }
  4150. /**
  4151. * fromXML 메서드는 XML 형태의 문자열을 $Json 객체로 인코딩한다.
  4152. * @param {String} sXML $Json 객체로 인코딩할 XML 형태의 문자열
  4153. * @returns {$Json} $Json 객체
  4154. * @remark 속성과 CDATA를 가지는 태그는 CDATA를 '$cdata' 속성과 값으로 인코딩한다.
  4155. * @example
  4156. var j1 = $Json.fromXML('<data>only string</data>');
  4157. // 결과 :
  4158. // {"data":"only string"}
  4159. var j2 = $Json.fromXML('<data><id>Faqh%$</id><str attr="123">string value</str></data>');
  4160. // 결과:
  4161. // {"data":{"id":"Faqh%$","str":{"attr":"123","$cdata":"string value"}}}
  4162. */
  4163. jindo.$Json.fromXML = function(sXML) {
  4164. var o = {};
  4165. var re = /\s*<(\/?[\w:\-]+)((?:\s+[\w:\-]+\s*=\s*(?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'))*)\s*((?:\/>)|(?:><\/\1>|\s*))|\s*<!\[CDATA\[([\w\W]*?)\]\]>\s*|\s*>?([^<]*)/ig;
  4166. var re2= /^[0-9]+(?:\.[0-9]+)?$/;
  4167. var ec = {"&amp;":"&","&nbsp;":" ","&quot;":"\"","&lt;":"<","&gt;":">"};
  4168. var fg = {tags:["/"],stack:[o]};
  4169. var es = function(s){
  4170. if (typeof s == "undefined") return "";
  4171. return s.replace(/&[a-z]+;/g, function(m){ return (typeof ec[m] == "string")?ec[m]:m; })
  4172. };
  4173. var at = function(s,c){s.replace(/([\w\:\-]+)\s*=\s*(?:"((?:\\"|[^"])*)"|'((?:\\'|[^'])*)')/g, function($0,$1,$2,$3){c[$1] = es(($2?$2.replace(/\\"/g,'"'):undefined)||($3?$3.replace(/\\'/g,"'"):undefined));}) };
  4174. var em = function(o){
  4175. for(var x in o){
  4176. if (o.hasOwnProperty(x)) {
  4177. if(Object.prototype[x])
  4178. continue;
  4179. return false;
  4180. }
  4181. };
  4182. return true
  4183. };
  4184. /*
  4185. $0 : 전체
  4186. $1 : 태그명
  4187. $2 : 속성문자열
  4188. $3 : 닫는태그
  4189. $4 : CDATA바디값
  4190. $5 : 그냥 바디값
  4191. */
  4192. var cb = function($0,$1,$2,$3,$4,$5) {
  4193. var cur, cdata = "";
  4194. var idx = fg.stack.length - 1;
  4195. if (typeof $1 == "string" && $1) {
  4196. if ($1.substr(0,1) != "/") {
  4197. var has_attr = (typeof $2 == "string" && $2);
  4198. var closed = (typeof $3 == "string" && $3);
  4199. var newobj = (!has_attr && closed)?"":{};
  4200. cur = fg.stack[idx];
  4201. if (typeof cur[$1] == "undefined") {
  4202. cur[$1] = newobj;
  4203. cur = fg.stack[idx+1] = cur[$1];
  4204. } else if (cur[$1] instanceof Array) {
  4205. var len = cur[$1].length;
  4206. cur[$1][len] = newobj;
  4207. cur = fg.stack[idx+1] = cur[$1][len];
  4208. } else {
  4209. cur[$1] = [cur[$1], newobj];
  4210. cur = fg.stack[idx+1] = cur[$1][1];
  4211. }
  4212. if (has_attr) at($2,cur);
  4213. fg.tags[idx+1] = $1;
  4214. if (closed) {
  4215. fg.tags.length--;
  4216. fg.stack.length--;
  4217. }
  4218. } else {
  4219. fg.tags.length--;
  4220. fg.stack.length--;
  4221. }
  4222. } else if (typeof $4 == "string" && $4) {
  4223. cdata = $4;
  4224. } else if (typeof $5 == "string" && $5) {
  4225. cdata = es($5);
  4226. }
  4227. if (cdata.replace(/^\s+/g, "").length > 0) {
  4228. var par = fg.stack[idx-1];
  4229. var tag = fg.tags[idx];
  4230. if (re2.test(cdata)) {
  4231. cdata = parseFloat(cdata);
  4232. }else if (cdata == "true"){
  4233. cdata = true;
  4234. }else if(cdata == "false"){
  4235. cdata = false;
  4236. }
  4237. if(typeof par =='undefined') return;
  4238. if (par[tag] instanceof Array) {
  4239. var o = par[tag];
  4240. if (typeof o[o.length-1] == "object" && !em(o[o.length-1])) {
  4241. o[o.length-1].$cdata = cdata;
  4242. o[o.length-1].toString = function(){ return cdata; }
  4243. } else {
  4244. o[o.length-1] = cdata;
  4245. }
  4246. } else {
  4247. if (typeof par[tag] == "object" && !em(par[tag])) {
  4248. par[tag].$cdata = cdata;
  4249. par[tag].toString = function(){ return cdata; }
  4250. } else {
  4251. par[tag] = cdata;
  4252. }
  4253. }
  4254. }
  4255. };
  4256. sXML = sXML.replace(/<(\?|\!-)[^>]*>/g, "");
  4257. sXML.replace(re, cb);
  4258. return jindo.$Json(o);
  4259. };
  4260. /**
  4261. * get 메서드는 path에 해당하는 $Json 객체의 값을 리턴한다.
  4262. * @param {String} sPath path 문자열
  4263. * @return {Array} 지정된 path에 해당하는 value를 원소로 가지는 배열
  4264. * @example
  4265. var j = $Json.fromXML('<data><id>Faqh%$</id><str attr="123">string value</str></data>');
  4266. var r = j.get ("/data/id");
  4267. // 결과 :
  4268. // [Faqh%$]
  4269. */
  4270. jindo.$Json.prototype.get = function(sPath) {
  4271. var o = this._object;
  4272. var p = sPath.split("/");
  4273. var re = /^([\w:\-]+)\[([0-9]+)\]$/;
  4274. var stack = [[o]], cur = stack[0];
  4275. var len = p.length, c_len, idx, buf, j, e;
  4276. for(var i=0; i < len; i++) {
  4277. if (p[i] == "." || p[i] == "") continue;
  4278. if (p[i] == "..") {
  4279. stack.length--;
  4280. } else {
  4281. buf = [];
  4282. idx = -1;
  4283. c_len = cur.length;
  4284. if (c_len == 0) return [];
  4285. if (re.test(p[i])) idx = +RegExp.$2;
  4286. for(j=0; j < c_len; j++) {
  4287. e = cur[j][p[i]];
  4288. if (typeof e == "undefined") continue;
  4289. if (e instanceof Array) {
  4290. if (idx > -1) {
  4291. if (idx < e.length) buf[buf.length] = e[idx];
  4292. } else {
  4293. buf = buf.concat(e);
  4294. }
  4295. } else if (idx == -1) {
  4296. buf[buf.length] = e;
  4297. }
  4298. }
  4299. stack[stack.length] = buf;
  4300. }
  4301. cur = stack[stack.length-1];
  4302. }
  4303. return cur;
  4304. };
  4305. /**
  4306. * toString 메서드는 $Json 객체를 JSON 문자열로 리턴한다.
  4307. * @return {String} JSON 문자열
  4308. * @example
  4309. var j = $Json({foo:1, bar: 31});
  4310. document.write (j.toString());
  4311. document.write (j);
  4312. // 결과 :
  4313. // {"bar":31,"foo":1}{"bar":31,"foo":1}
  4314. */
  4315. jindo.$Json.prototype.toString = function() {
  4316. if (window.JSON&&window.JSON.stringify) {
  4317. jindo.$Json.prototype.toString = function() {
  4318. try{
  4319. return window.JSON.stringify(this._object);
  4320. }catch(e){
  4321. return jindo.$Json._oldToString(this._object);
  4322. }
  4323. }
  4324. }else{
  4325. jindo.$Json.prototype.toString = function() {
  4326. return jindo.$Json._oldToString(this._object);
  4327. }
  4328. }
  4329. return this.toString();
  4330. };
  4331. jindo.$Json._oldToString = function(oObj){
  4332. var func = {
  4333. $ : function($) {
  4334. if (typeof $ == "object" && $ == null) return 'null';
  4335. if (typeof $ == "undefined") return '""';
  4336. if (typeof $ == "boolean") return $?"true":"false";
  4337. if (typeof $ == "string") return this.s($);
  4338. if (typeof $ == "number") return $;
  4339. if ($ instanceof Array) return this.a($);
  4340. if ($ instanceof Object) return this.o($);
  4341. },
  4342. s : function(s) {
  4343. var e = {'"':'\\"',"\\":"\\\\","\n":"\\n","\r":"\\r","\t":"\\t"};
  4344. var c = function(m){ return (typeof e[m] != "undefined")?e[m]:m };
  4345. return '"'+s.replace(/[\\"'\n\r\t]/g, c)+'"';
  4346. },
  4347. a : function(a) {
  4348. // a = a.sort();
  4349. var s = "[",c = "",n=a.length;
  4350. for(var i=0; i < n; i++) {
  4351. if (typeof a[i] == "function") continue;
  4352. s += c+this.$(a[i]);
  4353. if (!c) c = ",";
  4354. }
  4355. return s+"]";
  4356. },
  4357. o : function(o) {
  4358. o = jindo.$H(o).ksort().$value();
  4359. var s = "{",c = "";
  4360. for(var x in o) {
  4361. if (o.hasOwnProperty(x)) {
  4362. if (typeof o[x] == "function") continue;
  4363. s += c+this.s(x)+":"+this.$(o[x]);
  4364. if (!c) c = ",";
  4365. }
  4366. }
  4367. return s+"}";
  4368. }
  4369. }
  4370. return func.$(oObj);
  4371. }
  4372. /**
  4373. * toXML 메서드는 $Json 객체를 XML 형태의 문자열로 리턴한다.
  4374. * @return {String} XML 형태의 문자열
  4375. * @example
  4376. var json = $Json({foo:1, bar: 31});
  4377. json.toXML();
  4378. // 결과 :
  4379. // <foo>1</foo><bar>31</bar>
  4380. */
  4381. jindo.$Json.prototype.toXML = function() {
  4382. var f = function($,tag) {
  4383. var t = function(s,at) { return "<"+tag+(at||"")+">"+s+"</"+tag+">" };
  4384. switch (typeof $) {
  4385. case "undefined":
  4386. case "null":
  4387. return t("");
  4388. case "number":
  4389. return t($);
  4390. case "string":
  4391. if ($.indexOf("<") < 0){
  4392. return t($.replace(/&/g,"&amp;"));
  4393. }else{
  4394. return t("<![CDATA["+$+"]]>");
  4395. }
  4396. case "boolean":
  4397. return t(String($));
  4398. case "object":
  4399. var ret = "";
  4400. if ($ instanceof Array) {
  4401. var len = $.length;
  4402. for(var i=0; i < len; i++) { ret += f($[i],tag); };
  4403. } else {
  4404. var at = "";
  4405. for(var x in $) {
  4406. if ($.hasOwnProperty(x)) {
  4407. if (x == "$cdata" || typeof $[x] == "function") continue;
  4408. ret += f($[x], x);
  4409. }
  4410. }
  4411. if (tag) ret = t(ret, at);
  4412. }
  4413. return ret;
  4414. }
  4415. };
  4416. return f(this._object, "");
  4417. };
  4418. /**
  4419. * toObject 메서드는 $Json 객체 원래의 JSON 데이터 객체를 리턴한다.
  4420. * @return {Object} 원래의 데이터 객체
  4421. * @example
  4422. var json = $Json({foo:1, bar: 31});
  4423. json.toObject();
  4424. // 결과 :
  4425. // {foo: 1, bar: 31}
  4426. */
  4427. jindo.$Json.prototype.toObject = function() {
  4428. return this._object;
  4429. };
  4430. /**
  4431. * compare 메서드는 json객체 끼리 값이 같은지 비교를 한다. (1.4.4부터 사용가능.)
  4432. * @return {Boolean} 불린값.
  4433. * @example
  4434. $Json({foo:1, bar: 31}).compare({foo:1, bar: 31});
  4435. // 결과 :
  4436. // true
  4437. $Json({foo:1, bar: 31}).compare({foo:1, bar: 1});
  4438. // 결과 :
  4439. // false
  4440. */
  4441. jindo.$Json.prototype.compare = function(oData){
  4442. return jindo.$Json._oldToString(this._object).toString() == jindo.$Json._oldToString(jindo.$Json(oData).$value()).toString();
  4443. }
  4444. /**
  4445. * $value 메서드는 $Json.toObject의 별칭(Alias)이다.
  4446. * @return {Object} 원래의 데이터 객체
  4447. */
  4448. jindo.$Json.prototype.$value = jindo.$Json.prototype.toObject;
  4449. /**
  4450. * @fileOverview $Cookie의 생성자 및 메서드를 정의한 파일
  4451. * @name cookie.js
  4452. */
  4453. /**
  4454. * $Cookie 객체를 생성한다.
  4455. * @class $Cookie 클래스는 쿠키(Cookie)를 추가, 수정, 혹은 삭제하거나 쿠키의 값을 가져온다.
  4456. * @constructor
  4457. * @return {$Cookie} 생성된 $Cookie 객체
  4458. * @author Kim, Taegon
  4459. * @example
  4460. var cookie = $Cookie();
  4461. */
  4462. jindo.$Cookie = function() {
  4463. var cl = arguments.callee;
  4464. var cached = cl._cached;
  4465. if (cl._cached) return cl._cached;
  4466. if (!(this instanceof cl)) return new cl;
  4467. if (typeof cl._cached == "undefined") cl._cached = this;
  4468. };
  4469. /**
  4470. * keys 메서드는 쿠키 이름을 원소로 가지는 배열을 리턴한다.
  4471. * @return {Array} 쿠키 이름을 원소로 가지는 배열
  4472. * @example
  4473. var cookie = $Cookie();
  4474. cookie.set("session_id1", "value1", 1);
  4475. cookie.set("session_id2", "value2", 1);
  4476. cookie.set("session_id3", "value3", 1);
  4477. document.write (cookie.keys ());
  4478. *
  4479. * // 결과 :
  4480. * // session_id1, session_id2, session_id3
  4481. */
  4482. jindo.$Cookie.prototype.keys = function() {
  4483. var ca = document.cookie.split(";");
  4484. var re = /^\s+|\s+$/g;
  4485. var a = new Array;
  4486. for(var i=0; i < ca.length; i++) {
  4487. a[a.length] = ca[i].substr(0,ca[i].indexOf("=")).replace(re, "");
  4488. }
  4489. return a;
  4490. };
  4491. /**
  4492. * get 메서드는 쿠키 이름에 해당하는 쿠키 값을 가져온다. 값이 존재하지 않는다면 null을 리턴한다.
  4493. * @param {String} sName 쿠키 이름
  4494. * @return {String} 쿠키 값
  4495. * @example
  4496. var cookie = $Cookie();
  4497. cookie.set("session_id1", "value1", 1);
  4498. document.write (cookie.get ("session_id1"));
  4499. *
  4500. * // 결과 :
  4501. * // value1
  4502. *
  4503. document.write (cookie.get ("session_id0"));
  4504. *
  4505. * // 결과 :
  4506. * // null
  4507. */
  4508. jindo.$Cookie.prototype.get = function(sName) {
  4509. var ca = document.cookie.split(/\s*;\s*/);
  4510. var re = new RegExp("^(\\s*"+sName+"\\s*=)");
  4511. for(var i=0; i < ca.length; i++) {
  4512. if (re.test(ca[i])) return unescape(ca[i].substr(RegExp.$1.length));
  4513. }
  4514. return null;
  4515. };
  4516. /**
  4517. * set 메서드는 쿠키 값을 설정한다.
  4518. * @param {String} sName 쿠키 이름
  4519. * @param {String} sValue 쿠키 값
  4520. * @param {Number} [nDays] 쿠키 유효 시간. 유효 시간은 일단위로 설정한다. 유효시간을 생략했다면 쿠키는 웹 브라우저가 종료되면 없어진다.
  4521. * @param {String} [sDomain] 쿠키 도메인
  4522. * @param {String} [sPath] 쿠키 경로
  4523. * @return {$Cookie} $Cookie 객체
  4524. * @example
  4525. var cookie = $Cookie();
  4526. cookie.set("session_id1", "value1", 1);
  4527. cookie.set("session_id2", "value2", 1);
  4528. cookie.set("session_id3", "value3", 1);
  4529. */
  4530. jindo.$Cookie.prototype.set = function(sName, sValue, nDays, sDomain, sPath) {
  4531. var sExpire = "";
  4532. if (typeof nDays == "number") {
  4533. sExpire = ";expires="+(new Date((new Date()).getTime()+nDays*1000*60*60*24)).toGMTString();
  4534. }
  4535. if (typeof sDomain == "undefined") sDomain = "";
  4536. if (typeof sPath == "undefined") sPath = "/";
  4537. document.cookie = sName+"="+escape(sValue)+sExpire+"; path="+sPath+(sDomain?"; domain="+sDomain:"");
  4538. return this;
  4539. };
  4540. /**
  4541. * remove 메서드는 쿠키 이름에 설정된 쿠키 값을 제거한다.
  4542. * @param {String} sName 쿠키 이름
  4543. * @param {String} sDomain 쿠키 도메인
  4544. * @param {String} sPath 쿠키 경로
  4545. * @return {$Cookie} $Cookie 객체
  4546. * @example
  4547. var cookie = $Cookie();
  4548. cookie.set("session_id1", "value1", 1);
  4549. document.write (cookie.get ("session_id1"));
  4550. *
  4551. * // 결과 :
  4552. * // value1
  4553. *
  4554. cookie.remove("session_id1");
  4555. document.write (cookie.get ("session_id1"));
  4556. *
  4557. * // 결과 :
  4558. * // null
  4559. */
  4560. jindo.$Cookie.prototype.remove = function(sName, sDomain, sPath) {
  4561. if (this.get(sName) != null) this.set(sName, "", -1, sDomain, sPath);
  4562. return this;
  4563. };
  4564. /**
  4565. * @fileOverview $Element의 생성자 및 메서드를 정의한 파일
  4566. * @name element.js
  4567. */
  4568. /**
  4569. * $Element 객체를 생성하여 반환한다.
  4570. * @class $Element 클래스는 HTML 엘리먼트를 래핑(wrapping)하며, 엘리먼트를 다루기 위한 메서드를 제공한다.<br>
  4571. * 래핑이란 자바스크립트의 함수를 한번 더 감싸 본래 함수의 기능은 그대로 유지하면서 확장된 기능을 속성 형태로 제공하는 것을 말한다.
  4572. * @constructor
  4573. * @description [Lite]
  4574. * @author Kim, Taegon
  4575. *
  4576. * @param {String | HTML Element | $Element} el
  4577. * <br>
  4578. * $Element 는 문자열, HTML 엘리먼트, 혹은 $Element 를 매개 변수로 지정할 수 있다.<br>
  4579. * <br>
  4580. * 매개 변수가 문자열이면 두 가지 방식으로 동작한다.<br>
  4581. * 만일 "&lt;tagName&gt;" 과 같은 형식의 문자열이면 tagName을 가지는 객체를 생성한다.<br>
  4582. * 그 이외의 경우 문자열을 id 로 하는 HTML 엘리먼트를 사용하여 $Element 를 생성한다.<br>
  4583. * <br>
  4584. * 매개 변수가 HTML 엘리먼트이면 HTML 엘리먼트를 래핑하여 $Element 를 생성한다.<br>
  4585. * <br>
  4586. * 매개 변수가 $Element 이면 전달된 매개 변수를 그대로 반환하며 undefined 혹은 null 인 경우에는 null 을 반환한다.
  4587. * @return {$Element} 생성된 $Element 객체
  4588. *
  4589. * @example
  4590. var element = $Element($("box")); // HTML 엘리먼트를 매개 변수로 지정
  4591. var element = $Element("box"); // HTML 엘리먼트의 id를 매개 변수로 지정
  4592. var element = $Element("<DIV>"); // 태그를 매개 변수로 지정, DIV 엘리먼트를 생성하여 래핑함
  4593. */
  4594. jindo.$Element = function(el) {
  4595. var cl = arguments.callee;
  4596. if (el && el instanceof cl) return el;
  4597. if (el===null || typeof el == "undefined"){
  4598. return null;
  4599. }else{
  4600. el = jindo.$(el);
  4601. if (el === null) {
  4602. return null;
  4603. };
  4604. }
  4605. if (!(this instanceof cl)) return new cl(el);
  4606. this._element = (typeof el == "string") ? jindo.$(el) : el;
  4607. var tag = this._element.tagName;
  4608. // tagname
  4609. this.tag = (typeof tag!='undefined')?tag.toLowerCase():'';
  4610. }
  4611. /**
  4612. * agent의 dependency를 없애기 위해 별로도 설정.
  4613. * @ignore
  4614. **/
  4615. var _j_ag = navigator.userAgent;
  4616. var IS_IE = _j_ag.indexOf("MSIE") > -1;
  4617. var IS_FF = _j_ag.indexOf("Firefox") > -1;
  4618. var IS_OP = _j_ag.indexOf("Opera") > -1;
  4619. var IS_SF = _j_ag.indexOf("Apple") > -1;
  4620. var IS_CH = _j_ag.indexOf("Chrome") > -1;
  4621. /**
  4622. * $value 메서드는 원래의 HTML 엘리먼트를 반환한다.
  4623. * @return {HTML Element} 래핑된 원래의 엘리먼트
  4624. * @description [Lite]
  4625. *
  4626. * @example
  4627. var element = $Element("sample_div");
  4628. element.$value(); // 원래의 엘리먼트가 반환된다
  4629. */
  4630. jindo.$Element.prototype.$value = function() {
  4631. return this._element;
  4632. };
  4633. /**
  4634. * HTML 엘리먼트의 display 속성을 확인하거나 display 속성을 설정하기 위해 사용한다.
  4635. *
  4636. * @param {Boolean} [bVisible] 화면에 보여줄지의 여부<br>
  4637. * 매개 변수를 생략하면 HTML 엘리먼트의 현재 display 속성을 확인하여 true/false로 반환한다.(none 이면 false)<br>
  4638. * 매개 변수가 true인 경우에는 display 속성을 설정하고 false인 경우에는 display 속성을 none 으로 변경한다.
  4639. * @param {String} [sDisplay] display 속성 값<br>
  4640. * bVisible 매개 변수가 true 이면 display 속성을 전달된 매개 변수로 설정한다.
  4641. * @return {$Element} display 속성을 변경한 $Element 객체
  4642. *
  4643. * @description [Lite]
  4644. * @since 1.1.2부터 설정 기능을 사용할 수 있다.
  4645. * @since 1.4.5부터 bVisible 매개 변수의 값이 true 인 경우 sDisplay 매개 변수의 값으로 display 속성을 설정할 수 있다.
  4646. * @see $Element#show
  4647. * @see $Element#hide
  4648. * @see $Element#toggle
  4649. *
  4650. * @example
  4651. <div id="sample_div" style="display:none">Hello world</div>
  4652. // 조회
  4653. $Element("sample_div").visible(); // false
  4654. * @example
  4655. // 화면에 보이도록 설정
  4656. $Element("sample_div").visible(true, 'block');
  4657. //Before
  4658. <div id="sample_div" style="display:none">Hello world</div>
  4659. //After
  4660. <div id="sample_div" style="display:block">Hello world</div>
  4661. */
  4662. jindo.$Element.prototype.visible = function(bVisible, sDisplay) {
  4663. if (typeof bVisible != "undefined") {
  4664. this[bVisible?"show":"hide"](sDisplay);
  4665. return this;
  4666. }
  4667. return (this.css("display") != "none");
  4668. };
  4669. /**
  4670. * HTML 엘리먼트가 화면에 보이도록 display 속성을 변경한다.
  4671. * @param {String} [sDisplay] 변경할 display 속성 값<br>
  4672. * 매개 변수를 생략하면 태그별로 미리 지정된 디폴트 속성 값으로 설정한다.<br>
  4673. * 미리 지정된 디폴트 속성 값이 없으면 "inline" 으로 설정한다.
  4674. * @return {$Element} display 속성을 변경한 $Element 객체
  4675. * @description [Lite]
  4676. * @see $Element#hide
  4677. * @see $Element#toggle
  4678. * @see $Element#visible
  4679. * @since 1.4.5부터 sDisplay 값으로 display 속성 값 지정이 가능하다.
  4680. *
  4681. * @example
  4682. // 화면에 보이도록 설정
  4683. $Element("sample_div").show();
  4684. //Before
  4685. <div id="sample_div" style="display:none">Hello world</div>
  4686. //After
  4687. <div id="sample_div" style="display:block">Hello world</div>
  4688. */
  4689. jindo.$Element.prototype.show = function(sDisplay) {
  4690. var s = this._element.style;
  4691. var b = "block";
  4692. var c = { p:b,div:b,form:b,h1:b,h2:b,h3:b,h4:b,ol:b,ul:b,fieldset:b,td:"table-cell",th:"table-cell",
  4693. li:"list-item",table:"table",thead:"table-header-group",tbody:"table-row-group",tfoot:"table-footer-group",
  4694. tr:"table-row",col:"table-column",colgroup:"table-column-group",caption:"table-caption",dl:b,dt:b,dd:b};
  4695. try {
  4696. if (sDisplay) {
  4697. s.display = sDisplay;
  4698. }else{
  4699. var type = c[this.tag];
  4700. s.display = type || "inline";
  4701. }
  4702. } catch(e) {
  4703. /*
  4704. IE에서 sDisplay값이 비정상적일때 block로 셋팅한다.
  4705. */
  4706. s.display = "block";
  4707. }
  4708. return this;
  4709. };
  4710. /**
  4711. * HTML 엘리먼트가 화면에 보이지 않도록 display 속성을 none 으로 변경한다.
  4712. * @returns {$Element} display 속성을 변경한 $Element 객체
  4713. * @description [Lite]
  4714. * @see $Element#show
  4715. * @see $Element#toggle
  4716. * @see $Element#visible
  4717. *
  4718. * @example
  4719. // 화면에 보이지 않도록 설정
  4720. $Element("sample_div").hide();
  4721. //Before
  4722. <div id="sample_div" style="display:block">Hello world</div>
  4723. //After
  4724. <div id="sample_div" style="display:none">Hello world</div>
  4725. */
  4726. jindo.$Element.prototype.hide = function() {
  4727. this._element.style.display = "none";
  4728. return this;
  4729. };
  4730. /**
  4731. * HTML 엘리먼트의 display 속성을 변경하여 엘리먼트를 화면에 보이거나, 보이지 않게 한다.
  4732. * @param {String} [sDisplay] 보이도록 변경할 때 사용되는 display 속성 값
  4733. * @returns {$Element} display 속성을 변경한 $Element 객체
  4734. * @description [Lite]
  4735. * @see $Element#show
  4736. * @see $Element#hide
  4737. * @see $Element#visible
  4738. * @since 1.4.5부터 보이도록 설정할 때 sDisplay 값으로 display 속성 값 지정이 가능하다.
  4739. * @example
  4740. // 화면에 보이거나, 보이지 않도록 처리
  4741. $Element("sample_div1").toggle();
  4742. $Element("sample_div2").toggle();
  4743. //Before
  4744. <div id="sample_div1" style="display:block">Hello</div>
  4745. <div id="sample_div2" style="display:none">Good Bye</div>
  4746. //After
  4747. <div id="sample_div1" style="display:none">Hello</div>
  4748. <div id="sample_div2" style="display:block">Good Bye</div>
  4749. */
  4750. jindo.$Element.prototype.toggle = function(sDisplay) {
  4751. this[this.visible()?"hide":"show"](sDisplay);
  4752. return this;
  4753. };
  4754. /**
  4755. * HTML 엘리먼트의 투명도 값을 가져오거나 설정한다.
  4756. * @param {Number} [value] 설정할 투명도 값<br>
  4757. * 투명도 값은 0 ~ 1 사이의 실수 값으로 지정한다.<br>
  4758. * 매개 변수의 값이 0보다 작으면 0을, 1보다 크면 1을 설정한다.
  4759. * @return {Number} HTML 엘리먼트의 투명도 값
  4760. * @description [Lite]
  4761. *
  4762. * @example
  4763. <div id="sample" style="background-color:#2B81AF; width:20px; height:20px;"></div>
  4764. // 조회
  4765. $Element("sample").opacity(); // 1
  4766. * @example
  4767. // 투명도 값 설정
  4768. $Element("sample").opacity(0.4);
  4769. //Before
  4770. <div style="background-color: rgb(43, 129, 175); width: 20px; height: 20px;" id="sample"></div>
  4771. //After
  4772. <div style="background-color: rgb(43, 129, 175); width: 20px; height: 20px; opacity: 0.4;" id="sample"></div>
  4773. */
  4774. jindo.$Element.prototype.opacity = function(value) {
  4775. var v,e = this._element,b = (this._getCss(e,"display") != "none");
  4776. value = parseFloat(value);
  4777. /*
  4778. IE에서 layout을 가지고 있지 않으면 opacity가 적용되지 않음.
  4779. */
  4780. e.style.zoom = 1;
  4781. if (!isNaN(value)) {
  4782. value = Math.max(Math.min(value,1),0);
  4783. if (typeof e.filters != "undefined") {
  4784. value = Math.ceil(value*100);
  4785. if (typeof e.filters != 'unknown' && typeof e.filters.alpha != "undefined") {
  4786. e.filters.alpha.opacity = value;
  4787. } else {
  4788. e.style.filter = (e.style.filter + " alpha(opacity=" + value + ")");
  4789. }
  4790. } else {
  4791. e.style.opacity = value;
  4792. }
  4793. return value;
  4794. }
  4795. if (typeof e.filters != "undefined") {
  4796. v = (typeof e.filters.alpha == "undefined")?(b?100:0):e.filters.alpha.opacity;
  4797. v = v / 100;
  4798. } else {
  4799. v = parseFloat(e.style.opacity);
  4800. if (isNaN(v)) v = b?1:0;
  4801. }
  4802. return v;
  4803. };
  4804. /**
  4805. * HTML 엘리먼트의 CSS 속성 값을 가져오거나 설정한다.
  4806. * @remark CSS 속성은 Camel 표기법을 사용한다. 따라서 border-width-bottom은 borderWidthBottom으로 정의한다.
  4807. * @remark float 속성은 Javascript의 예약어로 사용하므로 css 메서드에서는 float 대신 cssFloat를 사용한다. (Internet Explorer에서는 styleFloat를, 그 외의 브라우저에서는 cssFloat를 사용한다.)
  4808. * @param {String | Object | $H} sName CSS 속성명 혹은 하나 이상의 CSS 속성과 값을 가지는 객체.<br>
  4809. * css 메서드는 문자열, Object, 혹은 $H 를 매개 변수로 지정할 수 있다.<br>
  4810. * <br>
  4811. * 매개 변수가 문자열이면 조회 혹은 수정할 속성 명으로 아래 두 가지 방식으로 동작한다.<br>
  4812. * 두 번째 매개 변수인 sValue 매개 변수를 생략하면 CSS 속성의 값을 가져온다.<br>
  4813. * 두 번째 매개 변수인 sValue 매개 변수에 값이 있으면 CSS 속성의 값을 sValue 값으로 설정한다.<br>
  4814. * <br>
  4815. * Object 혹은 $H 객체를 사용하면 두 개 이상의 CSS 속성을 한꺼번에 설정할 수 있다.<br>
  4816. * 객체의 프로퍼티 이름으로 CSS 속성을 찾아 프로퍼티 값으로 설정한다.
  4817. * @param {String | Number} [sValue] CSS 속성에 설정할 값.<br>
  4818. * 단위가 필요한 값은 숫자 혹은 단위를 포함한 문자열을 사용한다.
  4819. * @return {String | $Element} 값을 가져올 때는 값을 문자열로 반환하고, 값을 설정할 때는 값을 설정한 현재의 $Element 를 반환한다.
  4820. * @description [Lite]
  4821. * @example
  4822. <style type="text/css">
  4823. #btn {
  4824. width: 120px;
  4825. height: 30px;
  4826. background-color: blue;
  4827. }
  4828. </style>
  4829. <span id="btn"></span>
  4830. ...
  4831. // CSS 속성 값 조회
  4832. $Element('btn').css('backgroundColor'); // rgb (0, 0, 255)
  4833. * @example
  4834. // CSS 속성 값 설정
  4835. $Element('btn').css('backgroundColor', 'red');
  4836. //Before
  4837. <span id="btn"></span>
  4838. //After
  4839. <span id="btn" style="background-color: red;"></span>
  4840. * @example
  4841. // 여러개의 CSS 속성 값을 설정
  4842. $Element('btn').css({
  4843. width: "200px", // 200
  4844. height: "80px" // 80 으로 설정하여도 결과는 같음
  4845. });
  4846. //Before
  4847. <span id="btn" style="background-color: red;"></span>
  4848. //After
  4849. <span id="btn" style="background-color: red; width: 200px; height: 80px;"></span>
  4850. */
  4851. jindo.$Element.prototype.css = function(sName, sValue) {
  4852. var e = this._element;
  4853. var type_v = (typeof sValue);
  4854. if (sName == 'opacity') return type_v == 'undefined' ? this.opacity() : this.opacity(sValue);
  4855. var type_n = (typeof sName);
  4856. if (type_n == "string") {
  4857. var view;
  4858. if (type_v == "string" || type_v == "number") {
  4859. var obj = {};
  4860. obj[sName] = sValue;
  4861. sName = obj;
  4862. } else {
  4863. var _getCss = this._getCss;
  4864. if((IS_FF||IS_OP)&&(sName=="backgroundPositionX"||sName=="backgroundPositionY")){
  4865. var bp = _getCss(e, "backgroundPosition").split(/\s+/);
  4866. return (sName == "backgroundPositionX") ? bp[0] : bp[1];
  4867. }
  4868. if (IS_IE && sName == "backgroundPosition") {
  4869. return _getCss(e, "backgroundPositionX") + " " + _getCss(e, "backgroundPositionY")
  4870. }
  4871. if ((IS_FF||IS_SF||IS_CH) && (sName=="padding"||sName=="margin")) {
  4872. var top = _getCss(e, sName+"Top");
  4873. var right = _getCss(e, sName+"Right");
  4874. var bottom = _getCss(e, sName+"Bottom");
  4875. var left = _getCss(e, sName+"Left");
  4876. if ((top == right) && (bottom == left)) {
  4877. return top;
  4878. }else if (top == bottom) {
  4879. if (right == left) {
  4880. return top+" "+right;
  4881. }else{
  4882. return top+" "+right+" "+bottom+" "+left;
  4883. }
  4884. }else{
  4885. return top+" "+right+" "+bottom+" "+left;
  4886. }
  4887. }
  4888. return _getCss(e, sName);
  4889. }
  4890. }
  4891. var h = jindo.$H;
  4892. if (typeof h != "undefined" && sName instanceof h) {
  4893. sName = sName._table;
  4894. }
  4895. if (typeof sName == "object") {
  4896. var v, type;
  4897. for(var k in sName) {
  4898. if(sName.hasOwnProperty(k)){
  4899. v = sName[k];
  4900. type = (typeof v);
  4901. if (type != "string" && type != "number") continue;
  4902. if (k == 'opacity') {
  4903. type == 'undefined' ? this.opacity() : this.opacity(v);
  4904. continue;
  4905. }
  4906. if (k == "cssFloat" && IS_IE) k = "styleFloat";
  4907. if((IS_FF||IS_OP)&&( k =="backgroundPositionX" || k == "backgroundPositionY")){
  4908. var bp = this.css("backgroundPosition").split(/\s+/);
  4909. v = k == "backgroundPositionX" ? v+" "+bp[1] : bp[0]+" "+v;
  4910. this._setCss(e, "backgroundPosition", v);
  4911. }else{
  4912. this._setCss(e, k, v);
  4913. }
  4914. }
  4915. }
  4916. }
  4917. return this;
  4918. };
  4919. /**
  4920. * css에서 사용되는 함수
  4921. * @ignore
  4922. * @param {Element} e
  4923. * @param {String} sName
  4924. */
  4925. jindo.$Element.prototype._getCss = function(e, sName){
  4926. var fpGetCss;
  4927. if (e.currentStyle) {
  4928. fpGetCss = function(e, sName){
  4929. try{
  4930. if (sName == "cssFloat") sName = "styleFloat";
  4931. var sStyle = e.style[sName];
  4932. if(sStyle){
  4933. return sStyle;
  4934. }else{
  4935. var oCurrentStyle = e.currentStyle;
  4936. if (oCurrentStyle) {
  4937. return oCurrentStyle[sName];
  4938. }
  4939. }
  4940. return sStyle;
  4941. }catch(ex){
  4942. throw new Error((e.tagName||"document") + "는 css를 사용 할수 없습니다.");
  4943. }
  4944. }
  4945. } else if (window.getComputedStyle) {
  4946. fpGetCss = function(e, sName){
  4947. try{
  4948. if (sName == "cssFloat") sName = "float";
  4949. var d = e.ownerDocument || e.document || document;
  4950. var sVal = (e.style[sName]||d.defaultView.getComputedStyle(e,null).getPropertyValue(sName.replace(/([A-Z])/g,"-$1").toLowerCase()));
  4951. if (sName == "textDecoration") sVal = sVal.replace(",","");
  4952. return sVal;
  4953. }catch(ex){
  4954. throw new Error((e.tagName||"document") + "는 css를 사용 할수 없습니다.");
  4955. }
  4956. }
  4957. } else {
  4958. fpGetCss = function(e, sName){
  4959. try{
  4960. if (sName == "cssFloat" && IS_IE) sName = "styleFloat";
  4961. return e.style[sName];
  4962. }catch(ex){
  4963. throw new Error((e.tagName||"document") + "는 css를 사용 할수 없습니다.");
  4964. }
  4965. }
  4966. }
  4967. jindo.$Element.prototype._getCss = fpGetCss;
  4968. return fpGetCss(e, sName);
  4969. }
  4970. /**
  4971. * css에서 css를 세팅하기 위한 함수
  4972. * @ignore
  4973. * @param {Element} e
  4974. * @param {String} k
  4975. */
  4976. jindo.$Element.prototype._setCss = function(e, k, v){
  4977. if (("#top#left#right#bottom#").indexOf(k+"#") > 0 && (typeof v == "number" ||(/\d$/.test(v)))) {
  4978. e.style[k] = parseInt(v,10)+"px";
  4979. }else{
  4980. e.style[k] = v;
  4981. }
  4982. }
  4983. /**
  4984. * DOM 엘리먼트의 HTML 속성을 가져오거나 설정한다.
  4985. * 하나의 인자만 사용하면 해당 HTML 속성의 속성 값을 가져온다. 해당 속성이 없다면 null을 반환한다.
  4986. * 두 개의 인자를 사용하면 첫 번째 인자에 해당하는 HTML 속성의 속성 값을 두 번째 인자의 값으로 설정한다.
  4987. * 첫 번째 인자로 Object 혹은 $H 객체를 사용하면 두 개 이상의 HTML 속성을 한꺼번에 정의할 수 있다.
  4988. * @param {String|Object|$H} sName HTML 속성 이름 혹은 설정값 객체
  4989. * @param {String|Number} [sValue] 설정 값. 설정 값을 null로 지정하면 해당 HTML 속성을 삭제한다.
  4990. * @return {String|$Element} 값을 가져올 때는 String 설정 값을, 값을 설정할 때는 값을 설정한 현재의 $Element를 리턴한다.
  4991. * @description [Lite]
  4992. *
  4993. * @example
  4994. <a href="http://www.naver.com" id="sample_a" target="_blank">Naver</a>
  4995. $Element("sample_a").attr("href"); // http://www.naver.com
  4996. * @example
  4997. $Element("sample_a").attr("href", "http://www.hangame.com/");
  4998. //Before
  4999. <a href="http://www.naver.com" id="sample_a" target="_blank">Naver</a>
  5000. //After
  5001. <a href="http://www.hangame.com" id="sample_a" target="_blank">Naver</a>
  5002. * @example
  5003. $Element("sample_a").attr({
  5004. "href" : "http://www.hangame.com",
  5005. "target" : "_self"
  5006. })
  5007. //Before
  5008. <a href="http://www.naver.com" id="sample_a" target="_blank">Naver</a>
  5009. //After
  5010. <a href="http://www.hangame.com" id="sample_a" target="_self">Naver</a>
  5011. */
  5012. jindo.$Element.prototype.attr = function(sName, sValue) {
  5013. var e = this._element;
  5014. if (typeof sName == "string") {
  5015. if (typeof sValue != "undefined") {
  5016. var obj = {};
  5017. obj[sName] = sValue;
  5018. sName = obj;
  5019. } else {
  5020. if (sName == "class" || sName == "className"){
  5021. return e.className;
  5022. }else if(sName == "style"){
  5023. return e.style.cssText;
  5024. }else if(sName == "checked"||sName == "disabled"){
  5025. return !!e[sName];
  5026. }else if(sName == "value"){
  5027. return e.value;
  5028. }else if(sName == "href"){
  5029. return e.getAttribute(sName,2);
  5030. }
  5031. return e.getAttribute(sName);
  5032. }
  5033. }
  5034. if (typeof jindo.$H != "undefined" && sName instanceof jindo.$H) {
  5035. sName = sName.$value();
  5036. }
  5037. if (typeof sName == "object") {
  5038. for(var k in sName) {
  5039. if(sName.hasOwnProperty(k)){
  5040. if (typeof(sValue) != "undefined" && sValue === null) {
  5041. e.removeAttribute(k);
  5042. }else{
  5043. if (k == "class"|| k == "className") {
  5044. e.className = sName[k];
  5045. }else if(k == "style"){
  5046. e.style.cssText = sName[k];
  5047. }else if(k == "checked"||k == "disabled"){
  5048. e[k] = sName[k];
  5049. }else if(k == "value"){
  5050. e.value = sName[k];
  5051. }else{
  5052. e.setAttribute(k, sName[k]);
  5053. }
  5054. }
  5055. }
  5056. }
  5057. }
  5058. return this;
  5059. };
  5060. /**
  5061. * HTML 엘리먼트의 너비를 가져오거나 설정한다.
  5062. * @remark width 메서드는 HTML 엘리먼트의 실제 너비를 가져온다. 브라우저마다 Box 모델의 크기 계산 방법이 다르므로 CSS의 width 속성 값과 width 메서드의 반환 값은 서로 다를 수 있다.
  5063. * @param {Number} [width] 설정할 너비 값. 단위는 px 이며 매개 변수의 값은 숫자로 지정한다.<br>
  5064. * 매개 변수를 생략하면 너비 값을 가져온다.
  5065. * @return {Number | $Element} 값을 가져오는 경우에는 HTML 엘리먼트의 실제 너비를, 값을 설정하는 경우에는 너비 값이 변경된 현재의 $Element 객체를 반환한다.
  5066. * @description [Lite]
  5067. * @see $Element#height
  5068. *
  5069. * @example
  5070. <style type="text/css">
  5071. div { width:70px; height:50px; padding:5px; margin:5px; background:red; }
  5072. </style>
  5073. <div id="sample_div"></div>
  5074. ...
  5075. // 조회
  5076. $Element("sample_div").width(); // 80
  5077. * @example
  5078. // 위의 예제 HTML 엘리먼트에 너비 값을 설정
  5079. $Element("sample_div").width(200);
  5080. //Before
  5081. <div id="sample_div"></div>
  5082. //After
  5083. <div id="sample_div" style="width: 190px"></div>
  5084. */
  5085. jindo.$Element.prototype.width = function(width) {
  5086. if (typeof width == "number") {
  5087. var e = this._element;
  5088. e.style.width = width+"px";
  5089. var off = e.offsetWidth;
  5090. if (off != width && off!==0) {
  5091. var w = (width*2 - off);
  5092. if (w>0)
  5093. e.style.width = w + "px";
  5094. }
  5095. return this;
  5096. }
  5097. return this._element.offsetWidth;
  5098. };
  5099. /**
  5100. * HTML 엘리먼트의 높이를 가져오거나 설정한다.
  5101. * @remark height 메서드는 HTML 엘리먼트의 실제 높이를 가져온다. 브라우저마다 Box 모델의 크기 계산 방법이 다르므로 CSS의 height 속성 값과 height 메서드의 반환 값은 서로 다를 수 있다.
  5102. * @param {Number} [height] 설정할 높이 값. 단위는 px 이며 매개 변수의 값은 숫자로 지정한다.
  5103. * @return {Number | $Element} 값을 가져오는 경우에는 HTML 엘리먼트의 실제 높이를, 값을 설정하는 경우에는 높이 값이 변경된 현재의 $Element 객체를 반환한다.
  5104. * @description [Lite]
  5105. * @see $Element#width
  5106. *
  5107. * @example
  5108. <style type="text/css">
  5109. div { width:70px; height:50px; padding:5px; margin:5px; background:red; }
  5110. </style>
  5111. <div id="sample_div"></div>
  5112. ...
  5113. // 조회
  5114. $Element("sample_div").height(); // 60
  5115. * @example
  5116. // 위의 예제 HTML 엘리먼트에 높이 값을 설정
  5117. $Element("sample_div").height(100);
  5118. //Before
  5119. <div id="sample_div"></div>
  5120. //After
  5121. <div id="sample_div" style="height: 90px"></div>
  5122. */
  5123. jindo.$Element.prototype.height = function(height) {
  5124. if (typeof height == "number") {
  5125. var e = this._element;
  5126. e.style.height = height+"px";
  5127. var off = e.offsetHeight;
  5128. if (off != height && off!==0) {
  5129. var height = (height*2 - off);
  5130. if(height>0)
  5131. e.style.height = height + "px";
  5132. }
  5133. return this;
  5134. }
  5135. return this._element.offsetHeight;
  5136. };
  5137. /**
  5138. * HTML 엘리먼트의 클래스명을 설정하거나 반환한다.
  5139. * @param {String} [sClass] 설정할 클래스명<br>
  5140. * 매개 변수를 생략하면 HTML 엘리먼트의 현재의 클래스명을 반환한다.<br>
  5141. * 매개 변수를 지정하면 클래스명을 설정한다. 여러개의 클래스명을 설정하려면 공백으로 구분한다.
  5142. * @return {String | $Element} 클래스명을 조회하는 경우에는 클래스명을 반환한다.<br>
  5143. * 클래스가 두 개 이상이면 클래스명을 공백으로 구분하여 공백을 포함한 문자열로 반환한다.<br>
  5144. * 클래스명을 설정한 경우에는 변경된 현재의 $Element 객체를 반환한다.
  5145. * @description [Lite]
  5146. * @see $Element#hasClass
  5147. * @see $Element#addClass
  5148. * @see $Element#removeClass
  5149. * @see $Element#toggleClass
  5150. *
  5151. * @example
  5152. <style type="text/css">
  5153. p { margin: 8px; font-size:16px; }
  5154. .selected { color:#0077FF; }
  5155. .highlight { background:#C6E746; }
  5156. </style>
  5157. <p>Hello and <span id="sample_span" class="selected">Goodbye</span></p>
  5158. ...
  5159. // 클래스명 조회
  5160. $Element("sample_span").className(); // selected
  5161. * @example
  5162. // 위의 예제 HTML 엘리먼트에 클래스명 설정
  5163. welSample.className("highlight");
  5164. //Before
  5165. <p>Hello and <span id="sample_span" class="selected">Goodbye</span></p>
  5166. //After
  5167. <p>Hello and <span id="sample_span" class="highlight">Goodbye</span></p>
  5168. */
  5169. jindo.$Element.prototype.className = function(sClass) {
  5170. var e = this._element;
  5171. if (typeof sClass == "undefined") return e.className;
  5172. e.className = sClass;
  5173. return this;
  5174. };
  5175. /**
  5176. * HTML 엘리먼트에서 특정 클래스를 사용하고 있는지 확인한다.
  5177. * @param {String} sClass 확인할 클래스명
  5178. * @return {Boolean} 클래스 사용 여부
  5179. * @description [Lite]
  5180. * @see $Element#className
  5181. * @see $Element#addClass
  5182. * @see $Element#removeClass
  5183. * @see $Element#toggleClass
  5184. *
  5185. * @example
  5186. <style type="text/css">
  5187. p { margin: 8px; font-size:16px; }
  5188. .selected { color:#0077FF; }
  5189. .highlight { background:#C6E746; }
  5190. </style>
  5191. <p>Hello and <span id="sample_span" class="selected highlight">Goodbye</span></p>
  5192. ...
  5193. // 클래스의 사용여부를 확인
  5194. var welSample = $Element("sample_span");
  5195. welSample.hasClass("selected"); // true
  5196. welSample.hasClass("highlight"); // true
  5197. */
  5198. jindo.$Element.prototype.hasClass = function(sClass) {
  5199. if(this._element.classList){
  5200. jindo.$Element.prototype.hasClass = function(sClass){
  5201. return this._element.classList.contains(sClass);
  5202. }
  5203. } else {
  5204. jindo.$Element.prototype.hasClass = function(sClass){
  5205. return (" "+this._element.className+" ").indexOf(" "+sClass+" ") > -1;
  5206. }
  5207. }
  5208. return this.hasClass(sClass);
  5209. };
  5210. /**
  5211. * HTML 엘리먼트에 클래스를 추가한다.
  5212. * @param {String} sClass 추가할 클래스명. 여러개의 클래스명을 추가하려면 공백으로 구분한다.
  5213. * @return {$Element} 클래스가 추가된 현재의 $Element 객체
  5214. * @description [Lite]
  5215. * @see $Element#className
  5216. * @see $Element#hasClass
  5217. * @see $Element#removeClass
  5218. * @see $Element#toggleClass
  5219. *
  5220. * @example
  5221. // 클래스 추가
  5222. $Element("sample_span1").addClass("selected");
  5223. $Element("sample_span2").addClass("selected highlight");
  5224. //Before
  5225. <p>Hello and <span id="sample_span1">Goodbye</span></p>
  5226. <p>Hello and <span id="sample_span2">Goodbye</span></p>
  5227. //After
  5228. <p>Hello and <span id="sample_span1" class="selected">Goodbye</span></p>
  5229. <p>Hello and <span id="sample_span2" class="selected highlight">Goodbye</span></p>
  5230. */
  5231. jindo.$Element.prototype.addClass = function(sClass) {
  5232. if(this._element.classList){
  5233. jindo.$Element.prototype.addClass = function(sClass){
  5234. var aClass = sClass.split(/\s+/);
  5235. var flistApi = this._element.classList;
  5236. for(var i = aClass.length ; i-- ;){
  5237. flistApi.add(aClass[i]);
  5238. }
  5239. return this;
  5240. }
  5241. } else {
  5242. jindo.$Element.prototype.addClass = function(sClass){
  5243. var e = this._element;
  5244. var aClass = sClass.split(/\s+/);
  5245. var eachClass;
  5246. for (var i = aClass.length - 1; i >= 0 ; i--){
  5247. eachClass = aClass[i];
  5248. if (!this.hasClass(eachClass)) {
  5249. e.className = (e.className+" "+eachClass).replace(/^\s+/, "");
  5250. };
  5251. };
  5252. return this;
  5253. }
  5254. }
  5255. return this.addClass(sClass);
  5256. };
  5257. /**
  5258. * HTML 엘리먼트에서 특정 클래스를 제거한다.
  5259. * @param {String} sClass 제거할 클래스명. 여러개의 클래스명을 제거하려면 공백으로 구분한다.
  5260. * @return {$Element} 클래스가 제거된 현재의 $Element 객체
  5261. * @description [Lite]
  5262. * @see $Element#className
  5263. * @see $Element#hasClass
  5264. * @see $Element#addClass
  5265. * @see $Element#toggleClass
  5266. *
  5267. * @example
  5268. // 클래스 제거
  5269. $Element("sample_span").removeClass("selected");
  5270. //Before
  5271. <p>Hello and <span id="sample_span" class="selected highlight">Goodbye</span></p>
  5272. //After
  5273. <p>Hello and <span id="sample_span" class="highlight">Goodbye</span></p>
  5274. * @example
  5275. // 여러개의 클래스를 제거
  5276. $Element("sample_span").removeClass("selected highlight");
  5277. $Element("sample_span").removeClass("highlight selected");
  5278. //Before
  5279. <p>Hello and <span id="sample_span" class="selected highlight">Goodbye</span></p>
  5280. //After
  5281. <p>Hello and <span id="sample_span" class="">Goodbye</span></p>
  5282. */
  5283. jindo.$Element.prototype.removeClass = function(sClass) {
  5284. if(this._element.classList){
  5285. jindo.$Element.prototype.removeClass = function(sClass){
  5286. var flistApi = this._element.classList;
  5287. var aClass = sClass.split(" ");
  5288. for(var i = aClass.length ; i-- ;){
  5289. flistApi.remove(aClass[i]);
  5290. }
  5291. return this;
  5292. }
  5293. } else {
  5294. jindo.$Element.prototype.removeClass = function(sClass){
  5295. var e = this._element;
  5296. var aClass = sClass.split(/\s+/);
  5297. var eachClass;
  5298. for (var i = aClass.length - 1; i >= 0 ; i--){
  5299. eachClass = aClass[i];
  5300. if (this.hasClass(eachClass)) {
  5301. e.className = (" "+e.className.replace(/\s+$/, "").replace(/^\s+/, "")+" ").replace(" "+eachClass+" ", " ").replace(/\s+$/, "").replace(/^\s+/, "");
  5302. };
  5303. };
  5304. return this;
  5305. }
  5306. }
  5307. return this.removeClass(sClass);
  5308. };
  5309. /**
  5310. * HTML 엘리먼트에 클래스가 이미 적용되어 있으면 제거하고 만약 없으면 추가한다.
  5311. * @param {String} sClass 추가 혹은 제거할 클래스명
  5312. * @param {String} [sClass2] 추가 혹은 제거할 클래스명<br>
  5313. * sClass2 매개 변수를 생략하면 HTML 엘리먼트에서 sClass 매개 변수 값의 클래스를 사용 중인지 확인한다.<br>
  5314. * 만약 사용하고 있다면 해당 클래스를 제거하고, 사용하고 있지 않다면 추가한다.<br>
  5315. * 두 개의 매개 변수를 모두 사용하면, 두 클래스 중에서 사용하고 있는 것을 제거하고 나머지를 추가한다.
  5316. * @return {$Element} 클래스가 추가 혹은 제거된 현재의 $Element 객체
  5317. * @import core.$Element[hasClass,addClass,removeClass]
  5318. * @description [Lite]
  5319. * @see $Element#className
  5320. * @see $Element#hasClass
  5321. * @see $Element#addClass
  5322. * @see $Element#removeClass
  5323. *
  5324. * @example
  5325. // 매개 변수가 하나인 경우
  5326. $Element("sample_span1").toggleClass("highlight");
  5327. $Element("sample_span2").toggleClass("highlight");
  5328. //Before
  5329. <p>Hello and <span id="sample_span1" class="selected highlight">Goodbye</span></p>
  5330. <p>Hello and <span id="sample_span2" class="selected">Goodbye</span></p>
  5331. //After
  5332. <p>Hello and <span id="sample_span1" class="selected">Goodbye</span></p>
  5333. <p>Hello and <span id="sample_span2" class="selected highlight">Goodbye</span></p>
  5334. * @example
  5335. // 매개 변수가 두 개인 경우
  5336. $Element("sample_span1").toggleClass("selected", "highlight");
  5337. $Element("sample_span2").toggleClass("selected", "highlight");
  5338. //Before
  5339. <p>Hello and <span id="sample_span1" class="highlight">Goodbye</span></p>
  5340. <p>Hello and <span id="sample_span2" class="selected">Goodbye</span></p>
  5341. //After
  5342. <p>Hello and <span id="sample_span1" class="selected">Goodbye</span></p>
  5343. <p>Hello and <span id="sample_span2" class="highlight">Goodbye</span></p>
  5344. */
  5345. jindo.$Element.prototype.toggleClass = function(sClass, sClass2) {
  5346. if(this._element.classList){
  5347. jindo.$Element.prototype.toggleClass = function(sClass, sClass2){
  5348. if (typeof sClass2 == "undefined") {
  5349. this._element.classList.toggle(sClass);
  5350. } else {
  5351. if(this.hasClass(sClass)){
  5352. this.removeClass(sClass);
  5353. this.addClass(sClass2);
  5354. }else{
  5355. this.addClass(sClass);
  5356. this.removeClass(sClass2);
  5357. }
  5358. }
  5359. return this;
  5360. }
  5361. } else {
  5362. jindo.$Element.prototype.toggleClass = function(sClass, sClass2){
  5363. sClass2 = sClass2 || "";
  5364. if (this.hasClass(sClass)) {
  5365. this.removeClass(sClass);
  5366. if (sClass2) this.addClass(sClass2);
  5367. } else {
  5368. this.addClass(sClass);
  5369. if (sClass2) this.removeClass(sClass2);
  5370. }
  5371. return this;
  5372. }
  5373. }
  5374. return this.toggleClass(sClass, sClass2);
  5375. };
  5376. /**
  5377. * HTML 엘리먼트의 텍스트 노드 값을 가져오거나 설정한다.
  5378. * @param {String} [sText] 설정할 텍스트<br>
  5379. * 매개 변수를 생략하면 텍스트 노드를 조회하고, 매개 변수를 지정하면 매개 변수의 값으로 텍스트 노드를 설정한다.
  5380. * @returns {String} 값을 조회하는 경우에는 HTML 엘리먼트의 텍스트 노드를 반환하고,<br>
  5381. * 값을 설정하는 경우에는 텍스트 노드를 설정한 현재의 $Element 객체를 반환
  5382. * @description [Lite]
  5383. *
  5384. * @example
  5385. <ul id="sample_ul">
  5386. <li>하나</li>
  5387. <li>둘</li>
  5388. <li>셋</li>
  5389. <li>넷</li>
  5390. </ul>
  5391. ...
  5392. // 텍스트 노드 값 조회
  5393. $Element("sample_ul").text();
  5394. // 결과
  5395. // 하나
  5396. // 둘
  5397. // 셋
  5398. // 넷
  5399. @example
  5400. // 텍스트 노드 값 설정
  5401. $Element("sample_ul").text('다섯');
  5402. //Before
  5403. <ul id="sample_ul">
  5404. <li>하나</li>
  5405. <li>둘</li>
  5406. <li>셋</li>
  5407. <li>넷</li>
  5408. </ul>
  5409. //After
  5410. <ul id="sample_ul">다섯</ul>
  5411. @example
  5412. // 텍스트 노드 값 설정
  5413. $Element("sample_p").text("New Content");
  5414. //Before
  5415. <p id="sample_p">
  5416. Old Content
  5417. </p>
  5418. //After
  5419. <p id="sample_p">
  5420. New Content
  5421. </p>
  5422. */
  5423. jindo.$Element.prototype.text = function(sText) {
  5424. var ele = this._element;
  5425. var tag = this.tag;
  5426. var prop = (typeof ele.innerText != "undefined")?"innerText":"textContent";
  5427. if (tag == "textarea" || tag == "input") prop = "value";
  5428. var type = (typeof sText);
  5429. if (type != "undefined"&&(type == "string" || type == "number" || type == "boolean")) {
  5430. sText += "";
  5431. try {
  5432. /*
  5433. * Opera 11.01에서 textContext가 Get일때 정상적으로 동작하지 않음. 그래서 get일 때는 innerText을 사용하고 set하는 경우는 textContent을 사용한다.(http://devcafe.nhncorp.com/ajaxui/295768)
  5434. */
  5435. if (prop!="value") prop = (typeof ele.textContent != "undefined")?"textContent":"innerText";
  5436. ele[prop] = sText;
  5437. } catch(e) {
  5438. return this.html(sText.replace(/&/g, '&amp;').replace(/</g, '&lt;'));
  5439. }
  5440. return this;
  5441. }
  5442. return ele[prop];
  5443. };
  5444. /**
  5445. * HTML 엘리먼트의 내부 HTML(innerHTML) 을 가져오거나 설정한다.
  5446. * @param {String} [sHTML] 설정할 HTML 문자열<br>
  5447. * 매개 변수를 생략하면 내부 HTML 을 조회하고, 매개 변수를 지정하면 매개 변수의 값으로 내부 HTML을 변경한다.
  5448. * @return {String | $Element} 값을 조회하는 경우에는 HTML 엘리먼트의 내부 HTML을 반환하고,<br>
  5449. * 값을 설정하는 경우에는 내부 HTML 을 변경한 현재의 $Element 객체를 반환
  5450. * @see $Element#outerHTML
  5451. * @description [Lite]
  5452. *
  5453. * @example
  5454. <div id="sample_container">
  5455. <p><em>Old</em> content</p>
  5456. </div>
  5457. ...
  5458. // 내부 HTML 조회
  5459. $Element("sample_container").html(); // <p><em>Old</em> content</p>
  5460. * @example
  5461. // 내부 HTML 설정
  5462. $Element("sample_container").html("<p>New <em>content</em></p>");
  5463. //Before
  5464. <div id="sample_container">
  5465. <p><em>Old</em> content</p>
  5466. </div>
  5467. //After
  5468. <div id="sample_container">
  5469. <p>New <em>content</em></p>
  5470. </div>
  5471. */
  5472. jindo.$Element.prototype.html = function(sHTML) {
  5473. var isIe = IS_IE;
  5474. var isFF = IS_FF;
  5475. if (isIe) {
  5476. jindo.$Element.prototype.html = function(sHTML){
  5477. if (typeof sHTML != "undefined" && arguments.length) {
  5478. sHTML += "";
  5479. jindo.$$.release();
  5480. var oEl = this._element;
  5481. while(oEl.firstChild){
  5482. oEl.removeChild(oEl.firstChild);
  5483. }
  5484. /*
  5485. IE 나 FireFox 의 일부 상황에서 SELECT 태그나 TABLE, TR, THEAD, TBODY 태그에 innerHTML 을 셋팅해도
  5486. 문제가 생기지 않도록 보완 - hooriza
  5487. */
  5488. var sId = 'R' + new Date().getTime() + parseInt(Math.random() * 100000,10);
  5489. var oDoc = oEl.ownerDocument || oEl.document || document;
  5490. var oDummy;
  5491. var sTag = oEl.tagName.toLowerCase();
  5492. switch (sTag) {
  5493. case 'select':
  5494. case 'table':
  5495. oDummy = oDoc.createElement("div");
  5496. oDummy.innerHTML = '<' + sTag + ' class="' + sId + '">' + sHTML + '</' + sTag + '>';
  5497. break;
  5498. case 'tr':
  5499. case 'thead':
  5500. case 'tbody':
  5501. case 'colgroup':
  5502. oDummy = oDoc.createElement("div");
  5503. oDummy.innerHTML = '<table><' + sTag + ' class="' + sId + '">' + sHTML + '</' + sTag + '></table>';
  5504. break;
  5505. default:
  5506. oEl.innerHTML = sHTML;
  5507. break;
  5508. }
  5509. if (oDummy) {
  5510. var oFound;
  5511. for (oFound = oDummy.firstChild; oFound; oFound = oFound.firstChild)
  5512. if (oFound.className == sId) break;
  5513. if (oFound) {
  5514. var notYetSelected = true;
  5515. for (var oChild; oChild = oEl.firstChild;) oChild.removeNode(true); // innerHTML = '';
  5516. for (var oChild = oFound.firstChild; oChild; oChild = oFound.firstChild){
  5517. if(sTag=='select'){
  5518. /*
  5519. * ie에서 select테그일 경우 option중 selected가 되어 있는 option이 있는 경우 중간에
  5520. * selected가 되어 있으면 그 다음 부터는 계속 selected가 true로 되어 있어
  5521. * 해결하기 위해 cloneNode를 이용하여 option을 카피한 후 selected를 변경함. - mixed
  5522. */
  5523. var cloneNode = oChild.cloneNode(true);
  5524. if (oChild.selected && notYetSelected) {
  5525. notYetSelected = false;
  5526. cloneNode.selected = true;
  5527. }
  5528. oEl.appendChild(cloneNode);
  5529. oChild.removeNode(true);
  5530. }else{
  5531. oEl.appendChild(oChild);
  5532. }
  5533. }
  5534. oDummy.removeNode && oDummy.removeNode(true);
  5535. }
  5536. oDummy = null;
  5537. }
  5538. return this;
  5539. }
  5540. return this._element.innerHTML;
  5541. }
  5542. }else if(isFF){
  5543. jindo.$Element.prototype.html = function(sHTML){
  5544. if (typeof sHTML != "undefined" && arguments.length) {
  5545. sHTML += "";
  5546. var oEl = this._element;
  5547. if(!oEl.parentNode){
  5548. /*
  5549. IE 나 FireFox 의 일부 상황에서 SELECT 태그나 TABLE, TR, THEAD, TBODY 태그에 innerHTML 을 셋팅해도
  5550. 문제가 생기지 않도록 보완 - hooriza
  5551. */
  5552. var sId = 'R' + new Date().getTime() + parseInt(Math.random() * 100000,10);
  5553. var oDoc = oEl.ownerDocument || oEl.document || document;
  5554. var oDummy;
  5555. var sTag = oEl.tagName.toLowerCase();
  5556. switch (sTag) {
  5557. case 'select':
  5558. case 'table':
  5559. oDummy = oDoc.createElement("div");
  5560. oDummy.innerHTML = '<' + sTag + ' class="' + sId + '">' + sHTML + '</' + sTag + '>';
  5561. break;
  5562. case 'tr':
  5563. case 'thead':
  5564. case 'tbody':
  5565. case 'colgroup':
  5566. oDummy = oDoc.createElement("div");
  5567. oDummy.innerHTML = '<table><' + sTag + ' class="' + sId + '">' + sHTML + '</' + sTag + '></table>';
  5568. break;
  5569. default:
  5570. oEl.innerHTML = sHTML;
  5571. break;
  5572. }
  5573. if (oDummy) {
  5574. var oFound;
  5575. for (oFound = oDummy.firstChild; oFound; oFound = oFound.firstChild)
  5576. if (oFound.className == sId) break;
  5577. if (oFound) {
  5578. for (var oChild; oChild = oEl.firstChild;) oChild.removeNode(true); // innerHTML = '';
  5579. for (var oChild = oFound.firstChild; oChild; oChild = oFound.firstChild){
  5580. oEl.appendChild(oChild);
  5581. }
  5582. oDummy.removeNode && oDummy.removeNode(true);
  5583. }
  5584. oDummy = null;
  5585. }
  5586. }else{
  5587. oEl.innerHTML = sHTML;
  5588. }
  5589. return this;
  5590. }
  5591. return this._element.innerHTML;
  5592. }
  5593. }else{
  5594. jindo.$Element.prototype.html = function(sHTML){
  5595. if (typeof sHTML != "undefined" && arguments.length) {
  5596. sHTML += "";
  5597. var oEl = this._element;
  5598. oEl.innerHTML = sHTML;
  5599. return this;
  5600. }
  5601. return this._element.innerHTML;
  5602. }
  5603. }
  5604. return this.html(sHTML);
  5605. };
  5606. /**
  5607. * HTML 엘리먼트의 외부 HTML(outerHTML) 을 반환한다.
  5608. * @return {String} 외부 HTML
  5609. * @see $Element#html
  5610. * @description [Lite]
  5611. *
  5612. * @example
  5613. <h2 id="sample0">Today is...</h2>
  5614. <div id="sample1">
  5615. <p><span id="sample2">Sample</span> content</p>
  5616. </div>
  5617. ...
  5618. // 외부 HTML 값을 조회
  5619. $Element("sample0").outerHTML(); // <h2 id="sample0">Today is...</h2>
  5620. $Element("sample1").outerHTML(); // <div id="sample1"> <p><span id="sample2">Sample</span> content</p> </div>
  5621. $Element("sample2").outerHTML(); // <span id="sample2">Sample</span>
  5622. */
  5623. jindo.$Element.prototype.outerHTML = function() {
  5624. var e = this._element;
  5625. if (typeof e.outerHTML != "undefined") return e.outerHTML;
  5626. var oDoc = e.ownerDocument || e.document || document;
  5627. var div = oDoc.createElement("div");
  5628. var par = e.parentNode;
  5629. /**
  5630. 상위노드가 없으면 innerHTML반환
  5631. */
  5632. if(!par) return e.innerHTML;
  5633. par.insertBefore(div, e);
  5634. div.style.display = "none";
  5635. div.appendChild(e);
  5636. var s = div.innerHTML;
  5637. par.insertBefore(e, div);
  5638. par.removeChild(div);
  5639. return s;
  5640. };
  5641. /**
  5642. * HTML 엘리먼트를 HTML 문자열로 변환하여 반환한다. (outerHTML 메서드와 동일)
  5643. * @return {String} 외부 HTML
  5644. * @see $Element#outerHTML
  5645. */
  5646. jindo.$Element.prototype.toString = jindo.$Element.prototype.outerHTML;
  5647. /**
  5648. * @fileOverview $Element의 확장 메서드를 정의한 파일
  5649. * @name element.extend.js
  5650. */
  5651. /**
  5652. * appear ,disappear에서 사용되는 함수로 현재 transition을 사용 할수 있는지를 학인한다.
  5653. * @ignore
  5654. */
  5655. jindo.$Element._getTransition = function(){
  5656. var hasTransition = false , sTransitionName = "";
  5657. if (typeof document.body.style.trasition != "undefined") {
  5658. hasTransition = true;
  5659. sTransitionName = "trasition";
  5660. }
  5661. /*
  5662. 아직 firefox는 transitionEnd API를 지원 하지 않음.
  5663. */
  5664. // else if(typeof document.body.style.MozTransition !== "undefined"){
  5665. // hasTransition = true;
  5666. // sTransitionName = "MozTransition";
  5667. // }
  5668. else if(typeof document.body.style.webkitTransition !== "undefined"){
  5669. hasTransition = true;
  5670. sTransitionName = "webkitTransition";
  5671. }else if(typeof document.body.style.OTransition !== "undefined"){
  5672. hasTransition = true;
  5673. sTransitionName = "OTransition";
  5674. }
  5675. return (jindo.$Element._getTransition = function(){
  5676. return {
  5677. "hasTransition" : hasTransition,
  5678. "name" : sTransitionName
  5679. };
  5680. })();
  5681. }
  5682. /**
  5683. * HTML 엘리먼트를 서서히 나타나게 한다. (Fade-in 효과)
  5684. *
  5685. * @param {Number} duration HTML 엘리먼트가 완전히 나타날 때까지 걸리는 시간. 단위는 초를 사용한다.
  5686. * @param {Function} [callback] HTML 엘리먼트가 완전히 나타난 후에 실행할 콜백 함수.
  5687. * @return {$Element} 현재의 $Element 객체
  5688. *
  5689. * @remark IE6 에서 filter 사용 시 해당 엘리먼트가 position 속성을 가지고 있으면 사라지는 문제가 있기 때문에 HTML 엘리먼트에 position 속성이 없어야 한다.
  5690. * @remark webkit기반의 브라우저(safari5+, mobile safari, chrome, mobile webkit), opera10.60+ 에서는 CSS3 transition을 사용한다. 그 이외의 브라우저에서는 자바스크립트를 사용한다.
  5691. *
  5692. * @see $Element#show
  5693. * @see $Element#disappear
  5694. *
  5695. * @example
  5696. $Element("sample1").appear(5, function(){
  5697. $Element("sample2").appear(3);
  5698. });
  5699. //Before
  5700. <div style="display: none; background-color: rgb(51, 51, 153); width: 100px; height: 50px;" id="sample1">
  5701. <div style="display: none; background-color: rgb(165, 10, 81); width: 50px; height: 20px;" id="sample2">
  5702. </div>
  5703. </div>
  5704. //After(1) : sample1 엘리먼트가 나타남
  5705. <div style="display: block; background-color: rgb(51, 51, 153); width: 100px; height: 50px; opacity: 1;" id="sample1">
  5706. <div style="display: none; background-color: rgb(165, 10, 81); width: 50px; height: 20px;" id="sample2">
  5707. </div>
  5708. </div>
  5709. //After(2) : sample2 엘리먼트가 나타남
  5710. <div style="display: block; background-color: rgb(51, 51, 153); width: 100px; height: 50px; opacity: 1;" id="sample1">
  5711. <div style="display: block; background-color: rgb(165, 10, 81); width: 50px; height: 20px; opacity: 1;" id="sample2">
  5712. </div>
  5713. </div>
  5714. */
  5715. jindo.$Element.prototype.appear = function(duration, callback) {
  5716. var oTransition = jindo.$Element._getTransition();
  5717. if (oTransition.hasTransition) {
  5718. jindo.$Element.prototype.appear = function(duration, callback) {
  5719. duration = duration||0.3;
  5720. callback = callback || function(){};
  5721. var bindFunc = function(){
  5722. callback();
  5723. this.show();
  5724. this.removeEventListener(oTransition.name+"End", arguments.callee , false );
  5725. };
  5726. var ele = this._element;
  5727. var self = this;
  5728. if(!this.visible()){
  5729. ele.style.opacity = ele.style.opacity||0;
  5730. self.show();
  5731. }
  5732. ele.addEventListener( oTransition.name+"End", bindFunc , false );
  5733. ele.style[oTransition.name + 'Property'] = 'opacity';
  5734. ele.style[oTransition.name + 'Duration'] = duration+'s';
  5735. ele.style[oTransition.name + 'TimingFunction'] = 'linear';
  5736. setTimeout(function(){
  5737. ele.style.opacity = '1';
  5738. },1);
  5739. return this;
  5740. }
  5741. }else{
  5742. jindo.$Element.prototype.appear = function(duration, callback) {
  5743. var self = this;
  5744. var op = this.opacity();
  5745. if(!this.visible()) op = 0;
  5746. if (op == 1) return this;
  5747. try { clearTimeout(this._fade_timer); } catch(e){};
  5748. callback = callback || function(){};
  5749. var step = (1-op) / ((duration||0.3)*100);
  5750. var func = function(){
  5751. op += step;
  5752. self.opacity(op);
  5753. if (op >= 1) {
  5754. callback(self);
  5755. } else {
  5756. self._fade_timer = setTimeout(func, 10);
  5757. }
  5758. };
  5759. this.show();
  5760. func();
  5761. return this;
  5762. }
  5763. }
  5764. return this.appear(duration, callback);
  5765. };
  5766. /**
  5767. * HTML 엘리먼트를 서서히 사라지게 한다. (Fade-out 효과)<br>
  5768. * HTML 엘리먼트가 완전히 사라지면 엘리먼트의 display 속성은 none 으로 변한다.
  5769. *
  5770. * @param {Number} duration HTML 엘리먼트 완전히 사라질 때까지 걸리는 시간. 단위는 초를 사용한다.
  5771. * @param {Function} [callback] HTML 엘리먼트가 완전히 사라진 후에 실행할 콜백 함수.
  5772. * @return {$Element} 현재의 $Element 객체
  5773. *
  5774. * @remark webkit기반의 브라우저(safari5+, mobile safari, chrome, mobile webkit), opera10.60+ 에서는 CSS3 transition을 사용한다. 그 이외의 브라우저에서는 자바스크립트를 사용한다.
  5775. *
  5776. * @see $Element#hide
  5777. * @see $Element#appear
  5778. *
  5779. * @example
  5780. $Element("sample1").disappear(5, function(){
  5781. $Element("sample2").disappear(3);
  5782. });
  5783. //Before
  5784. <div id="sample1" style="background-color: rgb(51, 51, 153); width: 100px; height: 50px;">
  5785. </div>
  5786. <div id="sample2" style="background-color: rgb(165, 10, 81); width: 100px; height: 50px;">
  5787. </div>
  5788. //After(1) : sample1 엘리먼트가 사라짐
  5789. <div id="sample1" style="background-color: rgb(51, 51, 153); width: 100px; height: 50px; opacity: 1; display: none;">
  5790. </div>
  5791. <div id="sample2" style="background-color: rgb(165, 10, 81); width: 100px; height: 50px;">
  5792. </div>
  5793. //After(2) : sample2 엘리먼트가 사라짐
  5794. <div id="sample1" style="background-color: rgb(51, 51, 153); width: 100px; height: 50px; opacity: 1; display: none;">
  5795. </div>
  5796. <div id="sample2" style="background-color: rgb(165, 10, 81); width: 100px; height: 50px; opacity: 1; display: none;">
  5797. </div>
  5798. */
  5799. jindo.$Element.prototype.disappear = function(duration, callback) {
  5800. var oTransition = jindo.$Element._getTransition();
  5801. if (oTransition.hasTransition) {
  5802. jindo.$Element.prototype.disappear = function(duration, callback) {
  5803. duration = duration||0.3
  5804. var self = this;
  5805. callback = callback || function(){};
  5806. var bindFunc = function(){
  5807. callback();
  5808. this.removeEventListener(oTransition.name+"End", arguments.callee , false );
  5809. self.hide();
  5810. };
  5811. var ele = this._element;
  5812. ele.addEventListener( oTransition.name+"End", bindFunc , false );
  5813. ele.style[oTransition.name + 'Property'] = 'opacity';
  5814. ele.style[oTransition.name + 'Duration'] = duration+'s';
  5815. ele.style[oTransition.name + 'TimingFunction'] = 'linear';
  5816. /*
  5817. opera 버그로 인하여 아래와 같이 처리함.
  5818. */
  5819. setTimeout(function(){
  5820. ele.style.opacity = '0';
  5821. },1);
  5822. return this;
  5823. }
  5824. }else{
  5825. jindo.$Element.prototype.disappear = function(duration, callback) {
  5826. var self = this;
  5827. var op = this.opacity();
  5828. if (op == 0) return this;
  5829. try { clearTimeout(this._fade_timer); } catch(e){};
  5830. callback = callback || function(){};
  5831. var step = op / ((duration||0.3)*100);
  5832. var func = function(){
  5833. op -= step;
  5834. self.opacity(op);
  5835. if (op <= 0) {
  5836. self.hide();
  5837. self.opacity(1);
  5838. callback(self);
  5839. } else {
  5840. self._fade_timer = setTimeout(func, 10);
  5841. }
  5842. };
  5843. func();
  5844. return this;
  5845. }
  5846. }
  5847. return this.disappear(duration, callback);
  5848. };
  5849. /**
  5850. * HTML 엘리먼트의 위치를 가져오거나 설정한다.<br>
  5851. * <br>
  5852. * 매개 변수를 생략하면 위치 값을 가져온다.<br>
  5853. * 매개 변수를 지정하면 HTML 엘리먼트의 위치를 설정한다.<br>
  5854. * 기준점은 브라우저 문서의 왼쪽 상단이다.
  5855. *
  5856. * @param {Number} [nTop] 문서의 맨 위에서 HTML 엘리먼트 맨 위까지의 거리. 단위는 px
  5857. * @param {Number} [nLeft] 문서의 왼쪽 가장자리에서 HTML 엘리먼트 왼쪽 가장자리까지의 거리. 단위는 px
  5858. * @return {$Element | Object} 위치를 설정하면 위치 값이 변경된 $Element 객체를 반환하고,<br>
  5859. * 위치를 가져오면 HTML 엘리먼트의 top, left 위치 값을 객체로 반환한다.
  5860. *
  5861. * @remark HTML 엘리먼트가 보이는 상태에서 적용해야 한다. 엘리먼트가 화면에 보이지 않으면 offset 의 사용이 정확하지 않다.
  5862. * @remark 일부 브라우저와 일부 상황에서 inline 엘리먼트에 대한 위치가 올바르게 얻어지지 않는 문제가 있으며 이 경우 해당 엘리먼트를 position:relative; 로 바꿔주는 식으로 해결할 수 있다.
  5863. * @author Hooriza
  5864. *
  5865. * @example
  5866. <style type="text/css">
  5867. div { background-color:#2B81AF; width:20px; height:20px; float:left; left:100px; top:50px; position:absolute;}
  5868. </style>
  5869. <div id="sample"></div>
  5870. ...
  5871. // 위치 값 조회
  5872. $Element("sample").offset(); // { left=100, top=50 }
  5873. * @example
  5874. // 위치 값 설정
  5875. $Element("sample").offset(40, 30);
  5876. //Before
  5877. <div id="sample"></div>
  5878. //After
  5879. <div id="sample" style="top: 40px; left: 30px;"></div>
  5880. */
  5881. jindo.$Element.prototype.offset = function(nTop, nLeft) {
  5882. var oEl = this._element;
  5883. var oPhantom = null;
  5884. // setter
  5885. if (typeof nTop == 'number' && typeof nLeft == 'number') {
  5886. if (isNaN(parseInt(this.css('top'),10))) this.css('top', 0);
  5887. if (isNaN(parseInt(this.css('left'),10))) this.css('left', 0);
  5888. var oPos = this.offset();
  5889. var oGap = { top : nTop - oPos.top, left : nLeft - oPos.left };
  5890. oEl.style.top = parseInt(this.css('top'),10) + oGap.top + 'px';
  5891. oEl.style.left = parseInt(this.css('left'),10) + oGap.left + 'px';
  5892. return this;
  5893. }
  5894. // getter
  5895. var bSafari = /Safari/.test(navigator.userAgent);
  5896. var bIE = /MSIE/.test(navigator.userAgent);
  5897. var nVer = bIE?navigator.userAgent.match(/(?:MSIE) ([0-9.]+)/)[1]:0;
  5898. var fpSafari = function(oEl) {
  5899. var oPos = { left : 0, top : 0 };
  5900. for (var oParent = oEl, oOffsetParent = oParent.offsetParent; oParent = oParent.parentNode; ) {
  5901. if (oParent.offsetParent) {
  5902. oPos.left -= oParent.scrollLeft;
  5903. oPos.top -= oParent.scrollTop;
  5904. }
  5905. if (oParent == oOffsetParent) {
  5906. oPos.left += oEl.offsetLeft + oParent.clientLeft;
  5907. oPos.top += oEl.offsetTop + oParent.clientTop ;
  5908. if (!oParent.offsetParent) {
  5909. oPos.left += oParent.offsetLeft;
  5910. oPos.top += oParent.offsetTop;
  5911. }
  5912. oOffsetParent = oParent.offsetParent;
  5913. oEl = oParent;
  5914. }
  5915. }
  5916. return oPos;
  5917. };
  5918. var fpOthers = function(oEl) {
  5919. var oPos = { left : 0, top : 0 };
  5920. var oDoc = oEl.ownerDocument || oEl.document || document;
  5921. var oHtml = oDoc.documentElement;
  5922. var oBody = oDoc.body;
  5923. if (oEl.getBoundingClientRect) { // has getBoundingClientRect
  5924. if (!oPhantom) {
  5925. var bHasFrameBorder = (window == top);
  5926. if(!bHasFrameBorder){
  5927. try{
  5928. bHasFrameBorder = (window.frameElement && window.frameElement.frameBorder == 1);
  5929. }catch(e){}
  5930. }
  5931. if ((bIE && nVer < 8 && window.external) && bHasFrameBorder) {
  5932. oPhantom = { left : 2, top : 2 };
  5933. oBase = null;
  5934. } else {
  5935. oPhantom = { left : 0, top : 0 };
  5936. }
  5937. }
  5938. var box = oEl.getBoundingClientRect();
  5939. if (oEl !== oHtml && oEl !== oBody) {
  5940. oPos.left = box.left - oPhantom.left;
  5941. oPos.top = box.top - oPhantom.top;
  5942. oPos.left += oHtml.scrollLeft || oBody.scrollLeft;
  5943. oPos.top += oHtml.scrollTop || oBody.scrollTop;
  5944. }
  5945. } else if (oDoc.getBoxObjectFor) { // has getBoxObjectFor
  5946. var box = oDoc.getBoxObjectFor(oEl);
  5947. var vpBox = oDoc.getBoxObjectFor(oHtml || oBody);
  5948. oPos.left = box.screenX - vpBox.screenX;
  5949. oPos.top = box.screenY - vpBox.screenY;
  5950. } else {
  5951. for (var o = oEl; o; o = o.offsetParent) {
  5952. oPos.left += o.offsetLeft;
  5953. oPos.top += o.offsetTop;
  5954. }
  5955. for (var o = oEl.parentNode; o; o = o.parentNode) {
  5956. if (o.tagName == 'BODY') break;
  5957. if (o.tagName == 'TR') oPos.top += 2;
  5958. oPos.left -= o.scrollLeft;
  5959. oPos.top -= o.scrollTop;
  5960. }
  5961. }
  5962. return oPos;
  5963. };
  5964. return (bSafari ? fpSafari : fpOthers)(oEl);
  5965. };
  5966. /**
  5967. * 문자열 내의 JavaScript를 실행한다.<br>
  5968. * &lt;script&gt; 태그가 포함된 문자열을 매개 변수로 지정하면, &lt;script&gt; 안에 있는 내용을 파싱하여 eval 를 수행한다.
  5969. *
  5970. * @param {String} sHTML &lt;script&gt; 태그가 포함된 HTML 문자열
  5971. * @return {$Element} 현재의 $Element 객체를 반환
  5972. *
  5973. * @example
  5974. // script 태그가 포함된 문자열을 지정
  5975. var response = "<script type='text/javascript'>$Element('sample').appendHTML('<li>4</li>')</script>";
  5976. $Element("sample").evalScripts(response);
  5977. //Before
  5978. <ul id="sample">
  5979. <li>1</li>
  5980. <li>2</li>
  5981. <li>3</li>
  5982. </ul>
  5983. //After
  5984. <ul id="sample">
  5985. <li>1</li>
  5986. <li>2</li>
  5987. <li>3</li>
  5988. <li>4</li></ul>
  5989. */
  5990. jindo.$Element.prototype.evalScripts = function(sHTML) {
  5991. var aJS = [];
  5992. sHTML = sHTML.replace(new RegExp('<script(\\s[^>]+)*>(.*?)</'+'script>', 'gi'), function(_1, _2, sPart) { aJS.push(sPart); return ''; });
  5993. eval(aJS.join('\n'));
  5994. return this;
  5995. };
  5996. /**
  5997. * element를 뒤에 붙일때 사용되는 함수.
  5998. * @ignore
  5999. * @param {Element} 기준 엘리먼트
  6000. * @param {Element} 붙일 엘리먼트
  6001. * @return {$Element} 두번째 파라메터의 엘리먼트
  6002. */
  6003. jindo.$Element._append = function(oParent, oChild){
  6004. if (typeof oChild == "string") {
  6005. oChild = jindo.$(oChild);
  6006. }else if(oChild instanceof jindo.$Element){
  6007. oChild = oChild.$value();
  6008. }
  6009. oParent._element.appendChild(oChild);
  6010. return oParent;
  6011. }
  6012. /**
  6013. * element를 앞에 붙일때 사용되는 함수.
  6014. * @ignore
  6015. * @param {Element} 기준 엘리먼트
  6016. * @param {Element} 붙일 엘리먼트
  6017. * @return {$Element} 두번째 파라메터의 엘리먼트
  6018. */
  6019. jindo.$Element._prepend = function(oParent, oChild){
  6020. if (typeof oParent == "string") {
  6021. oParent = jindo.$(oParent);
  6022. }else if(oParent instanceof jindo.$Element){
  6023. oParent = oParent.$value();
  6024. }
  6025. var nodes = oParent.childNodes;
  6026. if (nodes.length > 0) {
  6027. oParent.insertBefore(oChild._element, nodes[0]);
  6028. } else {
  6029. oParent.appendChild(oChild._element);
  6030. }
  6031. return oChild;
  6032. }
  6033. /**
  6034. * HTML 엘리먼트에 마지막 자식 노드를 추가한다.
  6035. *
  6036. * @param {$Element | HTML Element | String} oElement 추가할 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6037. * <br>
  6038. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 마지막 자식노드로 추가한다.<br>
  6039. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 마지막 자식노드로 추가한다.<br>
  6040. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 마지막 자식노드로 추가한다.
  6041. * @return {$Element} $Element 객체 자신
  6042. *
  6043. * @see $Element#prepend
  6044. * @see $Element#before
  6045. * @see $Element#after
  6046. * @see $Element#appendTo
  6047. * @see $Element#prependTo
  6048. *
  6049. * @example
  6050. // id 가 sample1 인 HTML 엘리먼트에
  6051. // id 가 sample2 인 HTML 엘리먼트를 추가
  6052. $Element("sample1").append("sample2");
  6053. //Before
  6054. <div id="sample2">
  6055. <div>Hello 2</div>
  6056. </div>
  6057. <div id="sample1">
  6058. <div>Hello 1</div>
  6059. </div>
  6060. //After
  6061. <div id="sample1">
  6062. <div>Hello 1</div>
  6063. <div id="sample2">
  6064. <div>Hello 2</div>
  6065. </div>
  6066. </div>
  6067. * @example
  6068. // id 가 sample 인 HTML 엘리먼트에
  6069. // 새로운 DIV 엘리먼트를 추가
  6070. var elChild = $("<div>Hello New</div>");
  6071. $Element("sample").append(elChild);
  6072. //Before
  6073. <div id="sample">
  6074. <div>Hello</div>
  6075. </div>
  6076. //After
  6077. <div id="sample">
  6078. <div>Hello </div>
  6079. <div>Hello New</div>
  6080. </div>
  6081. */
  6082. jindo.$Element.prototype.append = function(oElement) {
  6083. return jindo.$Element._append(this,oElement);
  6084. };
  6085. /**
  6086. * HTML 엘리먼트에 첫 번째 자식 노드를 추가한다.
  6087. *
  6088. * @param {$Element | HTMLElement | String} oElement 추가할 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6089. * <br>
  6090. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 첫 번째 자식노드로 추가한다.<br>
  6091. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 첫 번째 자식노드로 추가한다.<br>
  6092. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 첫 번째 자식노드로 추가한다.
  6093. * @return {$Element} $Element 객체 자신
  6094. *
  6095. * @see $Element#append
  6096. * @see $Element#before
  6097. * @see $Element#after
  6098. * @see $Element#appendTo
  6099. * @see $Element#prependTo
  6100. *
  6101. * @example
  6102. // id 가 sample1 인 HTML 엘리먼트에서
  6103. // id 가 sample2 인 HTML 엘리먼트를 첫 번째 자식노드로 이동
  6104. $Element("sample1").prepend("sample2");
  6105. //Before
  6106. <div id="sample1">
  6107. <div>Hello 1</div>
  6108. <div id="sample2">
  6109. <div>Hello 2</div>
  6110. </div>
  6111. </div>
  6112. //After
  6113. <div id="sample1">
  6114. <div id="sample2">
  6115. <div>Hello 2</div>
  6116. </div>
  6117. <div>Hello 1</div>
  6118. </div>
  6119. * @example
  6120. // id 가 sample 인 HTML 엘리먼트에
  6121. // 새로운 DIV 엘리먼트를 추가
  6122. var elChild = $("<div>Hello New</div>");
  6123. $Element("sample").prepend(elChild);
  6124. //Before
  6125. <div id="sample">
  6126. <div>Hello</div>
  6127. </div>
  6128. //After
  6129. <div id="sample">
  6130. <div>Hello New</div>
  6131. <div>Hello</div>
  6132. </div>
  6133. */
  6134. jindo.$Element.prototype.prepend = function(oElement) {
  6135. return jindo.$Element._prepend(this._element, jindo.$Element(oElement));
  6136. };
  6137. /**
  6138. * $Element 객체 내부의 HTML 엘리먼트를 매개 변수로 지정한 엘리먼트로 대체한다.
  6139. *
  6140. * @param {$Element | HTML Element | String} oElement 대체할 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6141. * <br>
  6142. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트로 대체한다.<br>
  6143. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트로 대체한다.<br>
  6144. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트로 대체한다.
  6145. * @return {$Element} HTML 엘리먼트가 대체 된 $Element 객체를 반환
  6146. *
  6147. * @example
  6148. // id 가 sample1 인 HTML 엘리먼트에서
  6149. // id 가 sample2 인 HTML 엘리먼트로 대체
  6150. $Element('sample1').replace('sample2');
  6151. //Before
  6152. <div>
  6153. <div id="sample1">Sample1</div>
  6154. </div>
  6155. <div id="sample2">Sample2</div>
  6156. //After
  6157. <div>
  6158. <div id="sample2">Sample2</div>
  6159. </div>
  6160. * @example
  6161. // 새로운 DIV 엘리먼트로 대체
  6162. $Element("btn").replace($("<div>Sample</div>"));
  6163. //Before
  6164. <button id="btn">Sample</button>
  6165. //After
  6166. <div>Sample</div>
  6167. */
  6168. jindo.$Element.prototype.replace = function(oElement) {
  6169. jindo.$$.release();
  6170. var e = this._element;
  6171. var oParentNode = e.parentNode;
  6172. var o = jindo.$Element(oElement);
  6173. if(oParentNode&&oParentNode.replaceChild){
  6174. oParentNode.replaceChild(o.$value(),e);
  6175. return o;
  6176. }
  6177. var o = o.$value();
  6178. oParentNode.insertBefore(o, e);
  6179. oParentNode.removeChild(e);
  6180. return o;
  6181. };
  6182. /**
  6183. * HTML 엘리먼트를 다른 HTML 엘리먼트의 마지막 자식노드로 추가한다.
  6184. *
  6185. * @param {$Element | HTML Element | String} oElement 부모가 될 HTML 엘리먼트. <br>
  6186. * <br>
  6187. * 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6188. * <br>
  6189. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 부모로 한다.<br>
  6190. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 부모로 한다.<br>
  6191. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 부모로 한다.
  6192. * @return {$Element} 인자로 받은 엘리먼트
  6193. *
  6194. * @see $Element#append
  6195. * @see $Element#prepend
  6196. * @see $Element#after
  6197. * @see $Element#appendTo
  6198. * @see $Element#prependTo
  6199. *
  6200. * @example
  6201. // id 가 sample2 인 HTML 엘리먼트에
  6202. // id 가 sample1 인 HTML 엘리먼트를 추가
  6203. $Element("sample1").appendTo("sample2");
  6204. //Before
  6205. <div id="sample1">
  6206. <div>Hello 1</div>
  6207. </div>
  6208. <div id="sample2">
  6209. <div>Hello 2</div>
  6210. </div>
  6211. //After
  6212. <div id="sample2">
  6213. <div>Hello 2</div>
  6214. <div id="sample1">
  6215. <div>Hello 1</div>
  6216. </div>
  6217. </div>
  6218. */
  6219. jindo.$Element.prototype.appendTo = function(oElement) {
  6220. var ele = jindo.$Element(oElement);
  6221. jindo.$Element._append(ele, this._element);
  6222. return ele;
  6223. };
  6224. /**
  6225. * HTML 엘리먼트를 다른 HTML 엘리먼트의 첫 번째 자식노드로 추가한다.
  6226. *
  6227. * @param {$Element | HTML Element | String} oElement 부모가 될 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6228. * <br>
  6229. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 부모로 한다.<br>
  6230. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 부모로 한다.<br>
  6231. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 부모로 한다.
  6232. * @return {$Element} 인자로 받은 엘리먼트
  6233. *
  6234. * @see $Element#append
  6235. * @see $Element#prepend
  6236. * @see $Element#after
  6237. * @see $Element#appendTo
  6238. * @see $Element#prependTo
  6239. *
  6240. * @example
  6241. // id 가 sample2 인 HTML 엘리먼트에
  6242. // id 가 sample1 인 HTML 엘리먼트를 추가
  6243. $Element("sample1").prependTo("sample2");
  6244. //Before
  6245. <div id="sample1">
  6246. <div>Hello 1</div>
  6247. </div>
  6248. <div id="sample2">
  6249. <div>Hello 2</div>
  6250. </div>
  6251. //After
  6252. <div id="sample2">
  6253. <div id="sample1">
  6254. <div>Hello 1</div>
  6255. </div>
  6256. <div>Hello 2</div>
  6257. </div>
  6258. */
  6259. jindo.$Element.prototype.prependTo = function(oElement) {
  6260. jindo.$Element._prepend(oElement, this);
  6261. return jindo.$Element(oElement);
  6262. };
  6263. /**
  6264. * HTML 엘리먼트 바로 앞에 HTML 엘리먼트를 추가한다.
  6265. *
  6266. * @param {$Element | HTML Element | String} oElement 추가할 HTML 엘리먼트.<br>
  6267. * <br>
  6268. * 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6269. * <br>
  6270. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 추가한다.<br>
  6271. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 추가한다.<br>
  6272. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 추가한다.
  6273. * @return {$Element} 추가 된 $Element 객체
  6274. *
  6275. * @see $Element#append
  6276. * @see $Element#prepend
  6277. * @see $Element#after
  6278. * @see $Element#appendTo
  6279. * @see $Element#prependTo
  6280. *
  6281. * @example
  6282. // id 가 sample1 인 HTML 엘리먼트 앞에
  6283. // id 가 sample2 인 HTML 엘리먼트를 추가 함
  6284. $Element("sample1").before("sample2"); // sample2를 래핑한 $Element 를 반환
  6285. //Before
  6286. <div id="sample1">
  6287. <div>Hello 1</div>
  6288. <div id="sample2">
  6289. <div>Hello 2</div>
  6290. </div>
  6291. </div>
  6292. //After
  6293. <div id="sample2">
  6294. <div>Hello 2</div>
  6295. </div>
  6296. <div id="sample1">
  6297. <div>Hello 1</div>
  6298. </div>
  6299. * @example
  6300. // 새로운 DIV 엘리먼트를 추가
  6301. var elNew = $("<div>Hello New</div>");
  6302. $Element("sample").before(elNew); // elNew 엘리먼트를 래핑한 $Element 를 반환
  6303. //Before
  6304. <div id="sample">
  6305. <div>Hello</div>
  6306. </div>
  6307. //After
  6308. <div>Hello New</div>
  6309. <div id="sample">
  6310. <div>Hello</div>
  6311. </div>
  6312. */
  6313. jindo.$Element.prototype.before = function(oElement) {
  6314. var oRich = jindo.$Element(oElement);
  6315. var o = oRich.$value();
  6316. this._element.parentNode.insertBefore(o, this._element);
  6317. return oRich;
  6318. };
  6319. /**
  6320. * HTML 엘리먼트 바로 뒤에 HTML 엘리먼트를 추가한다.
  6321. *
  6322. * @param {$Element | HTML Element | String} oElement 추가할 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6323. * <br>
  6324. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 추가한다.<br>
  6325. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 추가한다.<br>
  6326. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 추가한다.
  6327. * @return {$Element} 추가 된 $Element 객체
  6328. *
  6329. * @see $Element#append
  6330. * @see $Element#prepend
  6331. * @see $Element#before
  6332. * @see $Element#appendTo
  6333. * @see $Element#prependTo
  6334. *
  6335. * @example
  6336. // id 가 sample1 인 HTML 엘리먼트 뒤에
  6337. // id 가 sample2 인 HTML 엘리먼트를 추가 함
  6338. $Element("sample1").after("sample2"); // sample2를 래핑한 $Element 를 반환
  6339. //Before
  6340. <div id="sample1">
  6341. <div>Hello 1</div>
  6342. <div id="sample2">
  6343. <div>Hello 2</div>
  6344. </div>
  6345. </div>
  6346. //After
  6347. <div id="sample1">
  6348. <div>Hello 1</div>
  6349. </div>
  6350. <div id="sample2">
  6351. <div>Hello 2</div>
  6352. </div>
  6353. * @example
  6354. // 새로운 DIV 엘리먼트를 추가
  6355. var elNew = $("<div>Hello New</div>");
  6356. $Element("sample").after(elNew); // elNew 엘리먼트를 래핑한 $Element 를 반환
  6357. //Before
  6358. <div id="sample">
  6359. <div>Hello</div>
  6360. </div>
  6361. //After
  6362. <div id="sample">
  6363. <div>Hello</div>
  6364. </div>
  6365. <div>Hello New</div>
  6366. */
  6367. jindo.$Element.prototype.after = function(oElement) {
  6368. var o = this.before(oElement);
  6369. o.before(this);
  6370. return o;
  6371. };
  6372. /**
  6373. * HTML 엘리먼트의 상위 엘리먼트 노드를 검색한다.
  6374. *
  6375. * @param {Function} [pFunc] 상위 엘리먼트 노드의 검색 조건을 지정한 콜백 함수.<br>
  6376. * 매개 변수를 생략하면 부모 엘리먼트 노드를 반환하고,<br>
  6377. * 매개 변수로 콜백 함수를 지정하면 콜백 함수의 실행 결과가 true 인 상위 엘리먼트 노드의 배열을 반환한다.<br>
  6378. * 콜백 함수에 매개 변수로 탐색 중인 상위 엘리먼트 노드의 $Element 객체를 넘긴다.
  6379. * @param {Number} [limit] 탐색할 상위 엘리먼트 노드의 뎁스.<br>
  6380. * 매개 변수를 생략하면 모든 상위 엘리먼트 노드를 탐색한다.<br>
  6381. * pFunc 매개 변수를 null로 설정하고 limit 매개 변수를 설정하면 제한된 뎁스의 상위 엘리먼트 노드를 조건 없이 검색한다.
  6382. * @return {$Element | Array} 부모 엘리먼트 노드 혹은 상위 엘리먼트 노드의 배열.<br>
  6383. * 매개 변수를 생략하여 부모 엘리먼트 노드를 반환하는 경우, $Element 타입으로 반환한다.<br>
  6384. * 그 이외에는 검색된 엘리먼트 노드를 $Element의 배열로 반환한다.
  6385. *
  6386. * @see $Element#child
  6387. * @see $Element#prev
  6388. * @see $Element#next
  6389. * @see $Element#first
  6390. * @see $Element#last
  6391. * @see $Element#indexOf
  6392. *
  6393. * @example
  6394. <div class="sample" id="div1">
  6395. <div id="div2">
  6396. <div class="sample" id="div3">
  6397. <div id="target">
  6398. Sample
  6399. <div id="div4">
  6400. Sample
  6401. </div>
  6402. <div class="sample" id="div5">
  6403. Sample
  6404. </div>
  6405. </div>
  6406. <div class="sample" id="div6">
  6407. Sample
  6408. </div>
  6409. </div>
  6410. </div>
  6411. </div>
  6412. <script type="text/javascript">
  6413. var welTarget = $Element("target");
  6414. var parent = welTarget.parent();
  6415. // id가 div3인 DIV를 래핑한 $Element를 반환
  6416. parent = welTarget.parent(function(v){
  6417. return v.hasClass("sample");
  6418. });
  6419. // id가 div3인 DIV를 래핑한 $Element와
  6420. // id가 div1인 DIV를 래핑한 $Element를 원소로 하는 배열을 반환
  6421. parent = welTarget.parent(function(v){
  6422. return v.hasClass("sample");
  6423. }, 1);
  6424. // id가 div3인 DIV를 래핑한 $Element를 원소로 하는 배열을 반환
  6425. </script>
  6426. */
  6427. jindo.$Element.prototype.parent = function(pFunc, limit) {
  6428. var e = this._element;
  6429. var a = [], p = null;
  6430. if (typeof pFunc == "undefined") return jindo.$Element(e.parentNode);
  6431. if (typeof limit == "undefined" || limit == 0) limit = -1;
  6432. while (e.parentNode && limit-- != 0) {
  6433. p = jindo.$Element(e.parentNode);
  6434. if (e.parentNode == document.documentElement) break;
  6435. if (!pFunc || (pFunc && pFunc(p))) a[a.length] = p;
  6436. e = e.parentNode;
  6437. }
  6438. return a;
  6439. };
  6440. /**
  6441. * HTML 엘리먼트의 하위 엘리먼트 노드를 검색한다.
  6442. *
  6443. * @param {Function} [pFunc] 하위 엘리먼트 노드의 검색 조건을 지정한 콜백 함수.<br>
  6444. * 매개 변수를 생략하면 자식 엘리먼트 노드의 배열을 반환하고,<br>
  6445. * 매개 변수로 콜백 함수를 지정하면 콜백 함수의 실행 결과가 true 인 하위 엘리먼트 노드의 배열을 반환한다.<br>
  6446. * 콜백 함수에 매개 변수로 탐색 중인 하위 엘리먼트 노드의 $Element 객체를 넘긴다.
  6447. * @param {Number} [limit] 탐색할 하위 엘리먼트 노드의 뎁스.<br>
  6448. * 매개 변수를 생략하면 모든 하위 엘리먼트 노드를 탐색한다.<br>
  6449. * pFunc 매개 변수를 null로 설정하고 limit 매개 변수를 설정하면 제한된 뎁스의 하위 엘리먼트 노드를 조건 없이 검색한다.
  6450. * @return {$Element | Array} 자식 엘리먼트 노드 혹은 조건에 맞는 하위 노드의 $Element의 배열을 반환한다.
  6451. *
  6452. * @see $Element#parent
  6453. * @see $Element#prev
  6454. * @see $Element#next
  6455. * @see $Element#first
  6456. * @see $Element#last
  6457. * @see $Element#indexOf
  6458. *
  6459. * @example
  6460. <div class="sample" id="target">
  6461. <div id="div1">
  6462. <div class="sample" id="div2">
  6463. <div id="div3">
  6464. Sample
  6465. <div id="div4">
  6466. Sample
  6467. </div>
  6468. <div class="sample" id="div5">
  6469. Sample
  6470. <div class="sample" id="div6">
  6471. Sample
  6472. </div>
  6473. </div>
  6474. </div>
  6475. </div>
  6476. </div>
  6477. <div class="sample" id="div7">
  6478. Sample
  6479. </div>
  6480. </div>
  6481. <script type="text/javascript">
  6482. var welTarget = $Element("target");
  6483. var child = welTarget.child();
  6484. // id가 div1인 DIV를 래핑한 $Element와
  6485. // id가 div7인 DIV를 래핑한 $Element를 원소로 하는 배열을 반환
  6486. child = welTarget.child(function(v){
  6487. return v.hasClass("sample");
  6488. });
  6489. // id가 div2인 DIV를 래핑한 $Element와
  6490. // id가 div5인 DIV를 래핑한 $Element와
  6491. // id가 div6인 DIV를 래핑한 $Element와
  6492. // id가 div7인 DIV를 래핑한 $Element를 원소로 하는 배열을 반환
  6493. child = welTarget.child(function(v){
  6494. return v.hasClass("sample");
  6495. }, 1);
  6496. // id가 div7인 DIV를 래핑한 $Element를 원소로 하는 배열을 반환
  6497. child = welTarget.child(function(v){
  6498. return v.hasClass("sample");
  6499. }, 2);
  6500. // id가 div2인 DIV를 래핑한 $Element와
  6501. // id가 div7인 DIV를 래핑한 $Element를 원소로 하는 배열을 반환
  6502. </script>
  6503. */
  6504. jindo.$Element.prototype.child = function(pFunc, limit) {
  6505. var e = this._element;
  6506. var a = [], c = null, f = null;
  6507. if (typeof pFunc == "undefined") return jindo.$A(e.childNodes).filter(function(v){ return v.nodeType == 1}).map(function(v){ return jindo.$Element(v) }).$value();
  6508. if (typeof limit == "undefined" || limit == 0) limit = -1;
  6509. (f = function(el, lim){
  6510. var ch = null, o = null;
  6511. for(var i=0; i < el.childNodes.length; i++) {
  6512. ch = el.childNodes[i];
  6513. if (ch.nodeType != 1) continue;
  6514. o = jindo.$Element(el.childNodes[i]);
  6515. if (!pFunc || (pFunc && pFunc(o))) a[a.length] = o;
  6516. if (lim != 0) f(el.childNodes[i], lim-1);
  6517. }
  6518. })(e, limit-1);
  6519. return a;
  6520. };
  6521. /**
  6522. * HTML 엘리먼트의 이전에 나오는 형제 엘리먼트 노드를 검색한다.
  6523. *
  6524. * @param {Function} [pFunc] 이전 형제 엘리먼트 노드의 검색 조건을 지정한 콜백 함수.<br>
  6525. * 매개 변수를 생략하면 바로 이전의 형제 엘리먼트 노드를 반환하고,<br>
  6526. * 매개 변수로 콜백 함수를 지정하면 콜백 함수의 실행 결과가 true 인 형제 엘리먼트 노드의 배열을 반환한다.<br>
  6527. * 콜백 함수에 매개 변수로 탐색 중인 형제 엘리먼트 노드를 넘긴다. ($Element 객체가 아님)
  6528. * @return {$Element | Array} 바로 전의 형제 엘리먼트 노드를 가리키는 $Element 혹은 조건에 맞는 형제 노드의 $Element의 배열을 반환한다.
  6529. *
  6530. * @see $Element#parent
  6531. * @see $Element#child
  6532. * @see $Element#next
  6533. * @see $Element#first
  6534. * @see $Element#last
  6535. * @see $Element#indexOf
  6536. *
  6537. * @example
  6538. <div class="sample" id="sample_div1">
  6539. <div id="sample_div2">
  6540. <div class="sample" id="sample_div3">
  6541. Sample1
  6542. </div>
  6543. <div id="sample_div4">
  6544. Sample2
  6545. </div>
  6546. <div class="sample" id="sample_div5">
  6547. Sample3
  6548. </div>
  6549. <div id="sample_div">
  6550. Sample4
  6551. <div id="sample_div6">
  6552. Sample5
  6553. </div>
  6554. </div>
  6555. <div id="sample_div7">
  6556. Sample6
  6557. </div>
  6558. <div class="sample" id="sample_div8">
  6559. Sample7
  6560. </div>
  6561. </div>
  6562. </div>
  6563. <script type="text/javascript">
  6564. var sibling = $Element("sample_div").prev();
  6565. // id가 sample_div5인 DIV를 래핑한 $Element를 반환
  6566. sibling = $Element("sample_div").prev(function(v){
  6567. return $Element(v).hasClass("sample");
  6568. });
  6569. // id가 sample_div5인 DIV를 래핑한 $Element와
  6570. // id가 sample_div3인 DIV를 래핑한 $Element를 원소로 하는 배열을 반환
  6571. </script>
  6572. */
  6573. jindo.$Element.prototype.prev = function(pFunc) {
  6574. var e = this._element;
  6575. var a = [];
  6576. var b = (typeof pFunc == "undefined");
  6577. if (!e) return b?jindo.$Element(null):a;
  6578. do {
  6579. e = e.previousSibling;
  6580. if (!e || e.nodeType != 1) continue;
  6581. if (b) return jindo.$Element(e);
  6582. if (!pFunc || pFunc(e)) a[a.length] = jindo.$Element(e);
  6583. } while(e);
  6584. return b?jindo.$Element(e):a;
  6585. };
  6586. /**
  6587. * HTML 엘리먼트의 다음에 나오는 형제 엘리먼트 노드를 검색한다.
  6588. *
  6589. * @param {Function} [pFunc] 다음 형제 엘리먼트 노드의 검색 조건을 지정한 콜백 함수.<br>
  6590. * 매개 변수를 생략하면 바로 다음의 형제 엘리먼트 노드를 반환하고,<br>
  6591. * 매개 변수로 콜백 함수를 지정하면 콜백 함수의 실행 결과가 true 인 형제 엘리먼트 노드의 배열을 반환한다.<br>
  6592. * 콜백 함수에 매개 변수로 탐색 중인 형제 엘리먼트 노드를 넘긴다. ($Element 객체가 아님)
  6593. * @return {$Element | Array} 바로 다음의 형제 엘리먼트 노드를 가리키는 $Element 혹은 조건에 맞는 형제 노드의 $Element의 배열을 반환한다.
  6594. *
  6595. * @see $Element#parent
  6596. * @see $Element#child
  6597. * @see $Element#prev
  6598. * @see $Element#first
  6599. * @see $Element#last
  6600. * @see $Element#indexOf
  6601. *
  6602. * @example
  6603. <div class="sample" id="sample_div1">
  6604. <div id="sample_div2">
  6605. <div class="sample" id="sample_div3">
  6606. Sample1
  6607. </div>
  6608. <div id="sample_div4">
  6609. Sample2
  6610. </div>
  6611. <div class="sample" id="sample_div5">
  6612. Sample3
  6613. </div>
  6614. <div id="sample_div">
  6615. Sample4
  6616. <div id="sample_div6">
  6617. Sample5
  6618. </div>
  6619. </div>
  6620. <div id="sample_div7">
  6621. Sample6
  6622. </div>
  6623. <div class="sample" id="sample_div8">
  6624. Sample7
  6625. </div>
  6626. </div>
  6627. </div>
  6628. <script type="text/javascript">
  6629. var sibling = $Element("sample_div").next();
  6630. // id가 sample_div7인 DIV를 래핑한 $Element를 반환
  6631. sibling = $Element("sample_div").next(function(v){
  6632. return $Element(v).hasClass("sample");
  6633. });
  6634. // id가 sample_div8인 DIV를 래핑한 $Element를 원소로 하는 배열을 반환
  6635. </script>
  6636. */
  6637. jindo.$Element.prototype.next = function(pFunc) {
  6638. var e = this._element;
  6639. var a = [];
  6640. var b = (typeof pFunc == "undefined");
  6641. if (!e) return b?jindo.$Element(null):a;
  6642. do {
  6643. e = e.nextSibling;
  6644. if (!e || e.nodeType != 1) continue;
  6645. if (b) return jindo.$Element(e);
  6646. if (!pFunc || pFunc(e)) a[a.length] = jindo.$Element(e);
  6647. } while(e);
  6648. return b?jindo.$Element(e):a;
  6649. };
  6650. /**
  6651. * HTML 엘리먼트의 첫 번째 자식 엘리먼트 노드를 반환한다.
  6652. *
  6653. * @return {$Element} 첫 번째 자식 엘리먼트 노드
  6654. * @since 1.2.0
  6655. *
  6656. * @see $Element#parent
  6657. * @see $Element#child
  6658. * @see $Element#prev
  6659. * @see $Element#next
  6660. * @see $Element#last
  6661. * @see $Element#indexOf
  6662. *
  6663. * @example
  6664. <div id="sample_div1">
  6665. <div id="sample_div2">
  6666. <div id="sample_div">
  6667. Sample1
  6668. <div id="sample_div3">
  6669. <div id="sample_div4">
  6670. Sample2
  6671. </div>
  6672. Sample3
  6673. </div>
  6674. <div id="sample_div5">
  6675. Sample4
  6676. <div id="sample_div6">
  6677. Sample5
  6678. </div>
  6679. </div>
  6680. </div>
  6681. </div>
  6682. </div>
  6683. <script type="text/javascript">
  6684. var firstChild = $Element("sample_div").first();
  6685. // id가 sample_div3인 DIV를 래핑한 $Element를 반환
  6686. </script>
  6687. */
  6688. jindo.$Element.prototype.first = function() {
  6689. var el = this._element.firstElementChild||this._element.firstChild;
  6690. if (!el) return null;
  6691. while(el && el.nodeType != 1) el = el.nextSibling;
  6692. return el?jindo.$Element(el):null;
  6693. }
  6694. /**
  6695. * HTML 엘리먼트의 마지막 자식 엘리먼트 노드를 반환한다.
  6696. *
  6697. * @return {$Element} 마지막 자식 엘리먼트 노드
  6698. * @since 1.2.0
  6699. *
  6700. * @see $Element#parent
  6701. * @see $Element#child
  6702. * @see $Element#prev
  6703. * @see $Element#next
  6704. * @see $Element#first
  6705. * @see $Element#indexOf
  6706. *
  6707. * @example
  6708. <div id="sample_div1">
  6709. <div id="sample_div2">
  6710. <div id="sample_div">
  6711. Sample1
  6712. <div id="sample_div3">
  6713. <div id="sample_div4">
  6714. Sample2
  6715. </div>
  6716. Sample3
  6717. </div>
  6718. <div id="sample_div5">
  6719. Sample4
  6720. <div id="sample_div6">
  6721. Sample5
  6722. </div>
  6723. </div>
  6724. </div>
  6725. </div>
  6726. </div>
  6727. <script type="text/javascript">
  6728. var lastChild = $Element("sample_div").last();
  6729. // id가 sample_div5인 DIV를 래핑한 $Element를 반환
  6730. </script>
  6731. */
  6732. jindo.$Element.prototype.last = function() {
  6733. var el = this._element.lastElementChild||this._element.lastChild;
  6734. if (!el) return null;
  6735. while(el && el.nodeType != 1) el = el.previousSibling;
  6736. return el?jindo.$Element(el):null;
  6737. }
  6738. /**
  6739. * HTML 엘리먼트의 부모 엘리먼트 노드를 확인한다.
  6740. *
  6741. * @param {HTML Element | String | $Element} element 부모 노드인지 확인할 HTML 엘리먼트.<br>
  6742. * <br>
  6743. * 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6744. * <br>
  6745. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 확인한다.<br>
  6746. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 확인한다.<br>
  6747. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 확인한다.
  6748. * @return {Boolean} 매개 변수가 부모 엘리먼트 노드이면 true 를, 그렇지 않으면 false 를 반환한다.
  6749. *
  6750. * @see $Element#isParentOf
  6751. *
  6752. * @example
  6753. <div id="parent">
  6754. <div id="child">
  6755. <div id="grandchild"></div>
  6756. </div>
  6757. </div>
  6758. <div id="others"></div>
  6759. ...
  6760. // 부모/자식 확인하기
  6761. $Element("child").isChildOf("parent"); // 결과 : true
  6762. $Element("others").isChildOf("parent"); // 결과 : false
  6763. $Element("grandchild").isChildOf("parent"); // 결과 : true
  6764. */
  6765. jindo.$Element.prototype.isChildOf = function(element) {
  6766. return jindo.$Element._contain(jindo.$Element(element).$value(),this._element);
  6767. };
  6768. /**
  6769. * HTML 엘리먼트의 자식 엘리먼트 노드를 확인한다.
  6770. *
  6771. * @param {HTML Element | String | $Element} element 자식 노드인지 확인할 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다가매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 확인한다.<br>
  6772. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 확인한다.<br>
  6773. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 확인한다.
  6774. * @return {Boolean} 매개 변수가 자식 엘리먼트 노드이면 true 를, 그렇지 않으면 false 를 반환한다.
  6775. *
  6776. * @see $Element#isChildOf
  6777. *
  6778. * @example
  6779. <div id="parent">
  6780. <div id="child"></div>
  6781. </div>
  6782. <div id="others"></div>
  6783. ...
  6784. // 부모/자식 확인하기
  6785. $Element("parent").isParentOf("child"); // 결과 : true
  6786. $Element("others").isParentOf("child"); // 결과 : false
  6787. $Element("parent").isParentOf("grandchild");// 결과 : true
  6788. */
  6789. jindo.$Element.prototype.isParentOf = function(element) {
  6790. return jindo.$Element._contain(this._element, jindo.$Element(element).$value());
  6791. };
  6792. /**
  6793. * isChildOf , isParentOf의 기본이 되는 API(IE에서는 contains,기타 브라우져에는 compareDocumentPosition을 사용하고 둘다 없는 경우는 기존 레거시 API사용.)
  6794. * @param {HTMLElement} eParent 부모노드
  6795. * @param {HTMLElement} eChild 자식노드
  6796. * @ignore
  6797. */
  6798. jindo.$Element._contain = function(eParent,eChild){
  6799. if (document.compareDocumentPosition) {
  6800. jindo.$Element._contain = function(eParent,eChild){
  6801. return !!(eParent.compareDocumentPosition(eChild)&16);
  6802. }
  6803. }else if(document.body.contains){
  6804. jindo.$Element._contain = function(eParent,eChild){
  6805. return (eParent !== eChild)&&(eParent.contains ? eParent.contains(eChild) : true);
  6806. }
  6807. }else{
  6808. jindo.$Element._contain = function(eParent,eChild){
  6809. var e = eParent;
  6810. var el = eChild;
  6811. while(e && e.parentNode) {
  6812. e = e.parentNode;
  6813. if (e == el) return true;
  6814. }
  6815. return false;
  6816. }
  6817. }
  6818. return jindo.$Element._contain(eParent,eChild);
  6819. }
  6820. /**
  6821. * 현재의 HTML 엘리먼트와 동일한 엘리먼트인지 확인한다.
  6822. *
  6823. * @remark DOM3의 API중 isSameNode와 같은 함수로 레퍼런스까지 확인 함수이다.
  6824. * @remark isEqualNode와는 다른 함수이기 때문에 헷갈리지 않도록 한다.
  6825. *
  6826. * @param {HTML Element | String | $Element} element 같은 HTML 엘리먼트인지 확인할 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6827. * <br>
  6828. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 확인한다.<br>
  6829. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 확인한다.<br>
  6830. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 확인한다.
  6831. * @return {Boolean} 매개 변수가 같은 HTML 엘리먼트이면 true 를, 그렇지 않으면 false 를 반환한다.
  6832. *
  6833. * @example
  6834. <div id="sample1"><span>Sample</span></div>
  6835. <div id="sample2"><span>Sample</span></div>
  6836. ...
  6837. // 같은 HTML 엘리먼트인지 확인
  6838. var welSpan1 = $Element("sample1").first(); // <span>Sample</span>
  6839. var welSpan2 = $Element("sample2").first(); // <span>Sample</span>
  6840. welSpan1.isEqual(welSpan2); // 결과 : false
  6841. welSpan1.isEqual(welSpan1); // 결과 : true
  6842. */
  6843. jindo.$Element.prototype.isEqual = function(element) {
  6844. try {
  6845. return (this._element === jindo.$Element(element).$value());
  6846. } catch(e) {
  6847. return false;
  6848. }
  6849. };
  6850. /**
  6851. * HTML 엘리먼트에 이벤트를 발생시킨다.
  6852. *
  6853. * @param {String} sEvent 실행할 이벤트 이름. on 접두사는 생략한다.
  6854. * @param {Object} [oProps] 이벤트 실행 시 사용할 이벤트 객체의 속성을 지정한다.
  6855. * @return {$Element} 이벤트가 발생한 HTML 엘리먼트
  6856. *
  6857. * @since WebKit 계열에서는 이벤트 객체의 keyCode 가 read-only 인 관계로 key 이벤트를 발생시킬 경우 keyCode 값이 설정되지 않는다. 1.4.1 부터 keyCode 값을 설정할 수 있다.
  6858. *
  6859. * @example
  6860. $Element("div").fireEvent("click", {left : true, middle : false, right : false}); // click 이벤트 발생
  6861. $Element("div").fireEvent("mouseover", {screenX : 50, screenY : 50, clientX : 50, clientY : 50}); // mouseover 이벤트 발생
  6862. $Element("div").fireEvent("keydown", {keyCode : 13, alt : true, shift : false ,meta : false, ctrl : true}); // keydown 이벤트 발생
  6863. */
  6864. jindo.$Element.prototype.fireEvent = function(sEvent, oProps) {
  6865. function IE(sEvent, oProps) {
  6866. sEvent = (sEvent+"").toLowerCase();
  6867. var oEvent = document.createEventObject();
  6868. if(oProps){
  6869. for (k in oProps){
  6870. if(oProps.hasOwnProperty(k))
  6871. oEvent[k] = oProps[k];
  6872. }
  6873. oEvent.button = (oProps.left?1:0)+(oProps.middle?4:0)+(oProps.right?2:0);
  6874. oEvent.relatedTarget = oProps.relatedElement||null;
  6875. }
  6876. this._element.fireEvent("on"+sEvent, oEvent);
  6877. return this;
  6878. };
  6879. function DOM2(sEvent, oProps) {
  6880. var sType = "HTMLEvents";
  6881. sEvent = (sEvent+"").toLowerCase();
  6882. if (sEvent == "click" || sEvent.indexOf("mouse") == 0) {
  6883. sType = "MouseEvent";
  6884. if (sEvent == "mousewheel") sEvent = "dommousescroll";
  6885. } else if (sEvent.indexOf("key") == 0) {
  6886. sType = "KeyboardEvent";
  6887. }
  6888. var evt;
  6889. if (oProps) {
  6890. oProps.button = 0 + (oProps.middle?1:0) + (oProps.right?2:0);
  6891. oProps.ctrl = oProps.ctrl||false;
  6892. oProps.alt = oProps.alt||false;
  6893. oProps.shift = oProps.shift||false;
  6894. oProps.meta = oProps.meta||false;
  6895. switch (sType) {
  6896. case 'MouseEvent':
  6897. evt = document.createEvent(sType);
  6898. evt.initMouseEvent( sEvent, true, true, null, oProps.detail||0, oProps.screenX||0, oProps.screenY||0, oProps.clientX||0, oProps.clientY||0,
  6899. oProps.ctrl, oProps.alt, oProps.shift, oProps.meta, oProps.button, oProps.relatedElement||null);
  6900. break;
  6901. case 'KeyboardEvent':
  6902. if (window.KeyEvent) {
  6903. evt = document.createEvent('KeyEvents');
  6904. evt.initKeyEvent(sEvent, true, true, window, oProps.ctrl, oProps.alt, oProps.shift, oProps.meta, oProps.keyCode, oProps.keyCode);
  6905. } else {
  6906. try {
  6907. evt = document.createEvent("Events");
  6908. } catch (e){
  6909. evt = document.createEvent("UIEvents");
  6910. } finally {
  6911. evt.initEvent(sEvent, true, true);
  6912. evt.ctrlKey = oProps.ctrl;
  6913. evt.altKey = oProps.alt;
  6914. evt.shiftKey = oProps.shift;
  6915. evt.metaKey = oProps.meta;
  6916. evt.keyCode = oProps.keyCode;
  6917. evt.which = oProps.keyCode;
  6918. }
  6919. }
  6920. break;
  6921. default:
  6922. evt = document.createEvent(sType);
  6923. evt.initEvent(sEvent, true, true);
  6924. }
  6925. }else{
  6926. evt = document.createEvent(sType);
  6927. evt.initEvent(sEvent, true, true);
  6928. }
  6929. this._element.dispatchEvent(evt);
  6930. return this;
  6931. };
  6932. jindo.$Element.prototype.fireEvent = (typeof this._element.dispatchEvent != "undefined")?DOM2:IE;
  6933. return this.fireEvent(sEvent, oProps);
  6934. };
  6935. /**
  6936. * HTML 엘리먼트의 자식 노드를 모두 제거한다.
  6937. *
  6938. * @return {$Element} 자식 노드를 모두 제거한 현재의 $Element 객체
  6939. *
  6940. * @see $Element#leave
  6941. * @see $Element#remove
  6942. *
  6943. * @example
  6944. // 자식 노드를 모두 제거
  6945. $Element("sample").empty();
  6946. //Before
  6947. <div id="sample"><span>노드</span> <span>모두</span> 삭제하기 </div>
  6948. //After
  6949. <div id="sample"></div>
  6950. */
  6951. jindo.$Element.prototype.empty = function() {
  6952. jindo.$$.release();
  6953. this.html("");
  6954. return this;
  6955. };
  6956. /**
  6957. * HTML 엘리먼트의 특정 자식 노드를 제거한다. 제거되는 자식 엘리먼트 노드의 이벤트 핸들러도 제거한다.
  6958. *
  6959. * @param {HTML Element | String | $Element} oChild 제거할 자식 엘리먼트 노드.<br>
  6960. * <br>
  6961. * 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  6962. * <br>
  6963. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 제거한다.<br>
  6964. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 제거한다.<br>
  6965. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 제거한다.
  6966. * @return {$Element} 자식 노드를 모두 제거한 현재의 $Element 객체
  6967. *
  6968. * @see $Element#empty
  6969. * @see $Element#leave
  6970. *
  6971. * @example
  6972. // 특정 자식 노드를 제거
  6973. $Element("sample").remove("child2");
  6974. //Before
  6975. <div id="sample"><span id="child1">노드</span> <span id="child2">삭제하기</span></div>
  6976. //After
  6977. <div id="sample"><span id="child1">노드</span> </div>
  6978. */
  6979. jindo.$Element.prototype.remove = function(oChild) {
  6980. jindo.$$.release();
  6981. jindo.$Element(oChild).leave();
  6982. return this;
  6983. }
  6984. /**
  6985. * HTML 엘리먼트를 부모 엘리먼트 노드에서 제거한다.<br>
  6986. * HTML 엘러먼트에 등록된 이벤트 핸들러도 제거한다.
  6987. *
  6988. * @return {$Element} 부모 엘리먼트 노드에서 제거 된 현재의 $Element 객체
  6989. *
  6990. * @see $Element#empty
  6991. * @see $Element#remove
  6992. *
  6993. * @example
  6994. // 부모 엘리먼트 노드에서 제거
  6995. $Element("sample").leave();
  6996. //Before
  6997. <div>
  6998. <div id="sample"><span>노드</span> <span>모두</span> 삭제하기 </div>
  6999. </div>
  7000. //After
  7001. // <div id="sample"><span>노드</span> <span>모두</span> 삭제하기 </div>를 래핑한 $Element가 반환된다
  7002. <div>
  7003. </div>
  7004. */
  7005. jindo.$Element.prototype.leave = function() {
  7006. var e = this._element;
  7007. if (e.parentNode) {
  7008. jindo.$$.release();
  7009. e.parentNode.removeChild(e);
  7010. }
  7011. jindo.$Fn.freeElement(this._element);
  7012. return this;
  7013. };
  7014. /**
  7015. * HTML 엘리먼트를 다른 HTML 엘리먼트로 감싼다.
  7016. *
  7017. * @param {String | HTML Element | $Element} wrapper 감쌀 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  7018. * <br>
  7019. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 사용한다.<br>
  7020. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 사용한다.<br>
  7021. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 사용한다.
  7022. * @return {$Element} 새로운 HTML 엘리먼트로 감싼 $Element 개체
  7023. *
  7024. * @example
  7025. $Element("sample1").wrap("sample2");
  7026. //Before
  7027. <div id="sample1"><span>Sample</span></div>
  7028. <div id="sample2"><span>Sample</span></div>
  7029. //After
  7030. <div id="sample2"><span>Sample</span><div id="sample1"><span>Sample</span></div></div>
  7031. * @example
  7032. $Element("box").wrap($('<DIV>'));
  7033. //Before
  7034. <span id="box"></span>
  7035. //After
  7036. <div><span id="box"></span></div>
  7037. */
  7038. jindo.$Element.prototype.wrap = function(wrapper) {
  7039. var e = this._element;
  7040. wrapper = jindo.$Element(wrapper).$value();
  7041. if (e.parentNode) {
  7042. e.parentNode.insertBefore(wrapper, e);
  7043. }
  7044. wrapper.appendChild(e);
  7045. return this;
  7046. };
  7047. /**
  7048. * HTML 엘리먼트의 텍스트 노드가 브라우저에서 한 줄로 보이도록 길이를 조절한다.
  7049. *
  7050. * @remark 이 메서드는 HTML 엘리먼트가 텍스트 노드만을 포함한다고 가정한다. 따라서, 이 외의 상황에서의 동작은 보장하지 않는다.
  7051. * @remark 브라우저에서의 HTML 엘리먼트의 너비를 기준으로 텍스트 노드의 길이를 정하므로 HTML 엘리먼트는 반드시 보이는 상태여야 한다.
  7052. * @remark 화면에 전체 텍스트 노드가 보였다가 줄어드는 경우가 있다. 이런 경우, HTML 엘리먼트에서 overflow:hidden 속성을 활용한다.
  7053. *
  7054. * @param {String} [stringTail] 말줄임 표시자. <br>
  7055. * 매개 변수에 지정한 문자열을 텍스트 노드 맨 끝에 붙이고 텍스트 노드의 길이를 조절한다.<br>
  7056. * 매개 변수를 생락하면 말줄임표('...')를 사용한다.
  7057. *
  7058. * @example
  7059. $Element("sample_span").ellipsis();
  7060. //Before
  7061. <div style="width:300px; border:1px solid #CCCCCC; padding:10px">
  7062. <span id="sample_span">NHN은 검색과 게임을 양축으로 혁신적이고 편리한 온라인 서비스를 꾸준히 선보이며 디지털 라이프를 선도하고 있습니다.</span>
  7063. </div>
  7064. //After
  7065. <div style="width:300px; border:1px solid #CCCCCC; padding:10px">
  7066. <span id="sample_span">NHN은 검색과 게임을 양축으로 혁신적...</span>
  7067. </div>
  7068. */
  7069. jindo.$Element.prototype.ellipsis = function(stringTail) {
  7070. stringTail = stringTail || "...";
  7071. var txt = this.text();
  7072. var len = txt.length;
  7073. var padding = parseInt(this.css("paddingTop"),10) + parseInt(this.css("paddingBottom"),10);
  7074. var cur_h = this.height() - padding;
  7075. var i = 0;
  7076. var h = this.text('A').height() - padding;
  7077. if (cur_h < h * 1.5) return this.text(txt);
  7078. cur_h = h;
  7079. while(cur_h < h * 1.5) {
  7080. i += Math.max(Math.ceil((len - i)/2), 1);
  7081. cur_h = this.text(txt.substring(0,i)+stringTail).height() - padding;
  7082. }
  7083. while(cur_h > h * 1.5) {
  7084. i--;
  7085. cur_h = this.text(txt.substring(0,i)+stringTail).height() - padding;
  7086. }
  7087. };
  7088. /**
  7089. * HTML 엘리먼트에서 매개 변수가 몇 번째 자식 엘리먼트 노드인지 확인하여 인덱스를 반환한다.
  7090. *
  7091. * @param {String | HTML Element | $Element} element 확인할 HTML 엘리먼트. 문자열, HTML 엘리먼트, 혹은 $Element 을 매개 변수로 지정할 수 있다.<br>
  7092. * <br>
  7093. * 매개 변수가 문자열이면 해당 문자열을 id 로 하는 HTML 엘리먼트를 사용한다.<br>
  7094. * 매개 변수가 HTML 엘리먼트이면 해당 엘리먼트를 사용한다.<br>
  7095. * 매개 변수가 $Element 이면 $Element 객체 내부의 HTML 엘리먼트를 사용한다.
  7096. * @return {Number} 검색 결과 인덱스.<br>
  7097. * 인덱스는 0 부터 시작하며, 찾지 못한 경우에는 -1 을 반환한다.
  7098. *
  7099. * @since 1.2.0
  7100. *
  7101. * @see $Element#parent
  7102. * @see $Element#child
  7103. * @see $Element#prev
  7104. * @see $Element#next
  7105. * @see $Element#first
  7106. * @see $Element#last
  7107. *
  7108. * @example
  7109. <div id="sample_div1">
  7110. <div id="sample_div">
  7111. <div id="sample_div2">
  7112. Sample1
  7113. </div>
  7114. <div id="sample_div3">
  7115. <div id="sample_div4">
  7116. Sample2
  7117. </div>
  7118. Sample3
  7119. </div>
  7120. <div id="sample_div5">
  7121. Sample4
  7122. <div id="sample_div6">
  7123. Sample5
  7124. </div>
  7125. </div>
  7126. </div>
  7127. </div>
  7128. <script type="text/javascript">
  7129. var welSample = $Element("sample_div");
  7130. welSample.indexOf($Element("sample_div1")); // 결과 : -1
  7131. welSample.indexOf($Element("sample_div2")); // 결과 : 0
  7132. welSample.indexOf($Element("sample_div3")); // 결과 : 1
  7133. welSample.indexOf($Element("sample_div4")); // 결과 : -1
  7134. welSample.indexOf($Element("sample_div5")); // 결과 : 2
  7135. welSample.indexOf($Element("sample_div6")); // 결과 : -1
  7136. </script>
  7137. */
  7138. jindo.$Element.prototype.indexOf = function(element) {
  7139. try {
  7140. var e = jindo.$Element(element).$value();
  7141. var n = this._element.childNodes;
  7142. var c = 0;
  7143. var l = n.length;
  7144. for (var i=0; i < l; i++) {
  7145. if (n[i].nodeType != 1) continue;
  7146. if (n[i] === e) return c;
  7147. c++;
  7148. }
  7149. }catch(e){}
  7150. return -1;
  7151. };
  7152. /**
  7153. * HTML 엘리먼트에서 특정 CSS 셀렉터(selector)를 만족하는 하위 엘리먼트 노드를 찾는다.
  7154. *
  7155. * @param {String} sSelector CSS 셀렉터
  7156. * @return {Array} CSS 셀렉터 조건을 만족하는 HTML 엘리먼트의 배열을 반환한다.<br>
  7157. * 만족하는 HTML 엘리먼트가 존재하지 않으면 빈 배열을 반환한다.
  7158. *
  7159. * @see $Element#query
  7160. * @see $Element#queryAll
  7161. *
  7162. * @example
  7163. <div id="sample">
  7164. <div></div>
  7165. <div class="pink"></div>
  7166. <div></div>
  7167. <div class="pink"></div>
  7168. <div></div>
  7169. <div class="blue"></div>
  7170. <div class="blue"></div>
  7171. </div>
  7172. <script type="text/javascript">
  7173. $Element("sample").queryAll(".pink");
  7174. // <div class="pink"></div>와 <div class="pink"></div>를 원소로 하는 배열을 반환
  7175. $Element("sample").queryAll(".green");
  7176. // [] 빈 배열을 반환
  7177. </script>
  7178. */
  7179. jindo.$Element.prototype.queryAll = function(sSelector) {
  7180. return jindo.$$(sSelector, this._element);
  7181. };
  7182. /**
  7183. * HTML 엘리먼트에서 특정 CSS 셀렉터(selector)를 만족하는 첫 번째 하위 엘리먼트 노드를 반환한다.
  7184. *
  7185. * @param {String} sSelector CSS 셀렉터
  7186. * @return {HTML Element} CSS 셀렉터 조건을 만족하는 첫 번째 HTML 엘리먼트.<br>
  7187. * 만족하는 HTML 엘리먼트가 존재하지 않으면 null 을 반환한다.
  7188. *
  7189. * @see $Element#test
  7190. * @see $Element#queryAll
  7191. *
  7192. * @example
  7193. <div id="sample">
  7194. <div></div>
  7195. <div class="pink"></div>
  7196. <div></div>
  7197. <div class="pink"></div>
  7198. <div></div>
  7199. <div class="blue"></div>
  7200. <div class="blue"></div>
  7201. </div>
  7202. <script type="text/javascript">
  7203. $Element("sample").query(".pink");
  7204. // 첫 번째 <div class="pink"></div> DIV 엘리먼트를 반환
  7205. $Element("sample").query(".green");
  7206. // null 을 반환
  7207. </script>
  7208. */
  7209. jindo.$Element.prototype.query = function(sSelector) {
  7210. return jindo.$$.getSingle(sSelector, this._element);
  7211. };
  7212. /**
  7213. * HTML 엘리먼트에서 특정 CSS 셀렉터(selector)를 만족하는지 확인한다.
  7214. *
  7215. * @param {String} sSelector CSS 셀렉터
  7216. * @return {Boolean} CSS 셀렉터 조건을 만족하는지 확인하여 true/false 로 반환한다.
  7217. *
  7218. * @see $Element#query
  7219. * @see $Element#queryAll
  7220. *
  7221. * @example
  7222. <div id="sample" class="blue"></div>
  7223. <script type="text/javascript">
  7224. $Element("sample").test(".blue"); // 결과 : true
  7225. $Element("sample").test(".red"); // 결과 : false
  7226. </script>
  7227. */
  7228. jindo.$Element.prototype.test = function(sSelector) {
  7229. return jindo.$$.test(this._element, sSelector);
  7230. };
  7231. /**
  7232. * HTML 엘리먼트를 기준으로 XPath 문법을 사용하여 해당하는 HTML 엘리먼트를 가져온다.
  7233. *
  7234. * @remark 지원하는 문법이 무척 제한적으로 특수한 경우에서만 사용하는 것을 권장한다.
  7235. *
  7236. * @param {String} sXPath XPath 문법
  7237. * @return {Array} XPath 에 해당하는 HTML 엘리먼트를 원소로 하는 배열을 반환한다.
  7238. *
  7239. * @example
  7240. <div id="sample">
  7241. <div>
  7242. <div>1</div>
  7243. <div>2</div>
  7244. <div>3</div>
  7245. <div>4</div>
  7246. <div>5</div>
  7247. <div>6</div>
  7248. </div>
  7249. </div>
  7250. <script type="text/javascript">
  7251. $Element("sample").xpathAll("div/div[5]");
  7252. // <div>5</div> 엘리먼트를 원소로 하는 배열이 반환 됨
  7253. </script>
  7254. */
  7255. jindo.$Element.prototype.xpathAll = function(sXPath) {
  7256. return jindo.$$.xpath(sXPath, this._element);
  7257. };
  7258. /**
  7259. * insertAdjacentHTML 함수. 직접사용하지 못함.
  7260. * @ignore
  7261. */
  7262. jindo.$Element.insertAdjacentHTML = function(ins,html,insertType,type,fn){
  7263. var _ele = ins._element;
  7264. if( _ele.insertAdjacentHTML && !(/^<(option|tr|td|th|col)(?:.*?)>/.test(html.replace(/^(\s| )+|(\s| )+$/g, "").toLowerCase()))){
  7265. _ele.insertAdjacentHTML(insertType, html);
  7266. }else{
  7267. var oDoc = _ele.ownerDocument || _ele.document || document;
  7268. var fragment = oDoc.createDocumentFragment();
  7269. var defaultElement;
  7270. var sTag = html.replace(/^(\s| )+|(\s| )+$/g, "");
  7271. var oParentTag = {
  7272. "option" : "select",
  7273. "tr" : "tbody",
  7274. "thead" : "table",
  7275. "tbody" : "table",
  7276. "col" : "table",
  7277. "td" : "tr",
  7278. "th" : "tr",
  7279. "div" : "div"
  7280. }
  7281. var aMatch = /^\<(option|tr|thead|tbody|td|th|col)(?:.*?)\>/i.exec(sTag);
  7282. var sChild = aMatch === null ? "div" : aMatch[1].toLowerCase();
  7283. var sParent = oParentTag[sChild] ;
  7284. defaultElement = jindo._createEle(sParent,sTag,oDoc,true);
  7285. var scripts = defaultElement.getElementsByTagName("script");
  7286. for ( var i = 0, l = scripts.length; i < l; i++ ){
  7287. scripts[i].parentNode.removeChild( scripts[i] );
  7288. }
  7289. while ( defaultElement[ type ]){
  7290. fragment.appendChild( defaultElement[ type ] );
  7291. }
  7292. fn(fragment.cloneNode(true));
  7293. }
  7294. return ins;
  7295. }
  7296. /**
  7297. * HTML 엘리먼트 내부 HTML 의 가장 뒤에 HTML 을 덧붙인다.
  7298. *
  7299. * @param {String} sHTML 덧붙일 HTML 문자열
  7300. * @return {$Element} 1.4.8부터 내부 HTML 을 변경한 현재의 $Element 객체를 반환한다.
  7301. * @since 1.4.6 부터 사용 가능.
  7302. * @since 1.4.8 부터 $Element 객체를 반환한다.
  7303. * @see $Element#prependHTML
  7304. * @see $Element#beforeHTML
  7305. * @see $Element#afterHTML
  7306. *
  7307. * @example
  7308. // 내부 HTML 가장 뒤에 덧붙이기
  7309. $Element("sample_ul").appendHTML("<li>3</li><li>4</li>");
  7310. //Before
  7311. <ul id="sample_ul">
  7312. <li>1</li>
  7313. <li>2</li>
  7314. </ul>
  7315. //After
  7316. <ul id="sample_ul">
  7317. <li>1</li>
  7318. <li>2</li>
  7319. <li>3</li>
  7320. <li>4</li>
  7321. </ul>
  7322. */
  7323. jindo.$Element.prototype.appendHTML = function(sHTML) {
  7324. return jindo.$Element.insertAdjacentHTML(this,sHTML,"beforeEnd","firstChild",jindo.$Fn(function(oEle){
  7325. this.append(oEle);
  7326. },this).bind());
  7327. };
  7328. /**
  7329. * HTML 엘리먼트 내부 HTML 의 가장 앞에 HTML 을 삽입한다.
  7330. *
  7331. * @param {String} sHTML 삽입할 HTML 문자열
  7332. * @return {$Element} 1.4.8부터 내부 HTML 을 변경한 현재의 $Element 객체를 반환한다.
  7333. * @since 1.4.6부터 사용 가능.
  7334. * @see $Element#appendHTML
  7335. * @see $Element#beforeHTML
  7336. * @see $Element#afterHTML
  7337. *
  7338. * @example
  7339. // 내부 HTML 가장 앞에 삽입
  7340. $Element("sample_ul").prependHTML("<li>3</li><li>4</li>");
  7341. //Before
  7342. <ul id="sample_ul">
  7343. <li>1</li>
  7344. <li>2</li>
  7345. </ul>
  7346. //After
  7347. <ul id="sample_ul">
  7348. <li>4</li>
  7349. <li>3</li>
  7350. <li>1</li>
  7351. <li>2</li>
  7352. </ul>
  7353. */
  7354. jindo.$Element.prototype.prependHTML = function(sHTML) {
  7355. return jindo.$Element.insertAdjacentHTML(this,sHTML,"afterBegin","lastChild",jindo.$Fn(function(oEle){
  7356. this.prepend(oEle);
  7357. },this).bind());
  7358. };
  7359. /**
  7360. * HTML 엘리먼트 앞에 HTML 을 삽입한다.
  7361. *
  7362. * @param {String} sHTML 삽입할 HTML 문자열
  7363. * @return {$Element} 1.4.8부터 현재의 $Element 객체를 반환한다.
  7364. * @since 1.4.6부터 사용 가능.
  7365. * @see $Element#appendHTML
  7366. * @see $Element#prependHTML
  7367. * @see $Element#afterHTML
  7368. *
  7369. * @example
  7370. var welSample = $Element("sample_ul");
  7371. welSample.beforeHTML("<ul><li>3</li><li>4</li></ul>");
  7372. welSample.beforeHTML("<ul><li>5</li><li>6</li></ul>");
  7373. //Before
  7374. <ul id="sample_ul">
  7375. <li>1</li>
  7376. <li>2</li>
  7377. </ul>
  7378. //After
  7379. <ul>
  7380. <li>3</li>
  7381. <li>4</li>
  7382. </ul>
  7383. <ul>
  7384. <li>5</li>
  7385. <li>6</li>
  7386. </ul>
  7387. <ul id="sample_ul">
  7388. <li>1</li>
  7389. <li>2</li>
  7390. </ul>
  7391. */
  7392. jindo.$Element.prototype.beforeHTML = function(sHTML) {
  7393. return jindo.$Element.insertAdjacentHTML(this,sHTML,"beforeBegin","firstChild",jindo.$Fn(function(oEle){
  7394. this.before(oEle);
  7395. },this).bind());
  7396. };
  7397. /**
  7398. * HTML 엘리먼트 뒤에 HTML 을 덧붙인다.
  7399. * @param {String} sHTML 덧붙일 HTML 문자열
  7400. * @returns {$Element} 1.4.8부터 현재의 $Element 객체를 반환한다.
  7401. * @since 1.4.6부터 사용 가능.
  7402. * @see $Element#appendHTML
  7403. * @see $Element#prependHTML
  7404. * @see $Element#beforeHTML
  7405. * @example
  7406. var welSample = $Element("sample_ul");
  7407. welSample.beforeHTML("<ul><li>3</li><li>4</li></ul>");
  7408. welSample.beforeHTML("<ul><li>5</li><li>6</li></ul>");
  7409. //Before
  7410. <ul id="sample_ul">
  7411. <li>1</li>
  7412. <li>2</li>
  7413. </ul>
  7414. //After
  7415. <ul id="sample_ul">
  7416. <li>1</li>
  7417. <li>2</li>
  7418. </ul>
  7419. <ul>
  7420. <li>5</li>
  7421. <li>6</li>
  7422. </ul>
  7423. <ul>
  7424. <li>3</li>
  7425. <li>4</li>
  7426. </ul>
  7427. */
  7428. jindo.$Element.prototype.afterHTML = function(sHTML) {
  7429. return jindo.$Element.insertAdjacentHTML(this,sHTML,"afterEnd","lastChild",jindo.$Fn(function(oEle){
  7430. this._element.parentNode.insertBefore( oEle, this._element.nextSibling );
  7431. },this).bind());
  7432. };
  7433. /**
  7434. * 이벤트 델리게이션으로 이벤트를 처리한다.<br>
  7435. * 이벤트 델리게이션이란 이벤트 버블링을 이용하여 효율적으로 이벤트를 관리하는 방법이다.<br>
  7436. * 자세한 내용은 아래의 URL을 참고한다.<br>
  7437. * <br>
  7438. *
  7439. * <ul>
  7440. * <li><a href="http://devcode.nhncorp.com/projects/jindo/wiki/EventDelegate" target="_blank">Event Delegate 란?</a></li>
  7441. * <ul>
  7442. *
  7443. * @param {String} sEvent 이벤트 이름. on 접두사는 생략한다.<br>
  7444. * domready, mousewheel, mouseenter, mouseleave 은 지원하지 않는다.<br>
  7445. *
  7446. * @param {String | Function} vFilter 원하는 HTML 엘리먼트에 대해서만 이벤트를 실행하도록 하기 위한 필터이다.<br>
  7447. * <br>
  7448. * 필터에는 CSS 셀렉터와 함수의 두 가지 타입이 있다.<br>
  7449. * <br>
  7450. * 필터를 CSS 셀렉터를 사용하려면 문자열을 매개 변수로 지정한다.<br>
  7451. * <br>
  7452. * 필터를 함수로 사용하려면 Boolean 을 반환하는 함수를 매개 변수로 지정한다.<br>
  7453. * 필터 함수의 첫 번째 매개 변수는 HTML 엘리먼트 자신이고, 두 번째 매개 변수는 이벤트가 발생한 HTML 엘리먼트이다.
  7454. *
  7455. * @param {Function} fpCallback 필터에서 true 가 반환된 경우 실행되는 콜백 함수이다.<br>
  7456. * 매개 변수로 이벤트 객체가 지정된다.
  7457. *
  7458. * @return {$Element} $Element 객체를 리턴한다.
  7459. * @since 1.4.6부터 사용 가능.
  7460. * @see $Element#undelegate
  7461. *
  7462. * @example
  7463. <ul id="parent">
  7464. <li class="odd">1</li>
  7465. <li>2</li>
  7466. <li class="odd">3</li>
  7467. <li>4</li>
  7468. </ul>
  7469. // CSS 셀렉터를 필터로 사용하는 경우
  7470. $Element("parent").delegate("click",
  7471. ".odd", // 필터
  7472. function(eEvent){ // 콜백 함수
  7473. alert("odd 클래스를 가진 li가 클릭 될 때 실행");
  7474. });
  7475. * @example
  7476. <ul id="parent">
  7477. <li class="odd">1</li>
  7478. <li>2</li>
  7479. <li class="odd">3</li>
  7480. <li>4</li>
  7481. </ul>
  7482. // 함수를 필터로 사용하는 경우
  7483. $Element("parent").delegate("click",
  7484. function(oEle,oClickEle){ // 필터
  7485. return oClickEle.innerHTML == "2"
  7486. },
  7487. function(eEvent){ // 콜백 함수
  7488. alert("클릭한 엘리먼트의 innerHTML이 2인 경우에 실행");
  7489. });
  7490. */
  7491. jindo.$Element.prototype.delegate = function(sEvent , vFilter , fpCallback){
  7492. if(!this._element["_delegate_"+sEvent]){
  7493. this._element["_delegate_"+sEvent] = {};
  7494. var fAroundFunc = jindo.$Fn(function(sEvent,wEvent){
  7495. wEvent = wEvent || window.event;
  7496. if (typeof wEvent.currentTarget == "undefined") {
  7497. wEvent.currentTarget = this._element;
  7498. }
  7499. var oEle = wEvent.target || wEvent.srcElement;
  7500. var aData = this._element["_delegate_"+sEvent];
  7501. var data,func,event,resultFilter;
  7502. for(var i in aData){
  7503. data = aData[i];
  7504. resultFilter = data.checker(oEle);
  7505. if(resultFilter[0]){
  7506. func = data.func;
  7507. event = jindo.$Event(wEvent);
  7508. event.element = resultFilter[1];
  7509. for(var j = 0, l = func.length ; j < l ;j++){
  7510. func[j](event);
  7511. }
  7512. }
  7513. }
  7514. },this).bind(sEvent);
  7515. jindo.$Element._eventBind(this._element,sEvent,fAroundFunc);
  7516. var oEle = this._element;
  7517. oEle["_delegate_"+sEvent+"_func"] = fAroundFunc;
  7518. if (this._element["_delegate_events"]) {
  7519. this._element["_delegate_events"].push(sEvent);
  7520. }else{
  7521. this._element["_delegate_events"] = [sEvent];
  7522. }
  7523. oEle = null;
  7524. }
  7525. this._bind(sEvent,vFilter,fpCallback);
  7526. return this;
  7527. }
  7528. /**
  7529. * 이벤트를 바인딩 하는 함수.
  7530. * @param {Element} oEle 엘리먼트
  7531. * @param {Boolean} sEvent 이벤트 타입.
  7532. * @param {Function} fAroundFunc 바인딩할 함수
  7533. * @ignore.
  7534. */
  7535. jindo.$Element._eventBind = function(oEle,sEvent,fAroundFunc){
  7536. if(oEle.addEventListener){
  7537. jindo.$Element._eventBind = function(oEle,sEvent,fAroundFunc){
  7538. oEle.addEventListener(sEvent,fAroundFunc,false);
  7539. }
  7540. }else{
  7541. jindo.$Element._eventBind = function(oEle,sEvent,fAroundFunc){
  7542. oEle.attachEvent("on"+sEvent,fAroundFunc);
  7543. }
  7544. }
  7545. jindo.$Element._eventBind(oEle,sEvent,fAroundFunc);
  7546. }
  7547. /**
  7548. * HTML 엘리먼트에 등록된 이벤트 델리게이션을 해제한다.
  7549. *
  7550. * @param {String} sEvent 이벤드 델리게이션 등록 시 사용한 이벤트 이름. on 접두사는 생략한다.
  7551. * @param {String|Function} vFilter 이벤트 델리게이션 등록 시 사용한 필터.
  7552. * @param {Function} fpCallback 이벤트 델리게이션 등록 시 사용한 콜백 함수.
  7553. * @return {$Element} $Element 객체를 리턴한다.
  7554. * @since 1.4.6부터 사용 가능.
  7555. * @see $Element#delegate
  7556. *
  7557. * @example
  7558. <ul id="parent">
  7559. <li class="odd">1</li>
  7560. <li>2</li>
  7561. <li class="odd">3</li>
  7562. <li>4</li>
  7563. </ul>
  7564. // 콜백 함수
  7565. var fnOddClass = function(eEvent){
  7566. alert("odd 클래스를 가진 li가 클릭 될 때 실행");
  7567. };
  7568. $Element("parent").delegate("click", ".odd", fnOddClass); // 이벤트 델리게이션 사용
  7569. $Element("parent").undelegate("click", ".odd", fnOddClass); // 이벤트 해제
  7570. */
  7571. jindo.$Element.prototype.undelegate = function(sEvent, vFilter, fpCallback){
  7572. this._unbind(sEvent,vFilter,fpCallback);
  7573. return this;
  7574. }
  7575. /**
  7576. * 딜리게이션으로 실행되어야 할 함수를 추가 하는 함수.
  7577. * @param {String} sEvent 이벤트 타입.
  7578. * @param {String|Function} vFilter cssquery,function 이렇게 2가지 타입이 들어옴.
  7579. * @param {Function} fpCallback 해당 cChecker에 들어오는 함수가 맞을때 실행되는 함수.
  7580. * @returns {$Element} $Element 객체.
  7581. * @since 1.4.6부터 사용가능.
  7582. * @ignore
  7583. */
  7584. jindo.$Element.prototype._bind = function(sEvent,vFilter,fpCallback){
  7585. var _aDataOfEvent = this._element["_delegate_"+sEvent];
  7586. if(_aDataOfEvent){
  7587. var fpCheck;
  7588. if(typeof vFilter == "string"){
  7589. fpCheck = jindo.$Fn(function(sCssquery,oEle){
  7590. var eIncludeEle = oEle;
  7591. var isIncludeEle = jindo.$$.test(oEle, sCssquery);
  7592. if(!isIncludeEle){
  7593. var aPropagationElements = this._getParent(oEle);
  7594. for(var i = 0, leng = aPropagationElements.length ; i < leng ; i++){
  7595. eIncludeEle = aPropagationElements[i];
  7596. if(jindo.$$.test(eIncludeEle, sCssquery)){
  7597. isIncludeEle = true;
  7598. break;
  7599. }
  7600. }
  7601. }
  7602. return [isIncludeEle,eIncludeEle];
  7603. },this).bind(vFilter);
  7604. }else if(typeof vFilter == "function"){
  7605. fpCheck = jindo.$Fn(function(fpFilter,oEle){
  7606. var eIncludeEle = oEle;
  7607. var isIncludeEle = fpFilter(this._element,oEle);
  7608. if(!isIncludeEle){
  7609. var aPropagationElements = this._getParent(oEle);
  7610. for(var i = 0, leng = aPropagationElements.length ; i < leng ; i++){
  7611. eIncludeEle = aPropagationElements[i];
  7612. if(fpFilter(this._element,eIncludeEle)){
  7613. isIncludeEle = true;
  7614. break;
  7615. }
  7616. }
  7617. }
  7618. return [isIncludeEle,eIncludeEle];
  7619. },this).bind(vFilter);
  7620. }
  7621. this._element["_delegate_"+sEvent] = jindo.$Element._addBind(_aDataOfEvent,vFilter,fpCallback,fpCheck);
  7622. }else{
  7623. alert("check your delegate event.");
  7624. }
  7625. }
  7626. /**
  7627. * 파라메터로 들어오는 엘리먼트 부터 자신의 엘리먼트 까지의 엘리먼트를 구하는 함수.
  7628. * @param {Element} 엘리먼트.
  7629. * @returns {Array} 배열 객체.
  7630. * @ignore
  7631. */
  7632. jindo.$Element.prototype._getParent = function(oEle) {
  7633. var e = this._element;
  7634. var a = [], p = null;
  7635. while (oEle.parentNode && p != e) {
  7636. p = oEle.parentNode;
  7637. if (p == document.documentElement) break;
  7638. a[a.length] = p;
  7639. oEle = p;
  7640. }
  7641. return a;
  7642. };
  7643. /**
  7644. * 엘리먼트에 이벤트를 추가하는 함수.
  7645. * @param {Object} aDataOfEvent 이벤트와 함수를 가지고 있는 오브젝트.
  7646. * @param {String|Function} vFilter cssquery,check하는 함수.
  7647. * @param {Function} fpCallback 실행될 함수.
  7648. * @param {Function} fpCheck 체크하는 함수.
  7649. * @retruns {Object} aDataOfEvent를 반환.
  7650. * @ignore
  7651. */
  7652. jindo.$Element._addBind = function(aDataOfEvent,vFilter,fpCallback,fpCheck){
  7653. var aEvent = aDataOfEvent[vFilter];
  7654. if(aEvent){
  7655. var fpFuncs = aEvent.func;
  7656. fpFuncs.push(fpCallback);
  7657. aEvent.func = fpFuncs;
  7658. }else{
  7659. aEvent = {
  7660. checker : fpCheck,
  7661. func : [fpCallback]
  7662. };
  7663. }
  7664. aDataOfEvent[vFilter] = aEvent
  7665. return aDataOfEvent;
  7666. }
  7667. /**
  7668. * 딜리게이션에서 해제되어야 할 함수를 삭제하는 함수.
  7669. * @param {String} sEvent 이벤트 타입.
  7670. * @param {String|Function} vFilter cssquery,function 이렇게 2가지 타입이 들어옴.
  7671. * @param {Function} fpCallback 해당 cChecker에 들어오는 함수가 맞을때 실행되는 함수.
  7672. * @returns {$Element} $Element 객체.
  7673. * @since 1.4.6부터 사용가능.
  7674. * @ignore
  7675. */
  7676. jindo.$Element.prototype._unbind = function(sEvent, vFilter,fpCallback){
  7677. var oEle = this._element;
  7678. if (sEvent&&vFilter&&fpCallback) {
  7679. var oEventInfo = oEle["_delegate_"+sEvent];
  7680. if(oEventInfo&&oEventInfo[vFilter]){
  7681. var fpFuncs = oEventInfo[vFilter].func;
  7682. fpFuncs = oEventInfo[vFilter].func = jindo.$A(fpFuncs).refuse(fpCallback).$value();
  7683. if (!fpFuncs.length) {
  7684. jindo.$Element._deleteFilter(oEle,sEvent,vFilter);
  7685. }
  7686. }
  7687. }else if (sEvent&&vFilter) {
  7688. jindo.$Element._deleteFilter(oEle,sEvent,vFilter);
  7689. }else if (sEvent) {
  7690. jindo.$Element._deleteEvent(oEle,sEvent,vFilter);
  7691. }else{
  7692. var aEvents = oEle['_delegate_events'];
  7693. var sEachEvent;
  7694. for(var i = 0 , l = aEvents.length ; i < l ; i++){
  7695. sEachEvent = aEvents[i];
  7696. jindo.$Element._unEventBind(oEle,sEachEvent,oEle["_delegate_"+sEachEvent+"_func"]);
  7697. jindo.$Element._delDelegateInfo(oEle,"_delegate_"+sEachEvent);
  7698. jindo.$Element._delDelegateInfo(oEle,"_delegate_"+sEachEvent+"_func");
  7699. }
  7700. jindo.$Element._delDelegateInfo(oEle,"_delegate_events");
  7701. }
  7702. return this;
  7703. }
  7704. /**
  7705. * 오브젝트에 키값으로 정보삭제하는 함수
  7706. * @param {Object} 삭제할 오브젝트.
  7707. * @param {String|Function} sType 키값이 들어옴.
  7708. * @returns {Object} 삭제된 오브젝트.
  7709. * @since 1.4.6부터 사용가능.
  7710. * @ignore
  7711. */
  7712. jindo.$Element._delDelegateInfo = function(oObj , sType){
  7713. try{
  7714. oObj[sType] = null;
  7715. delete oObj[sType];
  7716. }catch(e){}
  7717. return oObj
  7718. }
  7719. /**
  7720. * 플터 기준으로 삭제하는 함수.
  7721. * @param {Element} 삭제할 엘리먼트.
  7722. * @param {String} 이벤트명.
  7723. * @param {String|Function} cssquery, 필터하는 함수.
  7724. * @since 1.4.6부터 사용가능.
  7725. * @ignore
  7726. */
  7727. jindo.$Element._deleteFilter = function(oEle,sEvent,vFilter){
  7728. var oEventInfo = oEle["_delegate_"+sEvent];
  7729. if(oEventInfo&&oEventInfo[vFilter]){
  7730. if (jindo.$H(oEventInfo).keys().length == 1) {
  7731. jindo.$Element._deleteEvent(oEle,sEvent,vFilter);
  7732. }else{
  7733. jindo.$Element._delDelegateInfo(oEventInfo,vFilter);
  7734. }
  7735. }
  7736. }
  7737. /**
  7738. * event 기준으로 삭제하는 함수.
  7739. * @param {Element} 삭제할 엘리먼트.
  7740. * @param {String} 이벤트명.
  7741. * @param {String|Function} cssquery, 필터하는 함수.
  7742. * @since 1.4.6부터 사용가능.
  7743. * @ignore
  7744. */
  7745. jindo.$Element._deleteEvent = function(oEle,sEvent,vFilter){
  7746. var aEvents = oEle['_delegate_events'];
  7747. jindo.$Element._unEventBind(oEle,sEvent,oEle["_delegate_"+sEvent+"_func"]);
  7748. jindo.$Element._delDelegateInfo(oEle,"_delegate_"+sEvent);
  7749. jindo.$Element._delDelegateInfo(oEle,"_delegate_"+sEvent+"_func");
  7750. aEvents = jindo.$A(aEvents).refuse(sEvent).$value();
  7751. if (!aEvents.length) {
  7752. jindo.$Element._delDelegateInfo(oEle,"_delegate_events");
  7753. }else{
  7754. oEle['_delegate_events'] = jindo.$A(aEvents).refuse(sEvent).$value();
  7755. }
  7756. }
  7757. /**
  7758. * 이벤트를 해제 하는 함수.
  7759. * @param {Element} oEle 엘리먼트
  7760. * @param {Boolean} sType 이벤트 타입.
  7761. * @param {Function} fAroundFunc 바인딩을 해제할 함수.
  7762. * @ignore
  7763. */
  7764. jindo.$Element._unEventBind = function(oEle,sType,fAroundFunc){
  7765. if(oEle.removeEventListener){
  7766. jindo.$Element._unEventBind = function(oEle,sType,fAroundFunc){
  7767. oEle.removeEventListener(sType,fAroundFunc,false);
  7768. }
  7769. }else{
  7770. jindo.$Element._unEventBind = function(oEle,sType,fAroundFunc){
  7771. oEle.detachEvent("on"+sType,fAroundFunc);
  7772. }
  7773. }
  7774. jindo.$Element._unEventBind(oEle,sType,fAroundFunc);
  7775. }
  7776. /**
  7777. * @fileOverview $Fn의 생성자 및 메서드를 정의한 파일
  7778. * @name function.js
  7779. */
  7780. /**
  7781. * $Fn 객체를 리턴한다.
  7782. * @extends core
  7783. * @class $Fn 클래스는 자바스크립트 Function 객체의 래퍼(Wrapper) 클래스이다.
  7784. * @constructor
  7785. * @param {Function | String} func
  7786. * <br>
  7787. * Function 객체 혹은 함수의 매개변수를 나타내는 문자열
  7788. * @param {Object | String} thisObject
  7789. * <br>
  7790. * 함수가 특정 객체의 메서드일 때, 해당 객체도 같이 전달한다. 혹은 함수의 몸체를 나타내는 문자열.
  7791. * @return {$Fn} $Fn 객체
  7792. * @see $Fn#toFunction
  7793. * @description [Lite]
  7794. * @example
  7795. func : function() {
  7796. // code here
  7797. }
  7798. var fn = $Fn(func, this);
  7799. * @example
  7800. var someObject = {
  7801. func : function() {
  7802. // code here
  7803. }
  7804. }
  7805. var fn = $Fn(someObject.func, someObject);
  7806. * @example
  7807. var fn = $Fn("a, b", "return a + b;");
  7808. var result = fn.$value()(1, 2) // result = 3;
  7809. // fn은 함수 리터럴인 function(a, b){ return a + b;}와 동일한 함수를 래핑한다.
  7810. * @author Kim, Taegon
  7811. */
  7812. jindo.$Fn = function(func, thisObject) {
  7813. var cl = arguments.callee;
  7814. if (func instanceof cl) return func;
  7815. if (!(this instanceof cl)) return new cl(func, thisObject);
  7816. this._events = [];
  7817. this._tmpElm = null;
  7818. this._key = null;
  7819. if (typeof func == "function") {
  7820. this._func = func;
  7821. this._this = thisObject;
  7822. } else if (typeof func == "string" && typeof thisObject == "string") {
  7823. //this._func = new Function(func, thisObject);
  7824. this._func = eval("false||function("+func+"){"+thisObject+"}")
  7825. }
  7826. }
  7827. /**
  7828. * userAgent cache
  7829. * @ignore
  7830. */
  7831. var _ua = navigator.userAgent;
  7832. /**
  7833. * $value 메서드는 원래의 Function 객체를 리턴한다.
  7834. * @return {Function} 함수 객체
  7835. * @description [Lite]
  7836. * @example
  7837. func : function() {
  7838. // code here
  7839. }
  7840. var fn = $Fn(func, this);
  7841. fn.$value(); // 원래의 함수가 리턴된다.
  7842. */
  7843. jindo.$Fn.prototype.$value = function() {
  7844. return this._func;
  7845. };
  7846. /**
  7847. * bind 메서드는 함수가 객체의 메소드로 동작하도록 묶인 Function 객체를 리턴한다.
  7848. * @return {Function} thisObject의 메소드로 묶인 Function 객체
  7849. * @description [Lite]
  7850. * @example
  7851. var sName = "OUT";
  7852. var oThis = {
  7853. sName : "IN"
  7854. };
  7855. function getName() {
  7856. return this.sName;
  7857. }
  7858. oThis.getName = $Fn(getName, oThis).bind();
  7859. alert( getName() ); // OUT
  7860. alert( oThis.getName() ); // IN
  7861. * @example
  7862. // 함수를 미리 선언하고 나중에 사용할 때,
  7863. // 함수에서 참조 하는 값들은 해당 함수를 생성 할때의 값이 아니라 함수 실행 시점의 값이 사용 되므로 이때 bind를 이용한다.
  7864. for(var i=0; i<2;i++){
  7865. aTmp[i] = function(){alert(i);}
  7866. }
  7867. for(var n=0; n<2;n++){
  7868. aTmp[n](); // 숫자 2만 두번 alert된다.
  7869. }
  7870. for(var i=0; i<2;i++){
  7871. aTmp[i] = $Fn(function(nTest){alert(nTest);}, this).bind(i);
  7872. }
  7873. for(var n=0; n<2;n++){
  7874. aTmp[n](); // 숫자 0, 1이 alert된다.
  7875. }
  7876. * @example
  7877. //클래스 생성 시 함수를 매개변수로 할 때, scope를 맞춰주기 위해 bind를 사용한다.
  7878. var MyClass = $Class({
  7879. fFunc : null,
  7880. $init : function(func){
  7881. this.fFunc = func;
  7882. this.testFunc();
  7883. },
  7884. testFunc : function(){
  7885. this.fFunc();
  7886. }
  7887. })
  7888. var MainClass = $Class({
  7889. $init : function(){
  7890. var oMyClass1 = new MyClass(this.func1);
  7891. var oMyClass2 = new MyClass($Fn(this.func2, this).bind());
  7892. },
  7893. func1 : function(){
  7894. alert(this);// this는 MyClass 를 의미한다.
  7895. },
  7896. func2 : function(){
  7897. alert(this);// this는 MainClass 를 의미한다.
  7898. }
  7899. })
  7900. function init(){
  7901. var a = new MainClass();
  7902. }
  7903. */
  7904. jindo.$Fn.prototype.bind = function() {
  7905. var a = jindo.$A(arguments).$value();
  7906. var f = this._func;
  7907. var t = this._this;
  7908. var b = function() {
  7909. var args = jindo.$A(arguments).$value();
  7910. // fix opera concat bug
  7911. if (a.length) args = a.concat(args);
  7912. return f.apply(t, args);
  7913. };
  7914. return b;
  7915. };
  7916. /**
  7917. * bingForEvent는 객체와 메서드를 묶어 하나의 이벤트 핸들러 Function으로 반환한다.
  7918. * @param {Element, ...} [elementN] 이벤트 객체와 함께 전달할 값
  7919. * @see $Fn#bind
  7920. * @see $Event
  7921. * @description [Lite]
  7922. * @ignore
  7923. */
  7924. jindo.$Fn.prototype.bindForEvent = function() {
  7925. var a = arguments;
  7926. var f = this._func;
  7927. var t = this._this;
  7928. var m = this._tmpElm || null;
  7929. var b = function(e) {
  7930. var args = Array.prototype.slice.apply(a);
  7931. if (typeof e == "undefined") e = window.event;
  7932. if (typeof e.currentTarget == "undefined") {
  7933. e.currentTarget = m;
  7934. }
  7935. var oEvent = jindo.$Event(e);
  7936. args.unshift(oEvent);
  7937. var returnValue = f.apply(t, args);
  7938. if(typeof returnValue != "undefined" && oEvent.type=="beforeunload"){
  7939. e.returnValue = returnValue;
  7940. }
  7941. return returnValue;
  7942. };
  7943. return b;
  7944. };
  7945. /**
  7946. * attach 메서드는 함수를 특정 엘리먼트의 이벤트 핸들러로 할당한다.<br>
  7947. * 함수의 반환 값이 false인 경우, $Fn에 바인딩하여 사용했을 시 IE에서 기본 기능을 막기 때문에 사용하지 않도록 주의한다.
  7948. <ul>
  7949. <li>이벤트 이름에는 on 접두어를 사용하지 않는다.</li>
  7950. <li>마우스 휠 스크롤 이벤트는 mousewheel 로 사용한다.</li>
  7951. <li>기본 이벤트 외에 추가로 사용이 가능한 이벤트에는 domready, mouseenter, mouseleave, mousewheel이 있다.</li>
  7952. </ul>
  7953. * @param {Element | Array} oElement 이벤트 핸들러를 할당할 엘리먼트(엘리먼트가 원소인 배열도 가능)
  7954. * @param {String} sEvent 이벤트 종류
  7955. * @param {Boolean} bUseCapture capturing을 사용할 때(1.4.2 부터 지원)
  7956. * @see $Fn#detach
  7957. * @description [Lite]
  7958. * @return {$Fn} 생성된 $Fn 객체
  7959. * @example
  7960. var someObject = {
  7961. func : function() {
  7962. // code here
  7963. }
  7964. }
  7965. $Fn(someObject.func, someObject).attach($("test"),"click"); // 단일 엘리먼트에 클릭을 할당한 경우
  7966. $Fn(someObject.func, someObject).attach($$(".test"),"click"); // 여러 엘리먼트에 클릭을 할당한 경우
  7967. //attach에 첫번째 인자로 엘리먼트 배열이 들어오면 해당 모든 엘리먼트에 이벤트가 바인딩 됨.
  7968. */
  7969. jindo.$Fn.prototype.attach = function(oElement, sEvent, bUseCapture) {
  7970. var fn = null, l, ev = sEvent, el = oElement, ua = _ua;
  7971. if (typeof bUseCapture == "undefined") {
  7972. bUseCapture = false;
  7973. };
  7974. this._bUseCapture = bUseCapture;
  7975. if ((el instanceof Array) || (jindo.$A && (el instanceof jindo.$A) && (el=el.$value()))) {
  7976. for(var i=0; i < el.length; i++) this.attach(el[i], ev, bUseCapture);
  7977. return this;
  7978. }
  7979. if (!el || !ev) return this;
  7980. if (typeof el.$value == "function") el = el.$value();
  7981. el = jindo.$(el);
  7982. ev = ev.toLowerCase();
  7983. this._tmpElm = el;
  7984. fn = this.bindForEvent();
  7985. this._tmpElm = null;
  7986. var bIsIE = ua.indexOf("MSIE") > -1;
  7987. if (typeof el.addEventListener != "undefined") {
  7988. if (ev == "domready") {
  7989. ev = "DOMContentLoaded";
  7990. }else if (ev == "mousewheel" && ua.indexOf("WebKit") < 0 && !/Opera/.test(ua) && !bIsIE) {
  7991. /*
  7992. IE9인 경우도 DOMMouseScroll이 동작하지 않음.
  7993. */
  7994. ev = "DOMMouseScroll";
  7995. }else if (ev == "mouseenter" && !bIsIE){
  7996. ev = "mouseover";
  7997. fn = jindo.$Fn._fireWhenElementBoundary(el, fn);
  7998. }else if (ev == "mouseleave" && !bIsIE){
  7999. ev = "mouseout";
  8000. fn = jindo.$Fn._fireWhenElementBoundary(el, fn);
  8001. }else if(ev == "transitionend"||ev == "transitionstart"){
  8002. var sPrefix, sPostfix = ev.replace("transition","");
  8003. sPostfix = sPostfix.substr(0,1).toUpperCase() + sPostfix.substr(1);
  8004. if(typeof document.body.style.WebkitTransition !== "undefined"){
  8005. sPrefix = "webkit";
  8006. }else if(typeof document.body.style.OTransition !== "undefined"){
  8007. sPrefix = "o";
  8008. }else if(typeof document.body.style.MsTransition !== "undefined"){
  8009. sPrefix = "ms";
  8010. }
  8011. ev = (sPrefix?sPrefix+"Transition":"transition")+sPostfix;
  8012. this._for_test_attach = ev;
  8013. this._for_test_detach = "";
  8014. }else if(ev == "animationstart"||ev == "animationend"||ev == "animationiteration"){
  8015. var sPrefix, sPostfix = ev.replace("animation","");
  8016. sPostfix = sPostfix.substr(0,1).toUpperCase() + sPostfix.substr(1);
  8017. if(typeof document.body.style.WebkitAnimationName !== "undefined"){
  8018. sPrefix = "webkit";
  8019. }else if(typeof document.body.style.OAnimationName !== "undefined"){
  8020. sPrefix = "o";
  8021. }else if(typeof document.body.style.MsTransitionName !== "undefined"){
  8022. sPrefix = "ms";
  8023. }
  8024. ev = (sPrefix?sPrefix+"Animation":"animation")+sPostfix;
  8025. this._for_test_attach = ev;
  8026. this._for_test_detach = "";
  8027. }
  8028. el.addEventListener(ev, fn, bUseCapture);
  8029. } else if (typeof el.attachEvent != "undefined") {
  8030. if (ev == "domready") {
  8031. /*
  8032. iframe안에서 domready이벤트가 실행되지 않기 때문에 error를 던짐.
  8033. */
  8034. if(window.top != window) throw new Error("Domready Event doesn't work in the iframe.");
  8035. jindo.$Fn._domready(el, fn);
  8036. return this;
  8037. } else {
  8038. el.attachEvent("on"+ev, fn);
  8039. }
  8040. }
  8041. if (!this._key) {
  8042. this._key = "$"+jindo.$Fn.gc.count++;
  8043. jindo.$Fn.gc.pool[this._key] = this;
  8044. }
  8045. this._events[this._events.length] = {element:el, event:sEvent.toLowerCase(), func:fn};
  8046. return this;
  8047. };
  8048. /**
  8049. * detach 메서드는 엘리먼트의 이벤트 핸들러로 할당된 함수를 해제한다.
  8050. * @remark 이벤트 이름에는 on 접두어를 사용하지 않는다.
  8051. * @remark 마우스 휠 스크롤 이벤트는 mousewheel 로 사용한다.
  8052. * @param {Element} oElement 이벤트 핸들러를 해제할 엘리먼트
  8053. * @param {String} sEvent 이벤트 종류
  8054. * @see $Fn#attach
  8055. * @description [Lite]
  8056. * @return {$Fn} 생성된 $Fn 객체
  8057. * @example
  8058. var someObject = {
  8059. func : function() {
  8060. // code here
  8061. }
  8062. }
  8063. $Fn(someObject.func, someObject).detach($("test"),"click"); // 단일 엘리먼트에 클릭을 할당한 경우
  8064. $Fn(someObject.func, someObject).detach($$(".test"),"click"); // 여러 엘리먼트에 클릭을 할당한 경우
  8065. */
  8066. jindo.$Fn.prototype.detach = function(oElement, sEvent) {
  8067. var fn = null, l, el = oElement, ev = sEvent, ua = _ua;
  8068. if ((el instanceof Array) || (jindo.$A && (el instanceof jindo.$A) && (el=el.$value()))) {
  8069. for(var i=0; i < el.length; i++) this.detach(el[i], ev);
  8070. return this;
  8071. }
  8072. if (!el || !ev) return this;
  8073. if (jindo.$Element && el instanceof jindo.$Element) el = el.$value();
  8074. el = jindo.$(el);
  8075. ev = ev.toLowerCase();
  8076. var e = this._events;
  8077. for(var i=0; i < e.length; i++) {
  8078. if (e[i].element !== el || e[i].event !== ev) continue;
  8079. fn = e[i].func;
  8080. this._events = jindo.$A(this._events).refuse(e[i]).$value();
  8081. break;
  8082. }
  8083. if (typeof el.removeEventListener != "undefined") {
  8084. if (ev == "domready") {
  8085. ev = "DOMContentLoaded";
  8086. }else if (ev == "mousewheel" && ua.indexOf("WebKit") < 0) {
  8087. ev = "DOMMouseScroll";
  8088. }else if (ev == "mouseenter"){
  8089. ev = "mouseover";
  8090. }else if (ev == "mouseleave"){
  8091. ev = "mouseout";
  8092. }else if(ev == "transitionend"||ev == "transitionstart"){
  8093. var sPrefix, sPostfix = ev.replace("transition","");
  8094. sPostfix = sPostfix.substr(0,1).toUpperCase() + sPostfix.substr(1);
  8095. if(typeof document.body.style.WebkitTransition !== "undefined"){
  8096. sPrefix = "webkit";
  8097. }else if(typeof document.body.style.OTransition !== "undefined"){
  8098. sPrefix = "o";
  8099. }else if(typeof document.body.style.MsTransition !== "undefined"){
  8100. sPrefix = "ms";
  8101. }
  8102. ev = (sPrefix?sPrefix+"Transition":"transition")+sPostfix;
  8103. this._for_test_detach = ev;
  8104. this._for_test_attach = "";
  8105. }else if(ev == "animationstart"||ev == "animationend"||ev == "animationiteration"){
  8106. var sPrefix, sPostfix = ev.replace("animation","");
  8107. sPostfix = sPostfix.substr(0,1).toUpperCase() + sPostfix.substr(1);
  8108. if(typeof document.body.style.WebkitAnimationName !== "undefined"){
  8109. sPrefix = "webkit";
  8110. }else if(typeof document.body.style.OAnimationName !== "undefined"){
  8111. sPrefix = "o";
  8112. }else if(typeof document.body.style.MsTransitionName !== "undefined"){
  8113. sPrefix = "ms";
  8114. }
  8115. ev = (sPrefix?sPrefix+"Animation":"animation")+sPostfix;
  8116. this._for_test_detach = ev;
  8117. this._for_test_attach = "";
  8118. }
  8119. if (fn) el.removeEventListener(ev, fn, false);
  8120. } else if (typeof el.detachEvent != "undefined") {
  8121. if (ev == "domready") {
  8122. jindo.$Fn._domready.list = jindo.$Fn._domready.list.refuse(fn);
  8123. return this;
  8124. } else {
  8125. el.detachEvent("on"+ev, fn);
  8126. }
  8127. }
  8128. return this;
  8129. };
  8130. /**
  8131. * delay 메서드는 래핑한 함수를 지정한 시간 이후에 호출한다.
  8132. * @param {Number} nSec 함수를 호출할 때까지 대기할 시간(초 단위).
  8133. * @param {Array} args 함수를 호출할 때 사용할 매개변수. 매개변수가 여러 개일 경우 배열을 사용한다.
  8134. * @see $Fn#bind
  8135. * @see $Fn#setInterval
  8136. * @description [Lite]
  8137. * @return {$Fn} 생성된 $Fn 객체
  8138. * @example
  8139. function func(a, b) {
  8140. alert(a + b);
  8141. }
  8142. $Fn(func).delay(5, [3, 5]);//5초 이후에 3, 5 값을 매개변수로 하는 함수 func를 호출한다.
  8143. */
  8144. jindo.$Fn.prototype.delay = function(nSec, args) {
  8145. if (typeof args == "undefined") args = [];
  8146. this._delayKey = setTimeout(this.bind.apply(this, args), nSec*1000);
  8147. return this;
  8148. };
  8149. /**
  8150. * setInterval 메서드는 래핑한 함수를 지정한 시간 간격마다 호출한다.
  8151. * @param {Number} nSec 함수를 호출할 간격(초 단위).
  8152. * @param {Array} args 함수를 호출할 때 사용할 매개변수. 매개변수가 여러 개일 경우 배열을 사용한다.
  8153. * @return {Number} Interval ID, 함수 호출을 해제할 때 사용한다.
  8154. * @see $Fn#bind
  8155. * @see $Fn#delay
  8156. * @description [Lite]
  8157. * @example
  8158. function func(a, b) {
  8159. alert(a + b);
  8160. }
  8161. $Fn(func).setInterval(5, [3, 5]);//5초 간격으로 3, 5 값을 매개변수로 하는 함수 func를 호출한다.
  8162. */
  8163. jindo.$Fn.prototype.setInterval = function(nSec, args) {
  8164. if (typeof args == "undefined") args = [];
  8165. this._repeatKey = setInterval(this.bind.apply(this, args), nSec*1000);
  8166. return this._repeatKey;
  8167. };
  8168. /**
  8169. * repeat 메서드는 setInterval와 같다.
  8170. * @param {Number} nSec 함수를 호출간 간격.
  8171. * @param {Array} args 함수를 호출할 때 사용할 매개변수. 매개변수가 여러 개일 경우 배열을 사용한다.
  8172. * @return {Number} Interval ID, 함수 호출을 해제할 때 사용한다.
  8173. * @see $Fn#bind
  8174. * @see $Fn#delay
  8175. * @description [Lite]
  8176. * @example
  8177. function func(a, b) {
  8178. alert(a + b);
  8179. }
  8180. $Fn(func).repeat(5, [3, 5]);//5초 간격으로 3, 5 값을 매개변수로 하는 함수 func를 호출한다.
  8181. */
  8182. jindo.$Fn.prototype.repeat = jindo.$Fn.prototype.setInterval;
  8183. /**
  8184. * stopDelay는 delay 메서드로 지정한 함수 호출을 멈출 때 사용한다.
  8185. * @return {$Fn} $Fn 객체
  8186. * @see $Fn#delay
  8187. * @example
  8188. function func(a, b) {
  8189. alert(a + b);
  8190. }
  8191. var fpDelay = $Fn(func);
  8192. fpDelay.delay(5, [3, 5]);
  8193. fpDelay.stopDelay();
  8194. */
  8195. jindo.$Fn.prototype.stopDelay = function(){
  8196. if(typeof this._delayKey != "undefined"){
  8197. window.clearTimeout(this._delayKey);
  8198. delete this._delayKey;
  8199. }
  8200. return this;
  8201. }
  8202. /**
  8203. * stopRepeat는 repeat메서드로 지정한 함수 호출을 멈출 때 사용한다.
  8204. * @return {$Fn} $Fn 객체
  8205. * @see $Fn#repeat
  8206. * @example
  8207. function func(a, b) {
  8208. alert(a + b);
  8209. }
  8210. var fpDelay = $Fn(func);
  8211. fpDelay.repeat(5, [3, 5]);
  8212. fpDelay.stopRepeat();
  8213. */
  8214. jindo.$Fn.prototype.stopRepeat = function(){
  8215. if(typeof this._repeatKey != "undefined"){
  8216. window.clearInterval(this._repeatKey);
  8217. delete this._repeatKey;
  8218. }
  8219. return this;
  8220. }
  8221. /**
  8222. * 메모리에서 이 객체를 사용한 참조를 모두 해제한다(직접 호출 금지).
  8223. * @param {Element} 해당 요소의 이벤트 핸들러만 해제.
  8224. * @ignore
  8225. */
  8226. jindo.$Fn.prototype.free = function(oElement) {
  8227. var len = this._events.length;
  8228. while(len > 0) {
  8229. var el = this._events[--len].element;
  8230. var sEvent = this._events[len].event;
  8231. var fn = this._events[len].func;
  8232. if (oElement && el!==oElement){
  8233. continue;
  8234. }
  8235. this.detach(el, sEvent);
  8236. /*
  8237. unload시에 엘리먼트에 attach한 함수를 detach하는 로직이 있는데 해당 로직으로 인하여 unload이벤트가 실행되지 않아 실행시키는 로직을 만듬. 그리고 해당 로직은 gc에서 호출할때만 호출.
  8238. */
  8239. var isGCCall = !oElement;
  8240. if (isGCCall && window === el && sEvent == "unload" && _ua.indexOf("MSIE")<1) {
  8241. this._func.call(this._this);
  8242. }
  8243. delete this._events[len];
  8244. }
  8245. if(this._events.length==0)
  8246. try { delete jindo.$Fn.gc.pool[this._key]; }catch(e){};
  8247. };
  8248. /**
  8249. * IE에서 domready(=DOMContentLoaded) 이벤트를 에뮬레이션한다.
  8250. * @ignore
  8251. */
  8252. jindo.$Fn._domready = function(doc, func) {
  8253. if (typeof jindo.$Fn._domready.list == "undefined") {
  8254. var f = null, l = jindo.$Fn._domready.list = jindo.$A([func]);
  8255. // use the trick by Diego Perini
  8256. // http://javascript.nwbox.com/IEContentLoaded/
  8257. var done = false, execFuncs = function(){
  8258. if(!done) {
  8259. done = true;
  8260. var evt = {
  8261. type : "domready",
  8262. target : doc,
  8263. currentTarget : doc
  8264. };
  8265. while(f = l.shift()) f(evt);
  8266. }
  8267. };
  8268. (function (){
  8269. try {
  8270. doc.documentElement.doScroll("left");
  8271. } catch(e) {
  8272. setTimeout(arguments.callee, 50);
  8273. return;
  8274. }
  8275. execFuncs();
  8276. })();
  8277. // trying to always fire before onload
  8278. doc.onreadystatechange = function() {
  8279. if (doc.readyState == 'complete') {
  8280. doc.onreadystatechange = null;
  8281. execFuncs();
  8282. }
  8283. };
  8284. } else {
  8285. jindo.$Fn._domready.list.push(func);
  8286. }
  8287. };
  8288. /**
  8289. * 비 IE에서 mouseenter/mouseleave 이벤트를 에뮬레이션하기 위한 요소 영역을 벗어나는 경우에만 실행하는 함수 필터
  8290. * @ignore
  8291. */
  8292. jindo.$Fn._fireWhenElementBoundary = function(doc, func) {
  8293. return function(evt){
  8294. var oEvent = jindo.$Event(evt);
  8295. var relatedElement = jindo.$Element(oEvent.relatedElement);
  8296. if(relatedElement && (relatedElement.isEqual(this) || relatedElement.isChildOf(this))) return;
  8297. func.call(this,evt);
  8298. }
  8299. };
  8300. /**
  8301. * gc 메서드는 엘리먼트에 할당된 모든 이벤트 핸들러를 해제한다.
  8302. * @example
  8303. var someObject = {
  8304. func1 : function() {
  8305. // code here
  8306. },
  8307. func2 : function() {
  8308. // code here
  8309. }
  8310. }
  8311. $Fn(someObject.func1, someObject).attach($("test1"),"mouseup");
  8312. $Fn(someObject.func2, someObject).attach($("test1"),"mousedown");
  8313. $Fn(someObject.func1, someObject).attach($("test2"),"mouseup");
  8314. $Fn(someObject.func2, someObject).attach($("test2"),"mousedown");
  8315. ..
  8316. ..
  8317. $Fn.gc();
  8318. */
  8319. jindo.$Fn.gc = function() {
  8320. var p = jindo.$Fn.gc.pool;
  8321. for(var key in p) {
  8322. if(p.hasOwnProperty(key))
  8323. try { p[key].free(); }catch(e){ };
  8324. }
  8325. /*
  8326. 레퍼런스를 삭제한다.
  8327. */
  8328. jindo.$Fn.gc.pool = p = {};
  8329. };
  8330. /**
  8331. * freeElement 메소드는 지정한 엘리먼트에 할당된 이벤트 핸들러를 모두 해제한다.
  8332. * @since 1.3.5
  8333. * @see $Fn#gc
  8334. * @example
  8335. var someObject = {
  8336. func : function() {
  8337. // code here
  8338. }
  8339. }
  8340. $Fn(someObject.func, someObject).attach($("test"),"mouseup");
  8341. $Fn(someObject.func, someObject).attach($("test"),"mousedown");
  8342. $Fn.freeElement($("test"));
  8343. */
  8344. jindo.$Fn.freeElement = function(oElement){
  8345. var p = jindo.$Fn.gc.pool;
  8346. for(var key in p) {
  8347. if(p.hasOwnProperty(key)){
  8348. try {
  8349. p[key].free(oElement);
  8350. }catch(e){ };
  8351. }
  8352. }
  8353. }
  8354. jindo.$Fn.gc.count = 0;
  8355. jindo.$Fn.gc.pool = {};
  8356. function isUnCacheAgent(){
  8357. var isIPad = (_ua.indexOf("iPad") > -1);
  8358. var isAndroid = (_ua.indexOf("Android") > -1);
  8359. var isMSafari = (!(_ua.indexOf("IEMobile") > -1) && (_ua.indexOf("Mobile") > -1) )||(isIPad && (_ua.indexOf("Safari") > -1));
  8360. return isMSafari && !isIPad && !isAndroid;
  8361. }
  8362. if (typeof window != "undefined" && !isUnCacheAgent()) {
  8363. jindo.$Fn(jindo.$Fn.gc).attach(window, "unload");
  8364. }
  8365. /**
  8366. * @fileOverview $Event의 생성자 및 메서드를 정의한 파일
  8367. * @name event.js
  8368. */
  8369. /**
  8370. * JavaScript Core 이벤트 객체로부터 $Event 객체를 생성한다.
  8371. * @class $Event 클래스는 자바스크립트 Event 객체의 래퍼(Wrapper) 클래스이다. 사용자는 $Event.element 메서드를 사용하여 이벤트가 발생한 객체를 알 수 있다.
  8372. * @param {Event} e Event 객체
  8373. * @constructor
  8374. * @description [Lite]
  8375. * @author Kim, Taegon
  8376. */
  8377. jindo.$Event = function(e) {
  8378. var cl = arguments.callee;
  8379. if (e instanceof cl) return e;
  8380. if (!(this instanceof cl)) return new cl(e);
  8381. if (typeof e == "undefined") e = window.event;
  8382. if (e === window.event && document.createEventObject) e = document.createEventObject(e);
  8383. this._event = e;
  8384. this._globalEvent = window.event;
  8385. /**
  8386. 이벤트의 종류
  8387. */
  8388. this.type = e.type.toLowerCase();
  8389. if (this.type == "dommousescroll") {
  8390. this.type = "mousewheel";
  8391. } else if (this.type == "domcontentloaded") {
  8392. this.type = "domready";
  8393. }
  8394. this.canceled = false;
  8395. /**
  8396. 이벤트가 발생한 엘리먼트
  8397. */
  8398. this.element = e.target || e.srcElement;
  8399. /**
  8400. 이벤트가 정의된 엘리먼트
  8401. */
  8402. this.currentElement = e.currentTarget;
  8403. /**
  8404. 이벤트의 연관 엘리먼트
  8405. */
  8406. this.relatedElement = null;
  8407. if (typeof e.relatedTarget != "undefined") {
  8408. this.relatedElement = e.relatedTarget;
  8409. } else if(e.fromElement && e.toElement) {
  8410. this.relatedElement = e[(this.type=="mouseout")?"toElement":"fromElement"];
  8411. }
  8412. }
  8413. /**
  8414. * mouse 메서드는 마우스 이벤트의 버튼, 휠 정보를 리턴한다.
  8415. * @description [Lite]
  8416. * @example
  8417. function eventHandler(evt) {
  8418. var mouse = evt.mouse();
  8419. mouse.delta; // Number. 휠이 움직인 정도. 휠을 위로 굴리면 양수, 아래로 굴리면 음수.
  8420. mouse.left; // Boolean. 마우스 왼쪽 버튼을 눌렸으면 true, 아니면 false
  8421. mouse.middle; // Boolean. 마우스 중간 버튼을 눌렸으면 true, 아니면 false
  8422. mouse.right; // Boolean. 마우스 오른쪽 버튼을 눌렸으면 true, 아니면 false
  8423. }
  8424. * @return {Object} 마우스 정보를 가지는 객체. 리턴한 객체의 속성은 예제를 참조한다.
  8425. */
  8426. jindo.$Event.prototype.mouse = function() {
  8427. var e = this._event;
  8428. var delta = 0;
  8429. var left = false,mid = false,right = false;
  8430. var left = e.which ? e.button==0 : !!(e.button&1);
  8431. var mid = e.which ? e.button==1 : !!(e.button&4);
  8432. var right = e.which ? e.button==2 : !!(e.button&2);
  8433. var ret = {};
  8434. if (e.wheelDelta) {
  8435. delta = e.wheelDelta / 120;
  8436. } else if (e.detail) {
  8437. delta = -e.detail / 3;
  8438. }
  8439. ret = {
  8440. delta : delta,
  8441. left : left,
  8442. middle : mid,
  8443. right : right
  8444. };
  8445. // replace method
  8446. this.mouse = function(){ return ret };
  8447. return ret;
  8448. };
  8449. /**
  8450. * key 메서드는 키보드 이벤트 정보를 리턴한다.
  8451. * @description [Lite]
  8452. * @example
  8453. function eventHandler(evt) {
  8454. var key = evt.key();
  8455. key.keyCode; // Number. 눌린 키보드의 키코드
  8456. key.alt; // Boolean. Alt 키를 눌렸으면 true.
  8457. key.ctrl; // Boolean. Ctrl 키를 눌렸으면 true.
  8458. key.meta; // Boolean. Meta 키를 눌렸으면 true. Meta키는 맥의 커맨드키를 검출할 때 사용합니다.
  8459. key.shift; // Boolean. Shift 키를 눌렸으면 true.
  8460. key.up; // Boolean. 위쪽 화살표 키를 눌렸으면 true.
  8461. key.down; // Boolean. 아래쪽 화살표 키를 눌렸으면 true.
  8462. key.left; // Boolean. 왼쪽 화살표 키를 눌렸으면 true.
  8463. key.right; // Boolean. 오른쪽 화살표 키를 눌렸으면 true.
  8464. key.enter; // Boolean. 리턴키를 눌렀으면 true
  8465. key.esc; // Boolean. ESC키를 눌렀으면 true
  8466. }
  8467. }
  8468. * @return {Object} 키보드 이벤트의 눌린 키값. 객체의 속성은 예제를 참조한다.
  8469. */
  8470. jindo.$Event.prototype.key = function() {
  8471. var e = this._event;
  8472. var k = e.keyCode || e.charCode;
  8473. var ret = {
  8474. keyCode : k,
  8475. alt : e.altKey,
  8476. ctrl : e.ctrlKey,
  8477. meta : e.metaKey,
  8478. shift : e.shiftKey,
  8479. up : (k == 38),
  8480. down : (k == 40),
  8481. left : (k == 37),
  8482. right : (k == 39),
  8483. enter : (k == 13),
  8484. esc : (k == 27)
  8485. };
  8486. this.key = function(){ return ret };
  8487. return ret;
  8488. };
  8489. /**
  8490. * pos 메서드는 마우스 커서의 위치 정보를 리턴한다.
  8491. * @param {Boolean} bGetOffset 현재 엘리먼트에 대한 마우스 커서의 상대위치인 offsetX, offsetY를 구할 것인지의 여부. true면 값을 구한다(offsetX, offsetY는 1.2.0버전부터 추가). $Element 가 포함되어 있어야 한다.
  8492. * @description [Lite]
  8493. * @example
  8494. function eventHandler(evt) {
  8495. var pos = evt.pos();
  8496. pos.clientX; // Number. 현재 화면에 대한 X 좌표
  8497. pos.clientY; // Number. 현재 화면에 대한 Y 좌표
  8498. pos.pageX; // Number. 문서 전체에 대한 X 좌표
  8499. pos.pageY; // Number. 문서 전체에 대한 Y 좌표
  8500. pos.layerX; // Number. <b>deprecated.</b> 이벤트가 발생한 엘리먼트로부터의 상대적인 X 좌표
  8501. pos.layerY; // Number. <b>deprecated.</b> 이벤트가 발생한 엘리먼트로부터의 상대적인 Y 좌표
  8502. pos.offsetX; // Number. 이벤트가 발생한 엘리먼트에 대한 마우스 커서의 상대적인 X좌표 (1.2.0 이상)
  8503. pos.offsetY; // Number. 이벤트가 발생한 엘리먼트에 대한 마우스 커서의 상대적인 Y좌표 (1.2.0 이상)
  8504. }
  8505. * @return {Object} 마우스 커서의 위치 정보. 객체의 속성은 예제를 참조한다.
  8506. * @remark layerX, layerY는 차후 지원하지 않을(deprecated) 예정입니다.
  8507. */
  8508. jindo.$Event.prototype.pos = function(bGetOffset) {
  8509. var e = this._event;
  8510. var b = (this.element.ownerDocument||document).body;
  8511. var de = (this.element.ownerDocument||document).documentElement;
  8512. var pos = [b.scrollLeft || de.scrollLeft, b.scrollTop || de.scrollTop];
  8513. var ret = {
  8514. clientX : e.clientX,
  8515. clientY : e.clientY,
  8516. pageX : 'pageX' in e ? e.pageX : e.clientX+pos[0]-b.clientLeft,
  8517. pageY : 'pageY' in e ? e.pageY : e.clientY+pos[1]-b.clientTop,
  8518. layerX : 'offsetX' in e ? e.offsetX : e.layerX - 1,
  8519. layerY : 'offsetY' in e ? e.offsetY : e.layerY - 1
  8520. };
  8521. /*
  8522. 오프셋을 구하는 메소드의 비용이 크므로, 요청시에만 구하도록 한다.
  8523. */
  8524. if (bGetOffset && jindo.$Element) {
  8525. var offset = jindo.$Element(this.element).offset();
  8526. ret.offsetX = ret.pageX - offset.left;
  8527. ret.offsetY = ret.pageY - offset.top;
  8528. }
  8529. return ret;
  8530. };
  8531. /**
  8532. * stop 메서드는 이벤트의 버블링과 기본 동작을 중지시킨다.
  8533. * @remark 버블링은 특정 HTML 엘리먼트에서 이벤트가 발생했을 때 이벤트가 상위 노드로 전파되는 현상이다. 예를 들어, div 객체를 클릭할 때 div와 함께 상위 엘리먼트인 document에도 onclick 이벤트가 발생한다. stop() 메소드는 지정한 객체에서만 이벤트가 발생하도록 버블링을 차단한다.
  8534. * @description [Lite]
  8535. * @example
  8536. // 기본 동작만 중지시키고 싶을 때 (1.1.3버전 이상)
  8537. function stopDefaultOnly(evt) {
  8538. // Here is some code to execute
  8539. // Stop default event only
  8540. evt.stop($Event.CANCEL_DEFAULT);
  8541. }
  8542. * @return {$Event} 이벤트 객체.
  8543. * @param {Number} nCancel 이벤트의 버블링과 기본 동작을 선택하여 중지시킨다. 기본값은 $Event.CANCEL_ALL 이다(1.1.3 버전 이상).
  8544. */
  8545. jindo.$Event.prototype.stop = function(nCancel) {
  8546. nCancel = nCancel || jindo.$Event.CANCEL_ALL;
  8547. var e = (window.event && window.event == this._globalEvent)?this._globalEvent:this._event;
  8548. var b = !!(nCancel & jindo.$Event.CANCEL_BUBBLE); // stop bubbling
  8549. var d = !!(nCancel & jindo.$Event.CANCEL_DEFAULT); // stop default event
  8550. this.canceled = true;
  8551. if (typeof e.preventDefault != "undefined" && d) e.preventDefault();
  8552. if (typeof e.stopPropagation != "undefined" && b) e.stopPropagation();
  8553. if(d) e.returnValue = false;
  8554. if(b) e.cancelBubble = true;
  8555. return this;
  8556. };
  8557. /**
  8558. * stopDefault 메서드는 이벤트의 기본 동작을 중지시킨다.
  8559. * @return {$Event} 이벤트 객체.
  8560. * @see $Event#stop
  8561. * @description [Lite]
  8562. */
  8563. jindo.$Event.prototype.stopDefault = function(){
  8564. return this.stop(jindo.$Event.CANCEL_DEFAULT);
  8565. }
  8566. /**
  8567. * stopBubble 메서드는 이벤트의 버블링을 중지시킨다.
  8568. * @return {$Event} 이벤트 객체.
  8569. * @see $Event#stop
  8570. * @description [Lite]
  8571. */
  8572. jindo.$Event.prototype.stopBubble = function(){
  8573. return this.stop(jindo.$Event.CANCEL_BUBBLE);
  8574. }
  8575. /**
  8576. * $value 메서드는 원래의 이벤트 객체를 리턴한다
  8577. * @example
  8578. function eventHandler(evt){
  8579. evt.$value();
  8580. }
  8581. * @return {Event} Event
  8582. */
  8583. jindo.$Event.prototype.$value = function() {
  8584. return this._event;
  8585. };
  8586. /**
  8587. * $Event#stop 메서드에서 버블링을 중지시킨다.
  8588. * @final
  8589. */
  8590. jindo.$Event.CANCEL_BUBBLE = 1;
  8591. /**
  8592. * $Event#stop 메서드에서 기본 동작을 중지시킨다.
  8593. * @final
  8594. */
  8595. jindo.$Event.CANCEL_DEFAULT = 2;
  8596. /**
  8597. * $Event#stop 메서드에서 버블링과 기본 동작 모두 중지시킨다.
  8598. * @final
  8599. */
  8600. jindo.$Event.CANCEL_ALL = 3;
  8601. /**
  8602. * @fileOverview $ElementList의 생성자 및 메서드를 정의한 파일
  8603. * @name elementlist.js
  8604. */
  8605. /**
  8606. * $ElementList 객체를 생성 및 리턴한다.
  8607. * @class $ElementList 클래스는 id 배열, 혹은 CSS 쿼리 등을 사용하여 DOM 엘리먼트의 배열을 만든다.
  8608. * @param {String | Array} els 문서에서 DOM 엘리먼트를 찾기 위한 CSS 선택자 혹은 id, HTMLElement, $Element의 배열
  8609. * @constructor
  8610. * @borrows $Element#show as this.show
  8611. * @borrows $Element#hide as this.hide
  8612. * @borrows $Element#toggle as this.toggle
  8613. * @borrows $Element#addClass as this.addClass
  8614. * @borrows $Element#removeClass as this.removeClass
  8615. * @borrows $Element#toggleClass as this.toggleClass
  8616. * @borrows $Element#fireEvent as this.fireEvent
  8617. * @borrows $Element#leave as this.leave
  8618. * @borrows $Element#empty as this.empty
  8619. * @borrows $Element#appear as this.appear
  8620. * @borrows $Element#disappear as this.disappear
  8621. * @borrows $Element#className as this.className
  8622. * @borrows $Element#width as this.width
  8623. * @borrows $Element#height as this.height
  8624. * @borrows $Element#text as this.text
  8625. * @borrows $Element#html as this.html
  8626. * @borrows $Element#css as this.css
  8627. * @borrows $Element#attr as this.attr
  8628. * @author Kim, Taegon
  8629. */
  8630. jindo.$ElementList = function (els) {
  8631. var cl = arguments.callee;
  8632. if (els instanceof cl) return els;
  8633. if (!(this instanceof cl)) return new cl(els);
  8634. if (els instanceof Array) {
  8635. els = jindo.$A(els);
  8636. } else if(jindo.$A && els instanceof jindo.$A){
  8637. els = jindo.$A(els.$value());
  8638. } else if (typeof els == "string" && jindo.cssquery) {
  8639. els = jindo.$A(jindo.cssquery(els));
  8640. } else {
  8641. els = jindo.$A();
  8642. }
  8643. this._elements = els.map(function(v,i,a){ return jindo.$Element(v) });
  8644. }
  8645. /**
  8646. * get 메서드는 $ElementList에서 인덱스에 해당하는 엘리먼트를 가져온다.
  8647. * @param {Number} idx 가져올 엘리먼트의 인덱스. 인덱스는 0에서 부터 시작한다.
  8648. * @return {$Element} 인덱스에 해당하는 엘리먼트
  8649. */
  8650. jindo.$ElementList.prototype.get = function(idx) {
  8651. return this._elements.$value()[idx];
  8652. };
  8653. /**
  8654. * getFirst 메서드는 $ElementList의 첫번째 엘리먼트를 가져온다.
  8655. * @remark getFirst 메서드의 리턴값은 $ElementList.get(0)의 리턴값과 동일하다.
  8656. * @return {$Element} 첫번째 엘리먼트
  8657. */
  8658. jindo.$ElementList.prototype.getFirst = function() {
  8659. return this.get(0);
  8660. };
  8661. /**
  8662. * length메소드는 $A의 length를 이용한다.(1.4.3 부터 사용 가능.)
  8663. * @return Number 배열의 크기
  8664. * @param {Number} [nLen] 새로 리턴할 배열의 크기. nLen이 기존의 배열보다 크면 oValue으로 초기화한 원소를 마지막에 덧붙인다. nLen이 기존 배열보다 작으면 nLen번째 이후의 원소는 제거한다.
  8665. * @param {Value} [oValue] 새로운 원소를 추가할 때 사용할 초기값
  8666. * @see $A#length
  8667. */
  8668. jindo.$ElementList.prototype.length = function(nLen, oValue) {
  8669. return this._elements.length(nLen, oValue);
  8670. }
  8671. /**
  8672. * getLast 메서드는 $ElementList의 마지막 엘리먼트를 가져온다.
  8673. * @return {$Element} 마지막 엘리먼트
  8674. */
  8675. jindo.$ElementList.prototype.getLast = function() {
  8676. return this.get(Math.max(this._elements.length()-1,0));
  8677. };
  8678. /**
  8679. * $value 메소드는 자신의 배열 엘리먼트을 반환 한다.
  8680. * @return {Array} $Element가 들어 있는 배열.
  8681. */
  8682. jindo.$ElementList.prototype.$value = function() {
  8683. return this._elements.$value();
  8684. };
  8685. (function(proto){
  8686. var setters = ['show','hide','toggle','addClass','removeClass','toggleClass','fireEvent','leave',
  8687. 'empty','appear','disappear','className','width','height','text','html','css','attr'];
  8688. jindo.$A(setters).forEach(function(name){
  8689. proto[name] = function() {
  8690. var args = jindo.$A(arguments).$value();
  8691. this._elements.forEach(function(el){
  8692. el[name].apply(el, args);
  8693. });
  8694. return this;
  8695. }
  8696. });
  8697. jindo.$A(['appear','disappear']).forEach(function(name){
  8698. proto[name] = function(duration, callback) {
  8699. var len = this._elements.length;
  8700. var self = this;
  8701. this._elements.forEach(function(el,idx){
  8702. if(idx == len-1) {
  8703. el[name](duration, function(){callback(self)});
  8704. } else {
  8705. el[name](duration);
  8706. }
  8707. });
  8708. return this;
  8709. }
  8710. });
  8711. })(jindo.$ElementList.prototype);
  8712. /**
  8713. * @fileOverview $Json의 생성자 및 메서드를 정의한 파일
  8714. * @name json.js
  8715. */
  8716. /**
  8717. * $S 객체를 생성한다.
  8718. * @class $S 클래스는 문자열을 처리하기 위한 래퍼(Wrapper) 클래스이다.
  8719. * @constructor
  8720. * @param {String} str
  8721. * <br>
  8722. * 문자열을 매개변수로 지정한다.
  8723. * @author Kim, Taegon
  8724. */
  8725. jindo.$S = function(str) {
  8726. var cl = arguments.callee;
  8727. if (typeof str == "undefined") str = "";
  8728. if (str instanceof cl) return str;
  8729. if (!(this instanceof cl)) return new cl(str);
  8730. this._str = str+"";
  8731. }
  8732. /**
  8733. * $value 메서드는 원래의 문자열을 리턴한다.
  8734. * @return {String} 래핑된 원래의 문자열
  8735. * @see $S#toString
  8736. * @example
  8737. var str = $S("Hello world!!");
  8738. str.$value();
  8739. *
  8740. * // 결과 :
  8741. * // Hello world!!
  8742. */
  8743. jindo.$S.prototype.$value = function() {
  8744. return this._str;
  8745. };
  8746. /**
  8747. * toString 메서드는 원래의 문자열을 리턴한다.
  8748. * @return {String} 래핑된 원래의 문자열
  8749. * @remark $value와 같은 의미
  8750. * @example
  8751. var str = $S("Hello world!!");
  8752. str.toString();
  8753. *
  8754. * // 결과 :
  8755. * // Hello world!!
  8756. */
  8757. jindo.$S.prototype.toString = jindo.$S.prototype.$value;
  8758. /**
  8759. * trim 메서드는 문자열의 양 끝 공백을 제거한다.(1.4.1 부터 전각공백도 제거)
  8760. * @return {$S} 문자열의 양 끝을 제거한 새로운 $S 객체
  8761. * @example
  8762. var str = " I have many spaces. ";
  8763. document.write ( $S(str).trim() );
  8764. *
  8765. * // 결과 :
  8766. * // I have many spaces.
  8767. */
  8768. jindo.$S.prototype.trim = function() {
  8769. if ("".trim) {
  8770. jindo.$S.prototype.trim = function() {
  8771. return jindo.$S(this._str.trim());
  8772. }
  8773. }else{
  8774. jindo.$S.prototype.trim = function() {
  8775. return jindo.$S(this._str.replace(/^(\s| )+/g, "").replace(/(\s| )+$/g, ""));
  8776. }
  8777. }
  8778. return jindo.$S(this.trim());
  8779. };
  8780. /**
  8781. * escapeHTML 메서드는 HTML 특수 문자를 HTML 엔티티(Entities)형식으로 이스케이프(escape)한다.
  8782. * @return {$S} HTML 특수 문자를 엔티티 형식으로 변환한 새로운 $S 객체
  8783. * @see $S#unescapeHTML
  8784. * @remark ", &, <, > ,' 를 각각 &quot;, &amp;, &lt;, &gt; &#39;로 변경한다.
  8785. * @example
  8786. var str = ">_<;;";
  8787. document.write( $S(str).escapeHTML() );
  8788. *
  8789. * // 결과 :
  8790. * // &amp;gt;_&amp;lt;;;
  8791. */
  8792. jindo.$S.prototype.escapeHTML = function() {
  8793. var entities = {'"':'quot','&':'amp','<':'lt','>':'gt','\'':'#39'};
  8794. var s = this._str.replace(/[<>&"']/g, function(m0){
  8795. return entities[m0]?'&'+entities[m0]+';':m0;
  8796. });
  8797. return jindo.$S(s);
  8798. };
  8799. /**
  8800. * stripTags 메서드는 문자열에서 XML 혹은 HTML 태그를 제거한다.
  8801. * @return {$S} XML 혹은 HTML 태그를 제거한 새로운 $S 객체
  8802. * @example
  8803. var str = "Meeting <b>people</b> is easy.";
  8804. document.write( $S(str).stripTags() );
  8805. *
  8806. * // 결과 :
  8807. * // Meeting people is easy.
  8808. */
  8809. jindo.$S.prototype.stripTags = function() {
  8810. return jindo.$S(this._str.replace(/<\/?(?:h[1-5]|[a-z]+(?:\:[a-z]+)?)[^>]*>/ig, ''));
  8811. };
  8812. /**
  8813. * times 메서드는 문자열을 매개변수로 지정한 숫자만큼 반복한다.
  8814. * @param {Number} nTimes 반복할 횟수
  8815. * @return {$S} 문자열을 지정한 숫자만큼 반복한 새로운 $S 객체
  8816. * @example
  8817. document.write ( $S("Abc").times(3) );
  8818. *
  8819. * // 결과 : AbcAbcAbc
  8820. */
  8821. jindo.$S.prototype.times = function(nTimes) {
  8822. var buf = [];
  8823. for(var i=0; i < nTimes; i++) {
  8824. buf[buf.length] = this._str;
  8825. }
  8826. return jindo.$S(buf.join(''));
  8827. };
  8828. /**
  8829. * unescapeHTML 메서드는 이스케이프(escape)된 HTML을 원래의 HTML로 리턴한다.
  8830. * @return {$S} 이스케이프된 HTML을 원래의 HTML로 변환한 새로운 $S 객체
  8831. * @remark &quot;, &amp;, &lt;, &gt; &#39;를 각각 ", &, <, >, ' 으로 변경한다.
  8832. * @see $S#escapeHTML
  8833. * @example
  8834. * var str = "&lt;a href=&quot;http://naver.com&quot;&gt;Naver&lt;/a&gt;";
  8835. * document.write( $S(str).unescapeHTML() );
  8836. *
  8837. * // 결과 :
  8838. * // <a href="http://naver.com">Naver</a>
  8839. */
  8840. jindo.$S.prototype.unescapeHTML = function() {
  8841. var entities = {'quot':'"','amp':'&','lt':'<','gt':'>','#39':'\''};
  8842. var s = this._str.replace(/&([a-z]+|#[0-9]+);/g, function(m0,m1){
  8843. return entities[m1]?entities[m1]:m0;
  8844. });
  8845. return jindo.$S(s);
  8846. };
  8847. /**
  8848. * escape 메서드는 문자열에 포함된 한글을 ASCII 문자열로 인코딩한다.
  8849. * @remark \r, \n, \t, ', ", non-ASCII 문자를 이스케이프 처리한다.
  8850. * @return {$S} 문자열을 이스케이프 처리한 새로운 $S 객체
  8851. * @see $S#escapeHTML
  8852. * @example
  8853. * var str = '가"\'나\\';
  8854. * document.write( $S(str).escape() );
  8855. *
  8856. * // 결과 :
  8857. * \uAC00\"\'\uB098\\
  8858. */
  8859. jindo.$S.prototype.escape = function() {
  8860. var s = this._str.replace(/([\u0080-\uFFFF]+)|[\n\r\t"'\\]/g, function(m0,m1,_){
  8861. if(m1) return escape(m1).replace(/%/g,'\\');
  8862. return (_={"\n":"\\n","\r":"\\r","\t":"\\t"})[m0]?_[m0]:"\\"+m0;
  8863. });
  8864. return jindo.$S(s);
  8865. };
  8866. /**
  8867. * bytes 메서드는 문자열의 실제 바이트(byte) 수를 리턴하고, 제한하려는 바이트(byte) 수를 지정하면 문자열을 해당 크기에 맞게 잘라낸다.(1.4.3 부터 charset사용 가능)
  8868. * @return 문자열의 바이트 수. 단, 첫번째 매개변수를 설정하면 자기 객체($S)를 리턴한다.
  8869. * @param {Number|Object} nBytes 맞출 문자열의 바이트(byte) 수 | charset을 지정할 때 사용
  8870. * @remark 문서의 charset을 해석해서 인코딩 방식에 따라 한글을 비롯한 유니코드 문자열의 바이트 수를 계산한다.
  8871. * @example
  8872. // 문서가 euc-kr 환경임을 가정합니다.
  8873. *
  8874. var str = "한글과 English가 섞인 문장...";
  8875. document.write( $S(str).bytes() );
  8876. *
  8877. * // 결과 :
  8878. * // 37
  8879. *
  8880. document.write( $S(str).bytes(20) );
  8881. *
  8882. * // 결과 :
  8883. * // 한글과 English가
  8884. *
  8885. document.write( $S(str).bytes({charset:'euc-kr',size:20}) );
  8886. *
  8887. * // 결과 :
  8888. * // 한글과 English가 섞
  8889. *
  8890. document.write( $S(str).bytes({charset:'euc-kr'}) );
  8891. *
  8892. * // 결과 :
  8893. * // 29
  8894. */
  8895. jindo.$S.prototype.bytes = function(vConfig) {
  8896. var code = 0, bytes = 0, i = 0, len = this._str.length;
  8897. var charset = ((document.charset || document.characterSet || document.defaultCharset)+"");
  8898. var cut,nBytes;
  8899. if (typeof vConfig == "undefined") {
  8900. cut = false;
  8901. }else if(vConfig.constructor == Number){
  8902. cut = true;
  8903. nBytes = vConfig;
  8904. }else if(vConfig.constructor == Object){
  8905. charset = vConfig.charset||charset;
  8906. nBytes = vConfig.size||false;
  8907. cut = !!nBytes;
  8908. }else{
  8909. cut = false;
  8910. }
  8911. if (charset.toLowerCase() == "utf-8") {
  8912. /*
  8913. 유니코드 문자열의 바이트 수는 위키피디아를 참고했다(http://ko.wikipedia.org/wiki/UTF-8).
  8914. */
  8915. for(i=0; i < len; i++) {
  8916. code = this._str.charCodeAt(i);
  8917. if (code < 128) {
  8918. bytes += 1;
  8919. }else if (code < 2048){
  8920. bytes += 2;
  8921. }else if (code < 65536){
  8922. bytes += 3;
  8923. }else{
  8924. bytes += 4;
  8925. }
  8926. if (cut && bytes > nBytes) {
  8927. this._str = this._str.substr(0,i);
  8928. break;
  8929. }
  8930. }
  8931. } else {
  8932. for(i=0; i < len; i++) {
  8933. bytes += (this._str.charCodeAt(i) > 128)?2:1;
  8934. if (cut && bytes > nBytes) {
  8935. this._str = this._str.substr(0,i);
  8936. break;
  8937. }
  8938. }
  8939. }
  8940. return cut?this:bytes;
  8941. };
  8942. /**
  8943. * parseString 메서드는 URL 쿼리 스트링을 객체로 파싱한다.
  8944. * @return {Object} 문자열을 파싱한 객체
  8945. * @example
  8946. * var str = "aa=first&bb=second";
  8947. * var obj = $S(str).parseString();
  8948. *
  8949. * // 결과 :
  8950. * // obj => { aa : "first", bb : "second" }
  8951. */
  8952. jindo.$S.prototype.parseString = function() {
  8953. if(this._str=="") return {};
  8954. var str = this._str.split(/&/g), pos, key, val, buf = {},isescape = false;
  8955. for(var i=0; i < str.length; i++) {
  8956. key = str[i].substring(0, pos=str[i].indexOf("=")), isescape = false;
  8957. try{
  8958. val = decodeURIComponent(str[i].substring(pos+1));
  8959. }catch(e){
  8960. isescape = true;
  8961. val = decodeURIComponent(unescape(str[i].substring(pos+1)));
  8962. }
  8963. if (key.substr(key.length-2,2) == "[]") {
  8964. key = key.substring(0, key.length-2);
  8965. if (typeof buf[key] == "undefined") buf[key] = [];
  8966. buf[key][buf[key].length] = isescape? escape(val) : val;;
  8967. } else {
  8968. buf[key] = isescape? escape(val) : val;
  8969. }
  8970. }
  8971. return buf;
  8972. };
  8973. /**
  8974. * escapeRegex 메서드는 정규식에 사용할 수 있도록 문자열을 이스케이프(escape) 한다.
  8975. * @since 1.2.0
  8976. * @return {String} 이스케이프된 문자열
  8977. * @example
  8978. var str = "Slash / is very important. Backslash \ is more important. +_+";
  8979. document.write( $S(str).escapeRegex() );
  8980. *
  8981. * // 결과 : \/ is very important\. Backslash \\ is more important\. \+_\+
  8982. */
  8983. jindo.$S.prototype.escapeRegex = function() {
  8984. var s = this._str;
  8985. var r = /([\?\.\*\+\-\/\(\)\{\}\[\]\:\!\^\$\\\|])/g;
  8986. return jindo.$S(s.replace(r, "\\$1"));
  8987. };
  8988. /**
  8989. * format 메서드는 문자열을 형식 문자열에 대입하여 새로운 문자열을 만든다. 형식 문자열은 %로 시작하며, 형식 문자열의 종류는 <a href="http://www.php.net/manual/en/function.sprintf.php">PHP</a>와 동일하다.
  8990. * @param {String} formatString 형식 문자열
  8991. * @return {String} 문자열을 형식 문자열에 대입하여 만든 새로운 문자열.
  8992. * @example
  8993. var str = $S("%4d년 %02d월 %02d일").format(2008, 2, 13);
  8994. *
  8995. * // 결과 :
  8996. * // str = "2008년 02월 13일"
  8997. var str = $S("패딩 %5s 빈공백").format("값");
  8998. *
  8999. * // 결과 :
  9000. * // str => "패딩 값 빈공백"
  9001. var str = $S("%b").format(10);
  9002. *
  9003. * // 결과 :
  9004. * // str => "1010"
  9005. var str = $S("%x").format(10);
  9006. *
  9007. * // 결과 :
  9008. * // str => "a"
  9009. var str = $S("%X").format(10);
  9010. *
  9011. * // 결과 :
  9012. * // str => "A"
  9013. * @see $S#times
  9014. */
  9015. jindo.$S.prototype.format = function() {
  9016. var args = arguments;
  9017. var idx = 0;
  9018. var s = this._str.replace(/%([ 0])?(-)?([1-9][0-9]*)?([bcdsoxX])/g, function(m0,m1,m2,m3,m4){
  9019. var a = args[idx++];
  9020. var ret = "", pad = "";
  9021. m3 = m3?+m3:0;
  9022. if (m4 == "s") {
  9023. ret = a+"";
  9024. } else if (" bcdoxX".indexOf(m4) > 0) {
  9025. if (typeof a != "number") return "";
  9026. ret = (m4 == "c")?String.fromCharCode(a):a.toString(({b:2,d:10,o:8,x:16,X:16})[m4]);
  9027. if (" X".indexOf(m4) > 0) ret = ret.toUpperCase();
  9028. }
  9029. if (ret.length < m3) pad = jindo.$S(m1||" ").times(m3 - ret.length).toString();
  9030. (m2 == '-')?(ret+=pad):(ret=pad+ret);
  9031. return ret;
  9032. });
  9033. return jindo.$S(s);
  9034. };
  9035. /**
  9036. * @fileOverview $Document 생성자 및 메서드를 정의한 파일
  9037. * @name document.js
  9038. */
  9039. /**
  9040. * $Document 객체를 생성하고 리턴한다.
  9041. * @class $Document 클래스는 문서와 관련된 여러가지 기능의 메서드를 제공한다
  9042. * @param {Document} doc 기능에 사용된 document 객체. 기본값은 현재 문서의 document.
  9043. * @constructor
  9044. * @author Hooriza
  9045. */
  9046. jindo.$Document = function (el) {
  9047. var cl = arguments.callee;
  9048. if (el instanceof cl) return el;
  9049. if (!(this instanceof cl)) return new cl(el);
  9050. this._doc = el || document;
  9051. this._docKey = this.renderingMode() == 'Standards' ? 'documentElement' : 'body';
  9052. };
  9053. /**
  9054. * $value 메서드는 원래의 document 객체를 리턴한다.
  9055. * @return {HTMLDocument} document 객체
  9056. */
  9057. jindo.$Document.prototype.$value = function() {
  9058. return this._doc;
  9059. };
  9060. /**
  9061. * scrollSize 메서드는 문서의 실제 가로, 세로 크기를 구한다
  9062. * @return {Object} 가로크기는 width, 세로크기는 height 라는 키값으로 리턴된다.
  9063. * @example
  9064. var size = $Document().scrollSize();
  9065. alert('가로 : ' + size.width + ' / 세로 : ' + size.height);
  9066. */
  9067. jindo.$Document.prototype.scrollSize = function() {
  9068. /*
  9069. webkit 계열에서는 Standard 모드라도 body를 사용해야 정상적인 scroll Size를 얻어온다.
  9070. */
  9071. var isWebkit = navigator.userAgent.indexOf("WebKit")>-1;
  9072. var oDoc = this._doc[isWebkit?'body':this._docKey];
  9073. return {
  9074. width : Math.max(oDoc.scrollWidth, oDoc.clientWidth),
  9075. height : Math.max(oDoc.scrollHeight, oDoc.clientHeight)
  9076. };
  9077. };
  9078. /**
  9079. * scrollPosition 메서드는 문서의 스크롤바 위치를 구한다
  9080. * @return {Object} 가로 위치는 left, 세로위치는 top 라는 키값으로 리턴된다.
  9081. * @example
  9082. var size = $Document().scrollPosition();
  9083. alert('가로 : ' + size.left + ' / 세로 : ' + size.top);
  9084. * @since 1.3.5
  9085. */
  9086. jindo.$Document.prototype.scrollPosition = function() {
  9087. /*
  9088. webkit 계열에서는 Standard 모드라도 body를 사용해야 정상적인 scroll Size를 얻어온다.
  9089. */
  9090. var isWebkit = navigator.userAgent.indexOf("WebKit")>-1;
  9091. var oDoc = this._doc[isWebkit?'body':this._docKey];
  9092. return {
  9093. left : oDoc.scrollLeft||window.pageXOffset||window.scrollX||0,
  9094. top : oDoc.scrollTop||window.pageYOffset||window.scrollY||0
  9095. };
  9096. };
  9097. /**
  9098. * clientSize 메서드는 스크롤바로 인해 가려진 부분을 제외한 문서 중 보이는 부분의 가로, 세로 크기를 구한다
  9099. * @return {Object} 가로크기는 width, 세로크기는 height 라는 키값으로 리턴된다
  9100. * @example
  9101. var size = $Document(document).clientSize();
  9102. alert('가로 : ' + size.width + ' / 세로 : ' + size.height);
  9103. */
  9104. jindo.$Document.prototype.clientSize = function() {
  9105. var agent = navigator.userAgent;
  9106. var oDoc = this._doc[this._docKey];
  9107. var isSafari = agent.indexOf("WebKit")>-1 && agent.indexOf("Chrome")==-1;
  9108. /*
  9109. 사파리의 경우 윈도우 리사이즈시에 clientWidth,clientHeight값이 정상적으로 나오지 않아서 window.innerWidth,innerHeight로 대체
  9110. */
  9111. return (isSafari)?{
  9112. width : window.innerWidth,
  9113. height : window.innerHeight
  9114. }:{
  9115. width : oDoc.clientWidth,
  9116. height : oDoc.clientHeight
  9117. };
  9118. };
  9119. /**
  9120. * renderingMode 메서드는 문서의 렌더링 방식을 얻는다
  9121. * @return {String} 렌더링 모드
  9122. * <dl>
  9123. * <dt>Standards</dt>
  9124. * <dd>표준 렌더링 모드</dd>
  9125. * <dt>Almost</dt>
  9126. * <dd>유사 표준 렌더링 모드 (IE 외의 브라우저에서 DTD 을 올바르게 지정하지 않았을때 리턴)</dd>
  9127. * <dt>Quirks</dt>
  9128. * <dd>비표준 렌더링 모드</dd>
  9129. * </dl>
  9130. * @example
  9131. var mode = $Document().renderingMode();
  9132. alert('렌더링 방식 : ' + mode);
  9133. */
  9134. jindo.$Document.prototype.renderingMode = function() {
  9135. var agent = navigator.userAgent;
  9136. var isIe = (typeof window.opera=="undefined" && agent.indexOf("MSIE")>-1);
  9137. var isSafari = (agent.indexOf("WebKit")>-1 && agent.indexOf("Chrome")<0 && navigator.vendor.indexOf("Apple")>-1);
  9138. var sRet;
  9139. if ('compatMode' in this._doc){
  9140. sRet = this._doc.compatMode == 'CSS1Compat' ? 'Standards' : (isIe ? 'Quirks' : 'Almost');
  9141. }else{
  9142. sRet = isSafari ? 'Standards' : 'Quirks';
  9143. }
  9144. return sRet;
  9145. };
  9146. /**
  9147. * 문서에서 주어진 selector를 만족시키는 요소의 배열을 반환한다. 만족하는 요소가 존재하지 않으면 빈 배열을 반환한다.
  9148. * @param {String} sSelector
  9149. * @return {Array} 조건을 만족하는 요소의 배열
  9150. */
  9151. jindo.$Document.prototype.queryAll = function(sSelector) {
  9152. return jindo.$$(sSelector, this._doc);
  9153. };
  9154. /**
  9155. * 문서에서 주어진 selector를 만족시키는 요소중 첫 번째 요소를 반환한다. 만족하는 요소가 존재하지 않으면 null을 반환한다.
  9156. * @param {String} sSelector
  9157. * @return {Element} 조건을 만족하는 요소중 첫번째 요소
  9158. */
  9159. jindo.$Document.prototype.query = function(sSelector) {
  9160. return jindo.$$.getSingle(sSelector, this._doc);
  9161. };
  9162. /**
  9163. * 문서에서 XPath 문법에 해당하는 모든 엘리먼트를 배열로 리턴한다.
  9164. * @remark 지원하는 문법에 제약 사항이 많으므로 특수한 경우에만 사용한다.
  9165. * @param {String} sXPath 엘리먼트의 위치를 지정한 XPath 값
  9166. * @return {Array} path에 해당하는 요소의 배열
  9167. * @example
  9168. var oDocument = $Document();
  9169. alert (oDocument.xpathAll("body/div/div").length);
  9170. */
  9171. jindo.$Document.prototype.xpathAll = function(sXPath) {
  9172. return jindo.$$.xpath(sXPath, this._doc);
  9173. };
  9174. /**
  9175. * @fileOverview $Form 생성자 및 메서드를 정의한 파일
  9176. * @name form.js
  9177. */
  9178. /**
  9179. * $Form 객체를 생성 및 리턴한다.
  9180. * @class $Form 클래스는 form 엘리먼트와 자식 엘리먼트를 제어하는 클래스이다.
  9181. * @param {Element | String} el 폼(form) 엘리먼트, 혹은 폼 엘리먼트의 id. 만약 동일한 id를 두 개 이상의 엘리먼트에서 사용하면 먼저 나오는 엘리먼트를 리턴한다.
  9182. * @constructor
  9183. * @author Hooriza
  9184. */
  9185. jindo.$Form = function (el) {
  9186. var cl = arguments.callee;
  9187. if (el instanceof cl) return el;
  9188. if (!(this instanceof cl)) return new cl(el);
  9189. el = jindo.$(el);
  9190. if (!el.tagName || el.tagName.toUpperCase() != 'FORM') throw new Error('The element should be a FORM element');
  9191. this._form = el;
  9192. }
  9193. /**
  9194. * $value 메서드는 랩핑된 원래 폼 엘리먼트를 리턴한다
  9195. * @return {HTMLElement} 폼 엘리먼트
  9196. * @example
  9197. var el = $('<form>');
  9198. var form = $Form(el);
  9199. alert(form.$value() === el); // true
  9200. */
  9201. jindo.$Form.prototype.$value = function() {
  9202. return this._form;
  9203. };
  9204. /**
  9205. * serialize 메서드는 특정 또는 전체 엘리멘트 입력요소를 문자열 형태로 리턴한다.
  9206. * @param {Mixed} Mixed 인수를 지정하지 않거나 인수를 하나 이상 설정할 수 있다.
  9207. * <ol>
  9208. * <li>매개 변수를 지정하지 않으면 폼 엘리먼트와 자식 엘리먼트의 모든 값을 쿼리 형태의 문자열로 리턴한다.</li>
  9209. * <li>매개 변수로 문자열을 설정하면 문자열과 일치하는 name 속성을 가지는 엘리먼트를 탐색하고 값을 리턴한다.</li>
  9210. * <li>매배 변수로 두 개 이상의 문자열을 설정하면, 문자열과 일치하는 name 속성을 가지는 엘리먼트를 모두 탐색하고 값을 쿼리 스트링 형태로 리턴한다. </li>
  9211. * </ol>
  9212. * @return {String} 쿼리 문자열 형태로 변환한 엘리먼트와 그 값.
  9213. * @example
  9214. <form id="TEST">
  9215. <input name="ONE" value="1" type="text" />
  9216. <input name="TWO" value="2" checked="checked" type="checkbox" />
  9217. <input name="THREE" value="3_1" type="radio" />
  9218. <input name="THREE" value="3_2" checked="checked" type="radio" />
  9219. <input name="THREE" value="3_3" type="radio" />
  9220. <select name="FOUR">
  9221. <option value="4_1">..</option>
  9222. <option value="4_2">..</option>
  9223. <option value="4_3" selected="selected">..</option>
  9224. </select>
  9225. </form>
  9226. <script type="text/javascript">
  9227. var form = $Form('TEST');
  9228. var allstr = form.serialize();
  9229. alert(allstr == 'ONE=1&TWO=2&THREE=3_2&FOUR=4_3'); // true
  9230. var str = form.serialize('ONE', 'THREE');
  9231. alert(str == 'ONE=1&THREE=3_2'); // true
  9232. </script>
  9233. */
  9234. jindo.$Form.prototype.serialize = function() {
  9235. var self = this;
  9236. var oRet = {};
  9237. var nLen = arguments.length;
  9238. var fpInsert = function(sKey) {
  9239. var sVal = self.value(sKey);
  9240. if (typeof sVal != 'undefined') oRet[sKey] = sVal;
  9241. };
  9242. if (nLen == 0) {
  9243. jindo.$A(this.element()).forEach(function(o) { if (o.name) fpInsert(o.name); });
  9244. }else{
  9245. for (var i = 0; i < nLen; i++) {
  9246. fpInsert(arguments[i]);
  9247. }
  9248. }
  9249. return jindo.$H(oRet).toQueryString();
  9250. };
  9251. /**
  9252. * element 메서드는 특정 또는 전체 입력요소를 리턴한다.
  9253. * @param {String} sKey 얻고자 하는 입력요소 엘리먼트의 name 문자열, 생략시에는 모든 입력요소들을 배열로 리턴한다.
  9254. * @return {HTMLElement | Array} 입력 요소 엘리먼트
  9255. */
  9256. jindo.$Form.prototype.element = function(sKey) {
  9257. if (arguments.length > 0)
  9258. return this._form[sKey];
  9259. return this._form.elements;
  9260. };
  9261. /**
  9262. * enable 메서드는 입력 요소의 활성화 여부를 얻거나 설정한다.
  9263. * @param {Mixed} mixed enable 메서드는 매개 변수의 개수나 종류에 따라 다르게 동작한다. 자세한 사용법은 다음과 같다.
  9264. * <ol>
  9265. * <li> 매개 변수로 문자열을 사용하면 문자열과 일치하는 name 속성을 가진 엘리먼트를 탐색한다. 엘리먼트를 발견했다면 엘리먼트의 활성화 여부를 리턴한다.</li>
  9266. * <li> 매개 변수로 문자열과 불린(Boolean)을 사용하면 문자열과 일치하는 name 속성을 가진 엘리먼트를 탐색한 후, 활성화 여부를 설정한다. </li>
  9267. * <li> 매개 변수로 객체를 사용할 수 있다. 객체는 속성 값과 name이 일치하는 엘리먼트를 탐색해서 값에 따라 활성화 여부를 설정한다. </li>
  9268. * </ol>
  9269. * @return {Boolean|$Form} 엘리먼트의 활성화 여부를 가져오거나 엘리먼트의 활성화 여부를 설정한 $Form 객체.
  9270. * @example
  9271. <form id="TEST">
  9272. <input name="ONE" disabled="disabled" type="text" />
  9273. <input name="TWO" type="checkbox" />
  9274. </form>
  9275. <script type="text/javascript">
  9276. var form = $Form('TEST');
  9277. var one_enabled = form.enable('ONE');
  9278. alert(one_enabled === false); // true
  9279. form.enable('TWO', false);
  9280. form.enable({
  9281. 'ONE' : true,
  9282. 'TWO' : false
  9283. });
  9284. </script>
  9285. */
  9286. jindo.$Form.prototype.enable = function() {
  9287. var sKey = arguments[0];
  9288. if (typeof sKey == 'object') {
  9289. var self = this;
  9290. jindo.$H(sKey).forEach(function(bFlag, sKey) { self.enable(sKey, bFlag); });
  9291. return this;
  9292. }
  9293. var aEls = this.element(sKey);
  9294. if (!aEls) return this;
  9295. aEls = aEls.nodeType == 1 ? [ aEls ] : aEls;
  9296. if (arguments.length < 2) {
  9297. var bEnabled = true;
  9298. jindo.$A(aEls).forEach(function(o) { if (o.disabled) {
  9299. bEnabled = false;
  9300. jindo.$A.Break();
  9301. }});
  9302. return bEnabled;
  9303. } else { // setter
  9304. var sFlag = arguments[1];
  9305. jindo.$A(aEls).forEach(function(o) { o.disabled = !sFlag; });
  9306. return this;
  9307. }
  9308. };
  9309. /**
  9310. * value 메서드는 폼 엘리먼트의 값을 얻거나 설정한다.
  9311. * @param {Mixed} Mixed 정확안 인수 정보는 다음과 같다.
  9312. * <ol>
  9313. * <li>매개 변수로 문자열을 설정하면 name 속성이 일치하는 앨리먼트를 탐색하고 값을 리턴한다</li>
  9314. * <li>매개 변수로 두 개의 문자열과 불린 값을 name 속성이 일치하는 앨리먼트를 탐색하고 값을 설정한다. </br> checkbox, radio, selectbox는 엘리먼트를 선택/선택 해제 한다.</li>
  9315. * <li>두 개 이상의 엘리먼트 값을 동시에 지정하고 싶으면 '엘리먼트 이름 : 엘리먼트 값'을 원소로 가지는 객체를 매개 변수로 설정한다.</li>
  9316. * </ol>
  9317. * @return {String|$Form} 인수로 엘리먼트만 지정했다면 지정한 엘리먼트의 값을, 인수로 폼 엘리먼와 엘리먼트의 값을 지정했다면 $Form 객체를 리턴한다.
  9318. * @example
  9319. <form id="TEST">
  9320. <input name="ONE" value="1" type="text" />
  9321. <input name="TWO" value="2" type="checkbox" />
  9322. </form>
  9323. <script type="text/javascript">
  9324. var form = $Form('TEST');
  9325. var one_value = form.value('ONE');
  9326. alert(one_value === '1'); // true
  9327. var two_value = form.value('TWO');
  9328. alert(two_value === undefined); // true
  9329. form.value('TWO', 2);
  9330. alert(two_value === '2'); // true
  9331. form.value({
  9332. 'ONE' : '1111',
  9333. 'TWO' : '2'
  9334. });
  9335. // form.value('ONE') -> 1111
  9336. // form.value('ONE') -> 2
  9337. </script>
  9338. */
  9339. jindo.$Form.prototype.value = function(sKey) {
  9340. if (typeof sKey == 'object') {
  9341. var self = this;
  9342. jindo.$H(sKey).forEach(function(bFlag, sKey) { self.value(sKey, bFlag); });
  9343. return this;
  9344. }
  9345. var aEls = this.element(sKey);
  9346. if (!aEls) throw new Error('엘리먼트는 존재하지 않습니다.');
  9347. aEls = aEls.nodeType == 1 ? [ aEls ] : aEls;
  9348. if (arguments.length > 1) { // setter
  9349. var sVal = arguments[1];
  9350. jindo.$A(aEls).forEach(function(o) {
  9351. switch (o.type) {
  9352. case 'radio':
  9353. o.checked = (o.value == sVal);
  9354. break;
  9355. case 'checkbox':
  9356. if(sVal.constructor == Array){
  9357. o.checked = jindo.$A(sVal).has(o.value);
  9358. }else{
  9359. o.checked = (o.value == sVal);
  9360. }
  9361. break;
  9362. case 'select-one':
  9363. var nIndex = -1;
  9364. for (var i = 0, len = o.options.length; i < len; i++){
  9365. if (o.options[i].value == sVal) nIndex = i;
  9366. }
  9367. o.selectedIndex = nIndex;
  9368. break;
  9369. case 'select-multiple':
  9370. var nIndex = -1;
  9371. if(sVal.constructor == Array){
  9372. var waVal = jindo.$A(sVal);
  9373. for (var i = 0, len = o.options.length; i < len; i++){
  9374. o.options[i].selected = waVal.has(o.options[i].value);
  9375. }
  9376. }else{
  9377. for (var i = 0, len = o.options.length; i < len; i++){
  9378. if (o.options[i].value == sVal) nIndex = i;
  9379. }
  9380. o.selectedIndex = nIndex;
  9381. }
  9382. break;
  9383. default:
  9384. o.value = sVal;
  9385. break;
  9386. }
  9387. });
  9388. return this;
  9389. }
  9390. // getter
  9391. var aRet = [];
  9392. jindo.$A(aEls).forEach(function(o) {
  9393. switch (o.type) {
  9394. case 'radio':
  9395. case 'checkbox':
  9396. if (o.checked) aRet.push(o.value);
  9397. break;
  9398. case 'select-one':
  9399. if (o.selectedIndex != -1) aRet.push(o.options[o.selectedIndex].value);
  9400. break;
  9401. case 'select-multiple':
  9402. if (o.selectedIndex != -1){
  9403. for (var i = 0, len = o.options.length; i < len; i++){
  9404. if (o.options[i].selected) aRet.push(o.options[i].value);
  9405. }
  9406. }
  9407. break;
  9408. default:
  9409. aRet.push(o.value);
  9410. break;
  9411. }
  9412. });
  9413. return aRet.length > 1 ? aRet : aRet[0];
  9414. };
  9415. /**
  9416. * submit 메서드는 폼의 데이터를 웹으로 제출(submit) 한다.
  9417. * @param {String} sTargetName 제출할 폼이 있는 윈도우의 이름. sTargetName을 생략하면 기본 타겟
  9418. * @param {String} fValidation 제출할 폼의 밸리데이션 함수. form 요소를 인자로 받는다.
  9419. * @return {$Form} 데이터를 제출한 $Form 객체.
  9420. * @example
  9421. var form = $Form(el);
  9422. form.submit();
  9423. form.submit('foo');
  9424. */
  9425. jindo.$Form.prototype.submit = function(sTargetName, fValidation) {
  9426. var sOrgTarget = null;
  9427. if (typeof sTargetName == 'string') {
  9428. sOrgTarget = this._form.target;
  9429. this._form.target = sTargetName;
  9430. }
  9431. if(typeof sTargetName == 'function') fValidation = sTargetName;
  9432. if(typeof fValidation != 'undefined'){
  9433. if(!fValidation(this._form)) return this;
  9434. }
  9435. this._form.submit();
  9436. if (sOrgTarget !== null)
  9437. this._form.target = sOrgTarget;
  9438. return this;
  9439. };
  9440. /**
  9441. * reset 메서드는 폼을 초기화(reset)한다.
  9442. * @param {String} fValidation 제출할 폼의 밸리데이션 함수. form 요소를 인자로 받는다.
  9443. * @return {$Form} 초기화한 $Form 객체.
  9444. * @example
  9445. var form = $Form(el);
  9446. form.reset();
  9447. */
  9448. jindo.$Form.prototype.reset = function(fValidation) {
  9449. if(typeof fValidation != 'undefined'){
  9450. if(!fValidation(this._form)) return this;
  9451. }
  9452. this._form.reset();
  9453. return this;
  9454. };
  9455. /**
  9456. * @fileOverview $Template의 생성자 및 메서드를 정의한 파일
  9457. * @name template.js
  9458. */
  9459. /**
  9460. * $Template 객체를 생성한다.
  9461. * @class $Template 클래스는 템플릿을 해석하여 템플릿 문자열에 동적으로 문자를 삽입한다.
  9462. * @constructor
  9463. * @author Kim, Taegon
  9464. *
  9465. * @param {String | HTML Element | $Template} str
  9466. * <br>
  9467. * $Template 은 문자열, HTML 엘리먼트, 혹은 $Template 을 인자로 지정할 수 있다.<br>
  9468. * <br>
  9469. * 인자가 문자열이면 두 가지 방식으로 동작한다.<br>
  9470. * 만일 문자열이 HTML 엘리먼트의 id 라면 HTML 엘리먼트의 innerHTML 을 템플릿으로 사용한다.<br>
  9471. * 만약 일반 문자열이라면 문자열 자체를 템플릿으로 사용한다.<br>
  9472. * <br>
  9473. * 인자가 HTML 엘리먼트이면 TEXTAREA 와 SCRIPT 만이 사용 가능하다.<br>
  9474. * HTML 엘리먼트 value 값의 문자열을 템 플릿으로 사용하며, value 값이 없는 경우 HTML 엘리먼트의 innerHTML을 템플릿으로 사용한다.<br>
  9475. * <br>
  9476. * 인자가 $Template 이면 전달된 인자를 그대로 반환하며 인자를 생략하면 "" 를 템플릿으로 사용한다.
  9477. * @return {$Template} 생성된 $Template 객체
  9478. *
  9479. * @remark 인자가 SCRIPT인 경우의 type은 반드시 "text/template"으로 지정해야 한다.
  9480. *
  9481. * @example
  9482. // 인자가 일반 문자열인 경우
  9483. var tpl = $Template("{=service} : {=url}");
  9484. *
  9485. * @example
  9486. <textarea id="tpl1">
  9487. {=service} : {=url}
  9488. &lt;/textarea&gt;
  9489. // 같은 TEXTAREA 엘리먼트를 템플릿으로 사용한다
  9490. var template1 = $Template("tpl1"); // 인자가 HTML 엘리먼트의 id 아이디
  9491. var template2 = $Template($("tpl1")); // 인자가 TEXTAREA 엘리먼트인 경우
  9492. </script>
  9493. *
  9494. * @example
  9495. <script type="text/template" id="tpl2">
  9496. {=service} : {=url}
  9497. </script>
  9498. // 같은 SCRIPT 엘리먼트를 템플릿으로 사용한다
  9499. var template1 = $Template("tpl2"); // 인자가 HTML 엘리먼트의 id 아이디
  9500. var template2 = $Template($("tpl2")); // 인자가 SCRIPT 엘리먼트인 경우
  9501. */
  9502. jindo.$Template = function(str) {
  9503. var obj = null, tag = "";
  9504. var cl = arguments.callee;
  9505. if (str instanceof cl) return str;
  9506. if (!(this instanceof cl)) return new cl(str);
  9507. if(typeof str == "undefined") {
  9508. str = "";
  9509. }else if( (obj=document.getElementById(str)||str) && obj.tagName && (tag=obj.tagName.toUpperCase()) && (tag == "TEXTAREA" || (tag == "SCRIPT" && obj.getAttribute("type") == "text/template")) ) {
  9510. str = (obj.value||obj.innerHTML).replace(/^\s+|\s+$/g,"");
  9511. }
  9512. this._str = str+"";
  9513. }
  9514. jindo.$Template.splitter = /(?!\\)[\{\}]/g;
  9515. jindo.$Template.pattern = /^(?:if (.+)|elseif (.+)|for (?:(.+)\:)?(.+) in (.+)|(else)|\/(if|for)|=(.+)|js (.+)|set (.+))$/;
  9516. /**
  9517. * 템플릿을 해석하고 데이터를 적용하여 새로운 문자열을 생성한다.<br>
  9518. * <br>
  9519. * 템플릿을 해석할 때에<br>
  9520. * 템플릿 내에 패턴이 있으면 패턴에 따라 템플릿을 해석하는 방법이 다르다.(각 패턴의 해석은 예제를 참고한다)<br>
  9521. * 템플릿 내에 패턴이 없으면 단순 문자열 치환으로 처리한다.
  9522. * @param {Object} data 템플릿에 들어갈 데이터를 가지는 객체<br>
  9523. * 템플릿에 데이터를 적용할 부분은 객체의 프로퍼티(property) 이름으로 찾는다.
  9524. * @return {String} 템플릿을 해석하고 데이터를 적용한 새로운 문자열
  9525. *
  9526. * @example
  9527. // 단순 문자열 치환
  9528. // {=value} 부분의 값을 치환한다.
  9529. var tpl = $Template("Value1 : {=val1}, Value2 : {=val2}")
  9530. var data = { val1: "first value", val2: "second value" };
  9531. document.write( tpl.process(data) );
  9532. // 결과
  9533. // Value1 : first value, Value2 : second value
  9534. * @example
  9535. // if/elseif/else : 조건문
  9536. // 템플릿을 해석할 때 조건문을 판단하여 처리한다.
  9537. var tpl= $Template("{if num >= 7}7보다 크거나 같다.{elseif num <= 5}5보다 작거나 같다.{else}아마 6?{/if}");
  9538. var data = { num: 5 };
  9539. document.write( tpl.process(data) );
  9540. // 결과
  9541. // 5보다 작거나 같다.
  9542. * @example
  9543. // set : 임시 변수 사용
  9544. // set val=1 로 설정하는 경우 {=val} 부분에 1을 대입한다.
  9545. var tpl = $Template("{set val3=val1}Value1 : {=val1}, Value2 : {=val2}, Value3 : {=val3}")
  9546. var data = { val1: "first value", val2: "second value" };
  9547. document.write( tpl.process(data) );
  9548. // 결과
  9549. // Value1 : first value, Value2 : second value, Value3 : first value
  9550. * @example
  9551. // js : JavaScript 사용
  9552. // 템플릿을 해석할 때 해당 JavaScript를 실행한다.
  9553. var tpl = $Template("Value1 : {js $S(=val1).bytes()}, Value2 : {=val2}")
  9554. var data = { val1: "first value", val2: "second value" };
  9555. document.write( tpl.process(data) );
  9556. // 결과
  9557. // Value1 : 11, Value2 : second value
  9558. * @example
  9559. // for in : 반복문(인덱스를 사용하지 않는 경우)
  9560. var tpl = $Template("<h1>포탈 사이트</h1>\n<ul>{for site in portals}\n<li><a href='{=site.url}'>{=site.name}</a></li>{/for}\n</ul>");
  9561. var data = { portals: [
  9562. { name: "네이버", url : "http://www.naver.com" },
  9563. { name: "다음", url : "http://www.daum.net" },
  9564. { name: "야후", url : "http://www.yahoo.co.kr" }
  9565. ]};
  9566. document.write( tpl.process(data) );
  9567. // 결과
  9568. //<h1>포탈 사이트</h1>
  9569. //<ul>
  9570. //<li><a href='http://www.naver.com'>네이버</a></li>
  9571. //<li><a href='http://www.daum.net'>다음</a></li>
  9572. //<li><a href='http://www.yahoo.co.kr'>야후</a></li>
  9573. //</ul>
  9574. * @example
  9575. // for: 반복문(인덱스를 사용하는 경우)
  9576. var tpl = $Template("{for num:word in numbers}{=word}({=num}){/for}");
  9577. var data = { numbers: ["zero", "one", "two", "three"] };
  9578. document.write( tpl.process(data) );
  9579. // 결과
  9580. // zero(0) one(1) two(2) three(3)
  9581. */
  9582. jindo.$Template.prototype.process = function(data) {
  9583. var key = "\x01";
  9584. var leftBrace = "\x02";
  9585. var rightBrace = "\x03";
  9586. var tpl = (" "+this._str+" ").replace(/\\{/g,leftBrace).replace(/\\}/g,rightBrace).replace(/(?!\\)\}\{/g, "}"+key+"{").split(jindo.$Template.splitter), i = tpl.length;
  9587. var map = {'"':'\\"','\\':'\\\\','\n':'\\n','\r':'\\r','\t':'\\t','\f':'\\f'};
  9588. var reg = [/(["'](?:(?:\\.)+|[^\\["']+)*["']|[a-zA-Z_][\w\.]*)/g, /[\n\r\t\f"\\]/g, /^\s+/, /\s+$/, /#/g];
  9589. var cb = [function(m){ return (m.substring(0,1)=='"' || m.substring(0,1)=='\''||m=='null')?m:"d."+m; }, function(m){return map[m]||m}, "", ""];
  9590. var stm = [];
  9591. var lev = 0;
  9592. // remove " "
  9593. tpl[0] = tpl[0].substr(1);
  9594. tpl[i-1] = tpl[i-1].substr(0, tpl[i-1].length-1);
  9595. // no pattern
  9596. if(i<2) return tpl[0];
  9597. tpl = jindo.$A(tpl).reverse().$value();
  9598. var delete_info;
  9599. while(i--) {
  9600. if(i%2) {
  9601. tpl[i] = tpl[i].replace(jindo.$Template.pattern, function(){
  9602. var m = arguments;
  9603. // set
  9604. if (m[10]) {
  9605. return m[10].replace(/(\w+)(?:\s*)=(?:\s*)(?:([a-zA-Z0-9_]+)|(.+))$/g, function(){
  9606. var mm = arguments;
  9607. var str = "d."+mm[1]+"=";
  9608. if(mm[2]){
  9609. str+="d."+mm[2];
  9610. }else {
  9611. str += mm[3].replace( /(=(?:[a-zA-Z_][\w\.]*)+)/g,
  9612. function(m){ return (m.substring(0,1)=='=')?"d."+m.replace('=','') : m; }
  9613. );
  9614. }
  9615. return str;
  9616. }) + ";";
  9617. }
  9618. // js
  9619. if(m[9]) {
  9620. return 's[i++]=' + m[9].replace( /(=(?:[a-zA-Z_][\w\.]*)+)/g,
  9621. function(m){ return (m.substring(0,1)=='=')?"d."+m.replace('=','') : m; }
  9622. )+';';
  9623. }
  9624. // variables
  9625. if(m[8]) return 's[i++]= d.'+m[8]+';';
  9626. // if
  9627. if(m[1]) {
  9628. return 'if('+m[1].replace(reg[0],cb[0]).replace(/d\.(typeof) /,'$1 ').replace(/ d\.(instanceof) d\./,' $1 ')+'){';
  9629. }
  9630. // else if
  9631. if(m[2]) return '}else if('+m[2].replace(reg[0],cb[0]).replace(/d\.(typeof) /,'$1 ').replace(/ d\.(instanceof) d\./,' $1 ')+'){';
  9632. // for loop
  9633. if(m[5]) {
  9634. delete_info = m[4];
  9635. var _aStr = [];
  9636. _aStr.push('var t#=d.'+m[5]+'||{},p#=isArray(t#),i#=0;');
  9637. _aStr.push('for(var x# in t#){');
  9638. _aStr.push('if(!t#.hasOwnProperty(x#)){continue;}');
  9639. _aStr.push(' if( (p# && isNaN(i#=parseInt(x#,10))) || (!p# && !t#.propertyIsEnumerable(x#)) ) continue;');
  9640. _aStr.push(' d.'+m[4]+'=t#[x#];');
  9641. _aStr.push(m[3]?'d.'+m[3]+'=p#?i#:x#;':'');
  9642. return _aStr.join("").replace(reg[4], lev++ );
  9643. }
  9644. // else
  9645. if(m[6]) return '}else{';
  9646. // end if, end for
  9647. if(m[7]) {
  9648. if(m[7]=="for"){
  9649. return "delete d."+delete_info+"; };";
  9650. }else{
  9651. return '};';
  9652. }
  9653. }
  9654. return m[0];
  9655. });
  9656. }else if(tpl[i] == key) {
  9657. tpl[i] = "";
  9658. }else if(tpl[i]){
  9659. tpl[i] = 's[i++]="'+tpl[i].replace(reg[1],cb[1])+'";';
  9660. }
  9661. }
  9662. tpl = jindo.$A(tpl).reverse().$value().join('').replace(new RegExp(leftBrace,'g'),"{").replace(new RegExp(rightBrace,'g'),"}");
  9663. var _aStr = [];
  9664. _aStr.push('var s=[],i=0;');
  9665. _aStr.push('function isArray(o){ return Object.prototype.toString.call(o) == "[object Array]" };');
  9666. _aStr.push(tpl);
  9667. _aStr.push('return s.join("");');
  9668. tpl = eval("false||function(d){"+_aStr.join("")+"}");
  9669. tpl = tpl(data);
  9670. //(new Function("d",_aStr.join("")))(data);
  9671. return tpl;
  9672. };
  9673. /**
  9674. * @fileOverview $Date의 생성자 및 메서드를 정의한 파일
  9675. * @name date.js
  9676. */
  9677. /**
  9678. * $Date 객체를 생성하고 리턴한다.
  9679. * ISO문자를 넣은 경우 jindo.$Date.utc을 기반하여 계산된다.
  9680. * @extends core
  9681. * @class $Date 클래스는 날짜를 처리하기 위한 Date 타입의 레퍼(Wrapper) 클래스이다.
  9682. * @constructor
  9683. * @author Kim, Taegon
  9684. * @example
  9685. $Date();
  9686. $Date(milliseconds);
  9687. $Date(dateString);
  9688. //1.4.6 이후 부터 달까지만 넣어도 $Date사용 가능하여 빈 값은 1로 셋팅.
  9689. $Date(year, month, [date, [hours, [minitues, [seconds, [milliseconds]]]]]);
  9690. $Date(2010,6);//이러고 하면 $Date(2010,6,1,1,1,1,1); 와 같음.
  9691. */
  9692. jindo.$Date = function(src) {
  9693. var a=arguments,t="";
  9694. var cl=arguments.callee;
  9695. if (src && src instanceof cl) return src;
  9696. if (!(this instanceof cl)) return new cl(a[0],a[1],a[2],a[3],a[4],a[5],a[6]);
  9697. if ((t=typeof src) == "string") {
  9698. /*
  9699. iso string일때
  9700. */
  9701. if (/(\d\d\d\d)(?:-?(\d\d)(?:-?(\d\d)))/.test(src)) {
  9702. try{
  9703. this._date = new Date(src);
  9704. if (!this._date.toISOString) {
  9705. this._date = jindo.$Date.makeISO(src);
  9706. }else if(this._date.toISOString() == "Invalid Date"){
  9707. this._date = jindo.$Date.makeISO(src);
  9708. }
  9709. }catch(e){
  9710. this._date = jindo.$Date.makeISO(src);
  9711. }
  9712. }else{
  9713. this._date = cl.parse(src);
  9714. }
  9715. } else if (t == "number") {
  9716. if (typeof a[1] == "undefined") {
  9717. /*
  9718. 하나의 숫지인 경우는 밀리 세켄드로 계산함.
  9719. */
  9720. this._date = new Date(src);
  9721. }else{
  9722. for(var i = 0 ; i < 7 ; i++){
  9723. if(typeof a[i] != "number"){
  9724. a[i] = 1;
  9725. }
  9726. }
  9727. this._date = new Date(a[0],a[1],a[2],a[3],a[4],a[5],a[6]);
  9728. }
  9729. } else if (t == "object" && src.constructor == Date) {
  9730. (this._date = new Date).setTime(src.getTime());
  9731. this._date.setMilliseconds(src.getMilliseconds());
  9732. } else {
  9733. this._date = new Date;
  9734. }
  9735. this._names = {};
  9736. for(var i in jindo.$Date.names){
  9737. if(jindo.$Date.names.hasOwnProperty(i))
  9738. this._names[i] = jindo.$Date.names[i];
  9739. }
  9740. }
  9741. jindo.$Date.makeISO = function(src){
  9742. var match = src.match(/(\d\d\d\d)(?:-?(\d\d)(?:-?(\d\d)(?:[T ](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|(?:([-+])(\d\d)(?::?(\d\d))?)?)?)?)?)?/);
  9743. var hour = parseInt(match[4]||0,10);
  9744. var min = parseInt(match[5]||0,10);
  9745. if (match[8] == "Z") {
  9746. hour += jindo.$Date.utc;
  9747. }else if(match[9] == "+" || match[9] == "-"){
  9748. hour += (jindo.$Date.utc - parseInt(match[9]+match[10],10));
  9749. min += parseInt(match[9] + match[11],10);
  9750. }
  9751. return new Date(match[1]||0,parseInt(match[2]||0,10)-1,match[3]||0,hour ,min ,match[6]||0,match[7]||0);
  9752. }
  9753. /**
  9754. * names 속성은 $Date에서 사용할 달, 요일, 오전/오후의 이름을 문자열로 저장한다. s_ 를 접두어로 가지는 이름들은 약어(abbreviation)이다.
  9755. */
  9756. jindo.$Date.names = {
  9757. month : ["January","Febrary","March","April","May","June","July","August","September","October","Novermber","December"],
  9758. s_month : ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
  9759. day : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
  9760. s_day : ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],
  9761. ampm : ["AM", "PM"]
  9762. };
  9763. /**
  9764. * UTC는 <a href="http://ko.wikipedia.org/wiki/UTC">협정 세계시간</a>으로 한국을 기준으로 기본 값이 +9시간이다.
  9765. * @example
  9766. jindo.$Date.utc = -10; 을 하면 하와이를 기준으로 계산된다.
  9767. */
  9768. jindo.$Date.utc = 9;
  9769. /**
  9770. * now 메서드는 현재 시간을 밀리초 단위의 정수로 리턴한다.
  9771. * @return {Number} 밀리초 단위의 정수인 현재 시간
  9772. */
  9773. jindo.$Date.now = function() {
  9774. return Date.now();
  9775. };
  9776. /**
  9777. * names속성을 셋팅 혹은 가져 온다.(1.4.1 추가)
  9778. * @param {Object} oNames
  9779. */
  9780. jindo.$Date.prototype.name = function(oNames){
  9781. if(arguments.length){
  9782. for(var i in oNames){
  9783. if(oNames.hasOwnProperty(i))
  9784. this._names[i] = oNames[i];
  9785. }
  9786. }else{
  9787. return this._names;
  9788. }
  9789. }
  9790. /**
  9791. * parse 메서드는 인수로 지정한 문자열을 파싱하여 문자열의 형식에 맞는 Date 객체를 생성한다.
  9792. * @param {String} strDate 날짜, 혹은 시간 형식을 지정한 파싱 대상 문자열
  9793. * @return {Object} Date 객체.
  9794. */
  9795. jindo.$Date.parse = function(strDate) {
  9796. return new Date(Date.parse(strDate));
  9797. };
  9798. /**
  9799. * $value 메서드는 $Date가 감싸고 있던 원본 Date 객체를 반환한다.
  9800. * @returns {Object} Date 객체
  9801. */
  9802. jindo.$Date.prototype.$value = function(){
  9803. return this._date;
  9804. };
  9805. /**
  9806. * format 메서드는 $Date 객체가 저장하고 있는 시간을 인수로 지정한 형식 문자열에 맞추어 변환한다. 형식 문자열은 PHP의 date 함수와 동일하게 사용한다.
  9807. <table>
  9808. <caption>날짜</caption>
  9809. <thead>
  9810. <tr>
  9811. <th scope="col">문자</th>
  9812. <th scope="col">설명</th>
  9813. <th scope="col">기타</th>
  9814. </tr>
  9815. </thead>
  9816. <tbody>
  9817. <tr>
  9818. <td>d</td>
  9819. <td>두자리 날짜</td>
  9820. <td>01 ~ 31</td>
  9821. </tr>
  9822. <tr>
  9823. <td>j</td>
  9824. <td>0 없는 날짜</td>
  9825. <td>1 ~ 31</td>
  9826. </tr>
  9827. <tr>
  9828. <td>l (소문자L)</td>
  9829. <td>주의 전체 날짜</td>
  9830. <td>$Date.names.day에 지정되는 날짜</td>
  9831. </tr>
  9832. <tr>
  9833. <td>D</td>
  9834. <td>요약된 날짜</td>
  9835. <td>$Date.names.s_day에 지정된 날짜</td>
  9836. </tr>
  9837. <tr>
  9838. <td>w</td>
  9839. <td>그 주의 몇번째 일</td>
  9840. <td>0(일) ~ 6(토)</td>
  9841. </tr>
  9842. <tr>
  9843. <td>N</td>
  9844. <td>ISO-8601 주의 몇번째 일</td>
  9845. <td>1(월) ~ 7(일)</td>
  9846. </tr>
  9847. <tr>
  9848. <td>S</td>
  9849. <td>2글자, 서수형식의 표현(1st, 2nd)</td>
  9850. <td>st, nd, rd, th</td>
  9851. </tr>
  9852. <tr>
  9853. <td>z</td>
  9854. <td>해당 년도의 몇번째 일(0부터)</td>
  9855. <td>0 ~ 365</td>
  9856. </tr>
  9857. </tbody>
  9858. </table>
  9859. <table>
  9860. <caption>월</caption>
  9861. <thead>
  9862. <tr>
  9863. <th scope="col">문자</th>
  9864. <th scope="col">설명</th>
  9865. <th scope="col">기타</th>
  9866. </tr>
  9867. </thead>
  9868. <tbody>
  9869. <tr>
  9870. <td>m</td>
  9871. <td>두자리 고정으로 월</td>
  9872. <td>01 ~ 12</td>
  9873. </tr>
  9874. <tr>
  9875. <td>n</td>
  9876. <td>앞에 0제외 월</td>
  9877. <td>1 ~ 12</td>
  9878. </tr>
  9879. </tbody>
  9880. </table>
  9881. <table>
  9882. <caption>년</caption>
  9883. <thead>
  9884. <tr>
  9885. <th scope="col">문자</th>
  9886. <th scope="col">설명</th>
  9887. <th scope="col">기타</th>
  9888. </tr>
  9889. </thead>
  9890. <tbody>
  9891. <tr>
  9892. <td>L</td>
  9893. <td>윤년 여부</td>
  9894. <td>true, false</td>
  9895. </tr>
  9896. <tr>
  9897. <td>o</td>
  9898. <td>4자리 연도</td>
  9899. <td>2010</td>
  9900. </tr>
  9901. <tr>
  9902. <td>Y</td>
  9903. <td>o와 같음.</td>
  9904. <td>2010</td>
  9905. </tr>
  9906. <tr>
  9907. <td>y</td>
  9908. <td>2자리 연도</td>
  9909. <td>10</td>
  9910. </tr>
  9911. </tbody>
  9912. </table>
  9913. <table>
  9914. <caption>시</caption>
  9915. <thead>
  9916. <tr>
  9917. <th scope="col">문자</th>
  9918. <th scope="col">설명</th>
  9919. <th scope="col">기타</th>
  9920. </tr>
  9921. </thead>
  9922. <tbody>
  9923. <tr>
  9924. <td>a</td>
  9925. <td>소문자 오전, 오후</td>
  9926. <td>am,pm</td>
  9927. </tr>
  9928. <tr>
  9929. <td>A</td>
  9930. <td>대문자 오전,오후</td>
  9931. <td>AM,PM</td>
  9932. </tr>
  9933. <tr>
  9934. <td>g</td>
  9935. <td>(12시간 주기)0없는 두자리 시간.</td>
  9936. <td>1~12</td>
  9937. </tr>
  9938. <tr>
  9939. <td>G</td>
  9940. <td>(24시간 주기)0없는 두자리 시간.</td>
  9941. <td>0~24</td>
  9942. </tr>
  9943. <tr>
  9944. <td>h</td>
  9945. <td>(12시간 주기)0있는 두자리 시간.</td>
  9946. <td>01~12</td>
  9947. </tr>
  9948. <tr>
  9949. <td>H</td>
  9950. <td>(24시간 주기)0있는 두자리 시간.</td>
  9951. <td>00~24</td>
  9952. </tr>
  9953. <tr>
  9954. <td>i</td>
  9955. <td>0포함 2자리 분.</td>
  9956. <td>00~59</td>
  9957. </tr>
  9958. <tr>
  9959. <td>s</td>
  9960. <td>0포함 2자리 초</td>
  9961. <td>00~59</td>
  9962. </tr>
  9963. <tr>
  9964. <td>u</td>
  9965. <td>microseconds</td>
  9966. <td>654321</td>
  9967. </tr>
  9968. </tbody>
  9969. </table>
  9970. <table>
  9971. <caption>기타</caption>
  9972. <thead>
  9973. <tr>
  9974. <th scope="col">문자</th>
  9975. <th scope="col">설명</th>
  9976. <th scope="col">기타</th>
  9977. </tr>
  9978. </thead>
  9979. <tbody>
  9980. <tr>
  9981. <td>U</td>
  9982. <td>Unix Time(1970 00:00:00 GMT) </td>
  9983. <td></td>
  9984. </tr>
  9985. </tbody>
  9986. </table>
  9987. * @param {Date} strFormat 형식 문자열
  9988. * @returns {String} 시간을 형식 문자열에 맞추어 변환한 문자열.
  9989. * @example
  9990. var oDate = $Date("Jun 17 2009 12:02:54");
  9991. oDate.format("Y.m.d(D) A H:i") => "2009.06.17(Wed) PM 12:02"
  9992. */
  9993. jindo.$Date.prototype.format = function(strFormat){
  9994. var o = {};
  9995. var d = this._date;
  9996. var name = this.name();
  9997. var self = this;
  9998. return (strFormat||"").replace(/[a-z]/ig, function callback(m){
  9999. if (typeof o[m] != "undefined") return o[m];
  10000. switch(m) {
  10001. case"d":
  10002. case"j":
  10003. o.j = d.getDate();
  10004. o.d = (o.j>9?"":"0")+o.j;
  10005. return o[m];
  10006. case"l":
  10007. case"D":
  10008. case"w":
  10009. case"N":
  10010. o.w = d.getDay();
  10011. o.N = o.w?o.w:7;
  10012. o.D = name.s_day[o.w];
  10013. o.l = name.day[o.w];
  10014. return o[m];
  10015. case"S":
  10016. return (!!(o.S=["st","nd","rd"][d.getDate()]))?o.S:(o.S="th");
  10017. case"z":
  10018. o.z = Math.floor((d.getTime() - (new Date(d.getFullYear(),0,1)).getTime())/(3600*24*1000));
  10019. return o.z;
  10020. case"m":
  10021. case"n":
  10022. o.n = d.getMonth()+1;
  10023. o.m = (o.n>9?"":"0")+o.n;
  10024. return o[m];
  10025. case"L":
  10026. o.L = self.isLeapYear();
  10027. return o.L;
  10028. case"o":
  10029. case"Y":
  10030. case"y":
  10031. o.o = o.Y = d.getFullYear();
  10032. o.y = (o.o+"").substr(2);
  10033. return o[m];
  10034. case"a":
  10035. case"A":
  10036. case"g":
  10037. case"G":
  10038. case"h":
  10039. case"H":
  10040. o.G = d.getHours();
  10041. o.g = (o.g=o.G%12)?o.g:12;
  10042. o.A = o.G<12?name.ampm[0]:name.ampm[1];
  10043. o.a = o.A.toLowerCase();
  10044. o.H = (o.G>9?"":"0")+o.G;
  10045. o.h = (o.g>9?"":"0")+o.g;
  10046. return o[m];
  10047. case"i":
  10048. o.i = (((o.i=d.getMinutes())>9)?"":"0")+o.i;
  10049. return o.i;
  10050. case"s":
  10051. o.s = (((o.s=d.getSeconds())>9)?"":"0")+o.s;
  10052. return o.s;
  10053. case"u":
  10054. o.u = d.getMilliseconds();
  10055. return o.u;
  10056. case"U":
  10057. o.U = self.time();
  10058. return o.U;
  10059. default:
  10060. return m;
  10061. }
  10062. });
  10063. };
  10064. /**
  10065. * time 메서드는 GMT 1970/01/01 00:00:00을 기준으로 경과한 시간을 설정하거나 가져온다.
  10066. * @param {Number} nTime 밀리 초 단위의 시간 값.
  10067. * @return {$Date | Number} 인수를 지정했다면 GMT 1970/01/01 00:00:00 에서 부터 인수만큼 지난 시간을 설정한 $DAte 객체. 인수를 지정하지 않았다면 GMT 1970/01/01 00:00:00에서 부터 $Date 객체에 지정된 시각까지 경과한 시간(밀리 초).
  10068. */
  10069. jindo.$Date.prototype.time = function(nTime) {
  10070. if (typeof nTime == "number") {
  10071. this._date.setTime(nTime);
  10072. return this;
  10073. }
  10074. return this._date.getTime();
  10075. };
  10076. /**
  10077. * year 메서드는 년도를 설정하거나 가져온다.
  10078. * @param {Number} nYear 설정할 년도값
  10079. * @return {$Date | Number} 인수를 지정하였다면 새로 년도 값을 설정한 $Date 객체. 인수를 지정하지 않았다면 $Date 객체가 지정하고 있는 시각의 년도를 리턴한다.
  10080. */
  10081. jindo.$Date.prototype.year = function(nYear) {
  10082. if (typeof nYear == "number") {
  10083. this._date.setFullYear(nYear);
  10084. return this;
  10085. }
  10086. return this._date.getFullYear();
  10087. };
  10088. /**
  10089. * month 메서드는 달을 설정하거나 가져온다.
  10090. * @param {Number} nMon 설정할 달의 값
  10091. * @return {$Date | Number} 인수를 지정하였다면 새로 달을 설정한 $Date 객체. 인수를 지정하지 않았다면 $Date 객체가 지정하고 있는 시각의 달을 리턴한다.
  10092. * @remark 리턴 값의 범위는 0(1월)에서 11(12월)이다.
  10093. */
  10094. jindo.$Date.prototype.month = function(nMon) {
  10095. if (typeof nMon == "number") {
  10096. this._date.setMonth(nMon);
  10097. return this;
  10098. }
  10099. return this._date.getMonth();
  10100. };
  10101. /**
  10102. * date 메서드는 날짜를 설정하거나 가져온다.
  10103. * @param {nDate} nDate 설정할 날짜 값
  10104. * @return {$Date | Number} 인수를 지정하였다면 새로 날짜를 설정한 $Date 객체. 인수를 지정하지 않았다면 $Date 객체가 지정하고 있는 시각의 날짜를 리턴한다.
  10105. */
  10106. jindo.$Date.prototype.date = function(nDate) {
  10107. if (typeof nDate == "number") {
  10108. this._date.setDate(nDate);
  10109. return this;
  10110. }
  10111. return this._date.getDate();
  10112. };
  10113. /**
  10114. * day 메서드는 요일을 가져온다.
  10115. * @return {Number} 요일 값. 0(일요일)에서 6(토요일)을 리턴한다.
  10116. */
  10117. jindo.$Date.prototype.day = function() {
  10118. return this._date.getDay();
  10119. };
  10120. /**
  10121. * hours 메서드는 시(時)를 설정하거나 가져온다.
  10122. * @param {Number} nHour 설정할 시 값
  10123. * @return {$Date | Number} 인수를 지정하였다면 새로 시 값을 설정한 $Date 객체. 인수를 지정하지 않았다면 $Date 객체가 지정하고 있는 시각의 시 값.
  10124. */
  10125. jindo.$Date.prototype.hours = function(nHour) {
  10126. if (typeof nHour == "number") {
  10127. this._date.setHours(nHour);
  10128. return this;
  10129. }
  10130. return this._date.getHours();
  10131. };
  10132. /**
  10133. * minutes 메서드는 분을 설정하거나 가져온다.
  10134. * @param {Number} nMin 설정할 분 값
  10135. * @return {Number} 인수를 지정하였다면 새로 분 값을 설정한 $Date 객체. 인수를 지정하지 않았다면 $Date 객체가 지정하고 있는 시각의 분 값.
  10136. */
  10137. jindo.$Date.prototype.minutes = function(nMin) {
  10138. if (typeof nMin == "number") {
  10139. this._date.setMinutes(nMin);
  10140. return this;
  10141. }
  10142. return this._date.getMinutes();
  10143. };
  10144. /**
  10145. * seconds 메서드는 초을 설정하거나 가져온다.
  10146. * @param {Number} nSec 설정할 초 값
  10147. * @return {Number} 인수를 지정하였다면 새로 초 값을 설정한 $Date 객체. 인수를 지정하지 않았다면 $Date 객체가 지정하고 있는 시각의 초 값.
  10148. */
  10149. jindo.$Date.prototype.seconds = function(nSec) {
  10150. if (typeof nSec == "number") {
  10151. this._date.setSeconds(nSec);
  10152. return this;
  10153. }
  10154. return this._date.getSeconds();
  10155. };
  10156. /**
  10157. * isLeapYear 메서드는 시각의 윤년 여부를 확인한다.
  10158. * @returns {Boolean} $Date가 가리키고 있는 시각이 윤년이면 True, 그렇지 않다면 False
  10159. */
  10160. jindo.$Date.prototype.isLeapYear = function() {
  10161. var y = this._date.getFullYear();
  10162. return !(y%4)&&!!(y%100)||!(y%400);
  10163. };
  10164. /**
  10165. * @fileOverView $Window의 생성자 및 메서드를 정의한 파일
  10166. * @name window.js
  10167. */
  10168. /**
  10169. * $Window 객체를 생성하고 생성한 객체를 리턴한다.
  10170. * @class $Window 객체는 브라우저가 제공하는 window 객체를 래핑하고, 이를 다루기 위한 여러가지 메서드를 제공한다.
  10171. * @param {HTMLWidnow} el
  10172. * <br>
  10173. * $Window로 래핑할 window 엘리먼트.
  10174. * @author gony
  10175. */
  10176. jindo.$Window = function(el) {
  10177. var cl = arguments.callee;
  10178. if (el instanceof cl) return el;
  10179. if (!(this instanceof cl)) return new cl(el);
  10180. this._win = el || window;
  10181. }
  10182. /**
  10183. * $value 메서드는 원래의 window 객체를 리턴한다.
  10184. * @return {HTMLWindow} window 엘리먼트
  10185. * @example
  10186. $Window().$value(); // 원래의 window 객체를 리턴한다.
  10187. */
  10188. jindo.$Window.prototype.$value = function() {
  10189. return this._win;
  10190. };
  10191. /**
  10192. * resizeTo 메서드는 창의 크기를 지정한 크기로 변경한다.<br>
  10193. * 이 크기는 프레임을 포함한 창 전체의 크기를 나타내므로 실제로 표현하는 컨텐트 사이즈는 브라우저 종류와 설정에 따라 달라질 수 있다.<br>
  10194. * 브라우저에 따라 보안 문제 때문에, 창 크기가 화면의 가시 영역을 벗어나서 커지지 못하도록 막는 경우도 있다. 이 경우에는 지정한 크기보다 작게 창이 커진다.<br>
  10195. * @param {Number} nWidth 창의 너비
  10196. * @param {Number} nHeight 창의 높이
  10197. * @return {$Window} $Window 객체
  10198. * @see $Window#resizeBy
  10199. * @example
  10200. * // 현재 창의 너비를 400, 높이를 300으로 변경한다.
  10201. * $Window.resizeTo(400, 300);
  10202. */
  10203. jindo.$Window.prototype.resizeTo = function(nWidth, nHeight) {
  10204. this._win.resizeTo(nWidth, nHeight);
  10205. return this;
  10206. };
  10207. /**
  10208. * resizeBy 메서드는 창의 크기를 지정한 크기만큼 변경한다.
  10209. * @param {Number} nWidth 늘어날 창의 너비
  10210. * @param {Number} nHeight 늘어날 창의 높이
  10211. * @see $Window#resizeTo
  10212. * @example
  10213. * // 현재 창의 너비를 100, 높이를 50 만큼 늘린다.
  10214. * $Window().resize(100, 50);
  10215. */
  10216. jindo.$Window.prototype.resizeBy = function(nWidth, nHeight) {
  10217. this._win.resizeBy(nWidth, nHeight);
  10218. return this;
  10219. };
  10220. /**
  10221. * moveTo 메서드는 창을 지정한 위치로 이동시킨다. 좌표는 프레임을 포함한 창의 좌측 상단을 기준으로 한다.
  10222. * @param {Number} nLeft 이동할 x좌표 (pixel 단위)
  10223. * @param {Number} nTop 이동할 y좌표 (pixel 단위)
  10224. * @see $Window#moveBy
  10225. * @example
  10226. * // 현재 창을 (15, 10) 으로 이동시킨다.
  10227. * $Window().moveTo(15, 10);
  10228. */
  10229. jindo.$Window.prototype.moveTo = function(nLeft, nTop) {
  10230. this._win.moveTo(nLeft, nTop);
  10231. return this;
  10232. };
  10233. /**
  10234. * moveBy 메서드는 창을 지정한 위치만큼 이동시킨다.
  10235. * @param {Number} nLeft x좌표로 이동할 만큼의 양 (pixel 단위)
  10236. * @param {Number} nTop y좌표로 이동할 만큼의 양 (pixel 단위)
  10237. * @see $Window#moveTo
  10238. * @example
  10239. * // 현재 창을 좌측으로 15px만큼, 아래로 10px만큼 이동시킨다.
  10240. * $Window().moveBy(15, 10);
  10241. */
  10242. jindo.$Window.prototype.moveBy = function(nLeft, nTop) {
  10243. this._win.moveBy(nLeft, nTop);
  10244. return this;
  10245. };
  10246. /**
  10247. * sizeToContent 메서드는 내부 문서의 컨텐츠 크기에 맞추어 창의 크기를 변경하며, 몇 가지 제약 사항을 가진다. <br>
  10248. * 제약사항에 걸리는 경우 매개변수로 창의 사이즈를 지정할 수 있다.
  10249. <ul>
  10250. <li>메서드의 내부 문서가 완전히 로딩된 다음에 실행되어야 한다. </li>
  10251. <li>창이 내부 문서보다 큰 경우에는 내부 문서를 구할 수 없으므로, 반드시 창 크기를 내부 문서보다 작게 만든다.</li>
  10252. <li>반드시 body에 사이즈가 있어야 한다.</li>
  10253. <li>html의 DOCTYPE이 Quirks일때 맥에서는 opera(10), 윈도우에서는 IE6+, opera(10), safari(4)에서 정상적으로 동작하지 않는다.</li>
  10254. <li>가능 하면 부모창에서 실행 시켜야 한다. 자식창이 모니터 화면을 벗어나 가려져 있을 경우, IE는 가려진 영역은 컨텐츠가 없는 것으로 판단하여 가려진 영역 만큼 줄인다.</li>
  10255. </ul>
  10256. * @param {Number} nWidth 창의 너비
  10257. * @param {Number} nHeight 창의 높이
  10258. * @example
  10259. * // 새 창을 띄우고 자동으로 창 크기를 컨텐트에 맞게 변경하는 함수
  10260. * function winopen(url) {
  10261. * try {
  10262. * win = window.open(url, "", "toolbar=0,location=0,status=0,menubar=0,scrollbars=0,resizable=0,width=250,height=300");
  10263. * win.moveTo(200, 100);
  10264. * win.focus();
  10265. * } catch(e){}
  10266. *
  10267. * setTimeout(function() {
  10268. * $Window(win).sizeToContent();
  10269. * }, 1000);
  10270. * }
  10271. *
  10272. * winopen('/samples/popup.html');
  10273. */
  10274. jindo.$Window.prototype.sizeToContent = function(nWidth, nHeight) {
  10275. if (typeof this._win.sizeToContent == "function") {
  10276. this._win.sizeToContent();
  10277. } else {
  10278. if(arguments.length != 2){
  10279. // use trick by Peter-Paul Koch
  10280. // http://www.quirksmode.org/
  10281. var innerX,innerY;
  10282. var self = this._win;
  10283. var doc = this._win.document;
  10284. if (self.innerHeight) {
  10285. // all except Explorer
  10286. innerX = self.innerWidth;
  10287. innerY = self.innerHeight;
  10288. } else if (doc.documentElement && doc.documentElement.clientHeight) {
  10289. // Explorer 6 Strict Mode
  10290. innerX = doc.documentElement.clientWidth;
  10291. innerY = doc.documentElement.clientHeight;
  10292. } else if (doc.body) {
  10293. // other Explorers
  10294. innerX = doc.body.clientWidth;
  10295. innerY = doc.body.clientHeight;
  10296. }
  10297. var pageX,pageY;
  10298. var test1 = doc.body.scrollHeight;
  10299. var test2 = doc.body.offsetHeight;
  10300. if (test1 > test2) {
  10301. // all but Explorer Mac
  10302. pageX = doc.body.scrollWidth;
  10303. pageY = doc.body.scrollHeight;
  10304. } else {
  10305. // Explorer Mac;
  10306. //would also work in Explorer 6 Strict, Mozilla and Safari
  10307. pageX = doc.body.offsetWidth;
  10308. pageY = doc.body.offsetHeight;
  10309. }
  10310. nWidth = pageX - innerX;
  10311. nHeight = pageY - innerY;
  10312. }
  10313. this.resizeBy(nWidth, nHeight);
  10314. }
  10315. return this;
  10316. };
  10317. /**
  10318. * @fileOverview 다른 프레임웍 없이 jindo만 사용할 경우 편의성을 위해 jindo 객체를 window에 붙임
  10319. */
  10320. // copy jindo objects to window
  10321. if (typeof window != "undefined") {
  10322. for (prop in jindo) {
  10323. if (jindo.hasOwnProperty(prop)) {
  10324. window[prop] = jindo[prop];
  10325. }
  10326. }
  10327. }