A tumblelog CMS built on AJAX, PHP and MySQL.

tiny_mce_src.js 208KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493
  1. /* file:jscripts/tiny_mce/classes/TinyMCE_Engine.class.js */
  2. function TinyMCE_Engine() {
  3. var ua;
  4. this.majorVersion = "2";
  5. this.minorVersion = "1.0";
  6. this.releaseDate = "2007-02-13";
  7. this.instances = new Array();
  8. this.switchClassCache = new Array();
  9. this.windowArgs = new Array();
  10. this.loadedFiles = new Array();
  11. this.pendingFiles = new Array();
  12. this.loadingIndex = 0;
  13. this.configs = new Array();
  14. this.currentConfig = 0;
  15. this.eventHandlers = new Array();
  16. this.log = new Array();
  17. this.undoLevels = [];
  18. this.undoIndex = 0;
  19. this.typingUndoIndex = -1;
  20. // Browser check
  21. ua = navigator.userAgent;
  22. this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
  23. this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);
  24. this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);
  25. this.isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1);
  26. this.isGecko = ua.indexOf('Gecko') != -1;
  27. this.isSafari = ua.indexOf('Safari') != -1;
  28. this.isOpera = ua.indexOf('Opera') != -1;
  29. this.isMac = ua.indexOf('Mac') != -1;
  30. this.isNS7 = ua.indexOf('Netscape/7') != -1;
  31. this.isNS71 = ua.indexOf('Netscape/7.1') != -1;
  32. this.dialogCounter = 0;
  33. this.plugins = new Array();
  34. this.themes = new Array();
  35. this.menus = new Array();
  36. this.loadedPlugins = new Array();
  37. this.buttonMap = new Array();
  38. this.isLoaded = false;
  39. // Fake MSIE on Opera and if Opera fakes IE, Gecko or Safari cancel those
  40. if (this.isOpera) {
  41. this.isMSIE = true;
  42. this.isGecko = false;
  43. this.isSafari = false;
  44. }
  45. this.isIE = this.isMSIE;
  46. this.isRealIE = this.isMSIE && !this.isOpera;
  47. // TinyMCE editor id instance counter
  48. this.idCounter = 0;
  49. };
  50. TinyMCE_Engine.prototype = {
  51. init : function(settings) {
  52. var theme, nl, baseHREF = "", i;
  53. // IE 5.0x is no longer supported since 5.5, 6.0 and 7.0 now exists. We can't support old browsers forever, sorry.
  54. if (this.isMSIE5_0)
  55. return;
  56. this.settings = settings;
  57. // Check if valid browser has execcommand support
  58. if (typeof(document.execCommand) == 'undefined')
  59. return;
  60. // Get script base path
  61. if (!tinyMCE.baseURL) {
  62. var elements = document.getElementsByTagName('script');
  63. // If base element found, add that infront of baseURL
  64. nl = document.getElementsByTagName('base');
  65. for (i=0; i<nl.length; i++) {
  66. if (nl[i].href)
  67. baseHREF = nl[i].href;
  68. }
  69. for (var i=0; i<elements.length; i++) {
  70. if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_dev.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1 || elements[i].src.indexOf("tiny_mce_gzip") != -1)) {
  71. var src = elements[i].src;
  72. tinyMCE.srcMode = (src.indexOf('_src') != -1 || src.indexOf('_dev') != -1) ? '_src' : '';
  73. tinyMCE.gzipMode = src.indexOf('_gzip') != -1;
  74. src = src.substring(0, src.lastIndexOf('/'));
  75. if (settings.exec_mode == "src" || settings.exec_mode == "normal")
  76. tinyMCE.srcMode = settings.exec_mode == "src" ? '_src' : '';
  77. // Force it absolute if page has a base href
  78. if (baseHREF != "" && src.indexOf('://') == -1)
  79. tinyMCE.baseURL = baseHREF + src;
  80. else
  81. tinyMCE.baseURL = src;
  82. break;
  83. }
  84. }
  85. }
  86. // Get document base path
  87. this.documentBasePath = document.location.href;
  88. if (this.documentBasePath.indexOf('?') != -1)
  89. this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.indexOf('?'));
  90. this.documentURL = this.documentBasePath;
  91. this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.lastIndexOf('/'));
  92. // If not HTTP absolute
  93. if (tinyMCE.baseURL.indexOf('://') == -1 && tinyMCE.baseURL.charAt(0) != '/') {
  94. // If site absolute
  95. tinyMCE.baseURL = this.documentBasePath + "/" + tinyMCE.baseURL;
  96. }
  97. // Set default values on settings
  98. this._def("mode", "none");
  99. this._def("theme", "advanced");
  100. this._def("plugins", "", true);
  101. this._def("language", "en");
  102. this._def("docs_language", this.settings['language']);
  103. this._def("elements", "");
  104. this._def("textarea_trigger", "mce_editable");
  105. this._def("editor_selector", "");
  106. this._def("editor_deselector", "mceNoEditor");
  107. this._def("valid_elements", "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|style],-ul[class|style],-li[class|style],br,img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align],-sub[style|class],-sup[style|class],-blockquote[dir|style],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[style|class|align],-pre[class|align|style],address[class|align|style],-h1[id|style|dir|class|align],-h2[id|style|dir|class|align],-h3[id|style|dir|class|align],-h4[id|style|dir|class|align],-h5[id|style|dir|class|align],-h6[id|style|dir|class|align],hr[class|style],-font[face|size|style|id|class|dir|color],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],cite[title|id|class|style|dir|lang],abbr[title|id|class|style|dir|lang],acronym[title|id|class|style|dir|lang],del[title|id|class|style|dir|lang|datetime|cite],ins[title|id|class|style|dir|lang|datetime|cite]");
  108. this._def("extended_valid_elements", "");
  109. this._def("invalid_elements", "");
  110. this._def("encoding", "");
  111. this._def("urlconverter_callback", tinyMCE.getParam("urlconvertor_callback", "TinyMCE_Engine.prototype.convertURL"));
  112. this._def("save_callback", "");
  113. this._def("debug", false);
  114. this._def("force_br_newlines", false);
  115. this._def("force_p_newlines", true);
  116. this._def("add_form_submit_trigger", true);
  117. this._def("relative_urls", true);
  118. this._def("remove_script_host", true);
  119. this._def("focus_alert", true);
  120. this._def("document_base_url", this.documentURL);
  121. this._def("visual", true);
  122. this._def("visual_table_class", "mceVisualAid");
  123. this._def("setupcontent_callback", "");
  124. this._def("fix_content_duplication", true);
  125. this._def("custom_undo_redo", true);
  126. this._def("custom_undo_redo_levels", -1);
  127. this._def("custom_undo_redo_keyboard_shortcuts", true);
  128. this._def("custom_undo_redo_restore_selection", true);
  129. this._def("custom_undo_redo_global", false);
  130. this._def("verify_html", true);
  131. this._def("apply_source_formatting", false);
  132. this._def("directionality", "ltr");
  133. this._def("cleanup_on_startup", false);
  134. this._def("inline_styles", false);
  135. this._def("convert_newlines_to_brs", false);
  136. this._def("auto_reset_designmode", true);
  137. this._def("entities", "39,#39,160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,34,quot,38,amp,60,lt,62,gt,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro", true);
  138. this._def("entity_encoding", "named");
  139. this._def("cleanup_callback", "");
  140. this._def("add_unload_trigger", true);
  141. this._def("ask", false);
  142. this._def("nowrap", false);
  143. this._def("auto_resize", false);
  144. this._def("auto_focus", false);
  145. this._def("cleanup", true);
  146. this._def("remove_linebreaks", true);
  147. this._def("button_tile_map", false);
  148. this._def("submit_patch", true);
  149. this._def("browsers", "msie,safari,gecko,opera", true);
  150. this._def("dialog_type", "window");
  151. this._def("accessibility_warnings", true);
  152. this._def("accessibility_focus", true);
  153. this._def("merge_styles_invalid_parents", "");
  154. this._def("force_hex_style_colors", true);
  155. this._def("trim_span_elements", true);
  156. this._def("convert_fonts_to_spans", false);
  157. this._def("doctype", '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">');
  158. this._def("font_size_classes", '');
  159. this._def("font_size_style_values", 'xx-small,x-small,small,medium,large,x-large,xx-large', true);
  160. this._def("event_elements", 'a,img', true);
  161. this._def("convert_urls", true);
  162. this._def("table_inline_editing", false);
  163. this._def("object_resizing", true);
  164. this._def("custom_shortcuts", true);
  165. this._def("convert_on_click", false);
  166. this._def("content_css", '');
  167. this._def("fix_list_elements", true);
  168. this._def("fix_table_elements", false);
  169. this._def("strict_loading_mode", document.contentType == 'application/xhtml+xml');
  170. this._def("hidden_tab_class", '');
  171. this._def("display_tab_class", '');
  172. this._def("gecko_spellcheck", false);
  173. this._def("hide_selects_on_submit", true);
  174. // Force strict loading mode to false on non Gecko browsers
  175. if (this.isMSIE && !this.isOpera)
  176. this.settings.strict_loading_mode = false;
  177. // Browser check IE
  178. if (this.isMSIE && this.settings['browsers'].indexOf('msie') == -1)
  179. return;
  180. // Browser check Gecko
  181. if (this.isGecko && this.settings['browsers'].indexOf('gecko') == -1)
  182. return;
  183. // Browser check Safari
  184. if (this.isSafari && this.settings['browsers'].indexOf('safari') == -1)
  185. return;
  186. // Browser check Opera
  187. if (this.isOpera && this.settings['browsers'].indexOf('opera') == -1)
  188. return;
  189. // If not super absolute make it so
  190. baseHREF = tinyMCE.settings['document_base_url'];
  191. var h = document.location.href;
  192. var p = h.indexOf('://');
  193. if (p > 0 && document.location.protocol != "file:") {
  194. p = h.indexOf('/', p + 3);
  195. h = h.substring(0, p);
  196. if (baseHREF.indexOf('://') == -1)
  197. baseHREF = h + baseHREF;
  198. tinyMCE.settings['document_base_url'] = baseHREF;
  199. tinyMCE.settings['document_base_prefix'] = h;
  200. }
  201. // Trim away query part
  202. if (baseHREF.indexOf('?') != -1)
  203. baseHREF = baseHREF.substring(0, baseHREF.indexOf('?'));
  204. this.settings['base_href'] = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/";
  205. theme = this.settings['theme'];
  206. this.inlineStrict = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';
  207. this.inlineTransitional = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';
  208. this.blockElms = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';
  209. this.blockRegExp = new RegExp("^(" + this.blockElms + ")$", "i");
  210. this.posKeyCodes = new Array(13,45,36,35,33,34,37,38,39,40);
  211. this.uniqueURL = 'javascript:void(091039730);'; // Make unique URL non real URL
  212. this.uniqueTag = '<div id="mceTMPElement" style="display: none">TMP</div>';
  213. this.callbacks = new Array('onInit', 'getInfo', 'getEditorTemplate', 'setupContent', 'onChange', 'onPageLoad', 'handleNodeChange', 'initInstance', 'execCommand', 'getControlHTML', 'handleEvent', 'cleanup', 'removeInstance');
  214. // Theme url
  215. this.settings['theme_href'] = tinyMCE.baseURL + "/themes/" + theme;
  216. if (!tinyMCE.isIE || tinyMCE.isOpera)
  217. this.settings['force_br_newlines'] = false;
  218. if (tinyMCE.getParam("popups_css", false)) {
  219. var cssPath = tinyMCE.getParam("popups_css", "");
  220. // Is relative
  221. if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
  222. this.settings['popups_css'] = this.documentBasePath + "/" + cssPath;
  223. else
  224. this.settings['popups_css'] = cssPath;
  225. } else
  226. this.settings['popups_css'] = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_popup.css";
  227. if (tinyMCE.getParam("editor_css", false)) {
  228. var cssPath = tinyMCE.getParam("editor_css", "");
  229. // Is relative
  230. if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
  231. this.settings['editor_css'] = this.documentBasePath + "/" + cssPath;
  232. else
  233. this.settings['editor_css'] = cssPath;
  234. } else {
  235. if (this.settings.editor_css != '')
  236. this.settings['editor_css'] = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_ui.css";
  237. }
  238. if (tinyMCE.settings['debug']) {
  239. var msg = "Debug: \n";
  240. msg += "baseURL: " + this.baseURL + "\n";
  241. msg += "documentBasePath: " + this.documentBasePath + "\n";
  242. msg += "content_css: " + this.settings['content_css'] + "\n";
  243. msg += "popups_css: " + this.settings['popups_css'] + "\n";
  244. msg += "editor_css: " + this.settings['editor_css'] + "\n";
  245. alert(msg);
  246. }
  247. // Only do this once
  248. if (this.configs.length == 0) {
  249. if (typeof(TinyMCECompressed) == "undefined") {
  250. tinyMCE.addEvent(window, "DOMContentLoaded", TinyMCE_Engine.prototype.onLoad);
  251. if (tinyMCE.isRealIE) {
  252. if (document.body)
  253. tinyMCE.addEvent(document.body, "readystatechange", TinyMCE_Engine.prototype.onLoad);
  254. else
  255. tinyMCE.addEvent(document, "readystatechange", TinyMCE_Engine.prototype.onLoad);
  256. }
  257. tinyMCE.addEvent(window, "load", TinyMCE_Engine.prototype.onLoad);
  258. tinyMCE._addUnloadEvents();
  259. }
  260. }
  261. this.loadScript(tinyMCE.baseURL + '/themes/' + this.settings['theme'] + '/editor_template' + tinyMCE.srcMode + '.js');
  262. this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings['language'] + '.js');
  263. this.loadCSS(this.settings['editor_css']);
  264. // Add plugins
  265. var p = tinyMCE.getParam('plugins', '', true, ',');
  266. if (p.length > 0) {
  267. for (var i=0; i<p.length; i++) {
  268. if (p[i].charAt(0) != '-')
  269. this.loadScript(tinyMCE.baseURL + '/plugins/' + p[i] + '/editor_plugin' + tinyMCE.srcMode + '.js');
  270. }
  271. }
  272. // Setup entities
  273. if (tinyMCE.getParam('entity_encoding') == 'named') {
  274. settings['cleanup_entities'] = new Array();
  275. var entities = tinyMCE.getParam('entities', '', true, ',');
  276. for (var i=0; i<entities.length; i+=2)
  277. settings['cleanup_entities']['c' + entities[i]] = entities[i+1];
  278. }
  279. // Save away this config
  280. settings['index'] = this.configs.length;
  281. this.configs[this.configs.length] = settings;
  282. // Start loading first one in chain
  283. this.loadNextScript();
  284. // Force flicker free CSS backgrounds in IE
  285. if (this.isIE && !this.isOpera) {
  286. try {
  287. document.execCommand('BackgroundImageCache', false, true);
  288. } catch (e) {
  289. }
  290. }
  291. // Setup XML encoding regexps
  292. this.xmlEncodeAposRe = new RegExp('[<>&"\']', 'g');
  293. this.xmlEncodeRe = new RegExp('[<>&"]', 'g');
  294. // this.xmlEncodeEnts = {'&':'&amp;','"':'&quot;',"'":'&#39;','<':'&lt;','>':'&gt;'};
  295. },
  296. _addUnloadEvents : function() {
  297. if (tinyMCE.isIE) {
  298. if (tinyMCE.settings['add_unload_trigger']) {
  299. tinyMCE.addEvent(window, "unload", TinyMCE_Engine.prototype.unloadHandler);
  300. tinyMCE.addEvent(window.document, "beforeunload", TinyMCE_Engine.prototype.unloadHandler);
  301. }
  302. } else {
  303. if (tinyMCE.settings['add_unload_trigger'])
  304. tinyMCE.addEvent(window, "unload", function () {tinyMCE.triggerSave(true, true);});
  305. }
  306. },
  307. _def : function(key, def_val, t) {
  308. var v = tinyMCE.getParam(key, def_val);
  309. v = t ? v.replace(/\s+/g, "") : v;
  310. this.settings[key] = v;
  311. },
  312. hasPlugin : function(n) {
  313. return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
  314. },
  315. addPlugin : function(n, p) {
  316. var op = this.plugins[n];
  317. // Use the previous plugin object base URL used when loading external plugins
  318. p.baseURL = op ? op.baseURL : tinyMCE.baseURL + "/plugins/" + n;
  319. this.plugins[n] = p;
  320. this.loadNextScript();
  321. },
  322. setPluginBaseURL : function(n, u) {
  323. var op = this.plugins[n];
  324. if (op)
  325. op.baseURL = u;
  326. else
  327. this.plugins[n] = {baseURL : u};
  328. },
  329. loadPlugin : function(n, u) {
  330. u = u.indexOf('.js') != -1 ? u.substring(0, u.lastIndexOf('/')) : u;
  331. u = u.charAt(u.length-1) == '/' ? u.substring(0, u.length-1) : u;
  332. this.plugins[n] = {baseURL : u};
  333. this.loadScript(u + "/editor_plugin" + (tinyMCE.srcMode ? '_src' : '') + ".js");
  334. },
  335. hasTheme : function(n) {
  336. return typeof(this.themes[n]) != "undefined" && this.themes[n] != null;
  337. },
  338. addTheme : function(n, t) {
  339. this.themes[n] = t;
  340. this.loadNextScript();
  341. },
  342. addMenu : function(n, m) {
  343. this.menus[n] = m;
  344. },
  345. hasMenu : function(n) {
  346. return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
  347. },
  348. loadScript : function(url) {
  349. var i;
  350. for (i=0; i<this.loadedFiles.length; i++) {
  351. if (this.loadedFiles[i] == url)
  352. return;
  353. }
  354. if (tinyMCE.settings.strict_loading_mode)
  355. this.pendingFiles[this.pendingFiles.length] = url;
  356. else
  357. document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></script>');
  358. this.loadedFiles[this.loadedFiles.length] = url;
  359. },
  360. loadNextScript : function() {
  361. var d = document, se;
  362. if (!tinyMCE.settings.strict_loading_mode)
  363. return;
  364. if (this.loadingIndex < this.pendingFiles.length) {
  365. se = d.createElementNS('http://www.w3.org/1999/xhtml', 'script');
  366. se.setAttribute('language', 'javascript');
  367. se.setAttribute('type', 'text/javascript');
  368. se.setAttribute('src', this.pendingFiles[this.loadingIndex++]);
  369. d.getElementsByTagName("head")[0].appendChild(se);
  370. } else
  371. this.loadingIndex = -1; // Done with loading
  372. },
  373. loadCSS : function(url) {
  374. var ar = url.replace(/\s+/, '').split(',');
  375. var lflen = 0, csslen = 0;
  376. var skip = false;
  377. var x = 0, i = 0, nl, le;
  378. for (x = 0,csslen = ar.length; x<csslen; x++) {
  379. if (ar[x] != null && ar[x] != 'null' && ar[x].length > 0) {
  380. /* Make sure it doesn't exist. */
  381. for (i=0, lflen=this.loadedFiles.length; i<lflen; i++) {
  382. if (this.loadedFiles[i] == ar[x]) {
  383. skip = true;
  384. break;
  385. }
  386. }
  387. if (!skip) {
  388. if (tinyMCE.settings.strict_loading_mode) {
  389. nl = document.getElementsByTagName("head");
  390. le = document.createElement('link');
  391. le.setAttribute('href', ar[x]);
  392. le.setAttribute('rel', 'stylesheet');
  393. le.setAttribute('type', 'text/css');
  394. nl[0].appendChild(le);
  395. } else
  396. document.write('<link href="' + ar[x] + '" rel="stylesheet" type="text/css" />');
  397. this.loadedFiles[this.loadedFiles.length] = ar[x];
  398. }
  399. }
  400. }
  401. },
  402. importCSS : function(doc, css) {
  403. var css_ary = css.replace(/\s+/, '').split(',');
  404. var csslen, elm, headArr, x, css_file;
  405. for (x = 0, csslen = css_ary.length; x<csslen; x++) {
  406. css_file = css_ary[x];
  407. if (css_file != null && css_file != 'null' && css_file.length > 0) {
  408. // Is relative, make absolute
  409. if (css_file.indexOf('://') == -1 && css_file.charAt(0) != '/')
  410. css_file = this.documentBasePath + "/" + css_file;
  411. if (typeof(doc.createStyleSheet) == "undefined") {
  412. elm = doc.createElement("link");
  413. elm.rel = "stylesheet";
  414. elm.href = css_file;
  415. if ((headArr = doc.getElementsByTagName("head")) != null && headArr.length > 0)
  416. headArr[0].appendChild(elm);
  417. } else
  418. doc.createStyleSheet(css_file);
  419. }
  420. }
  421. },
  422. confirmAdd : function(e, settings) {
  423. var elm = tinyMCE.isIE ? event.srcElement : e.target;
  424. var elementId = elm.name ? elm.name : elm.id;
  425. tinyMCE.settings = settings;
  426. if (tinyMCE.settings['convert_on_click'] || (!elm.getAttribute('mce_noask') && confirm(tinyMCELang['lang_edit_confirm'])))
  427. tinyMCE.addMCEControl(elm, elementId);
  428. elm.setAttribute('mce_noask', 'true');
  429. },
  430. updateContent : function(form_element_name) {
  431. // Find MCE instance linked to given form element and copy it's value
  432. var formElement = document.getElementById(form_element_name);
  433. for (var n in tinyMCE.instances) {
  434. var inst = tinyMCE.instances[n];
  435. if (!tinyMCE.isInstance(inst))
  436. continue;
  437. inst.switchSettings();
  438. if (inst.formElement == formElement) {
  439. var doc = inst.getDoc();
  440. tinyMCE._setHTML(doc, inst.formElement.value);
  441. if (!tinyMCE.isIE)
  442. doc.body.innerHTML = tinyMCE._cleanupHTML(inst, doc, this.settings, doc.body, inst.visualAid);
  443. }
  444. }
  445. },
  446. addMCEControl : function(replace_element, form_element_name, target_document) {
  447. var id = "mce_editor_" + tinyMCE.idCounter++;
  448. var inst = new TinyMCE_Control(tinyMCE.settings);
  449. inst.editorId = id;
  450. this.instances[id] = inst;
  451. inst._onAdd(replace_element, form_element_name, target_document);
  452. },
  453. removeInstance : function(ti) {
  454. var t = [], n, i;
  455. // Remove from instances
  456. for (n in tinyMCE.instances) {
  457. i = tinyMCE.instances[n];
  458. if (tinyMCE.isInstance(i) && ti != i)
  459. t[n] = i;
  460. }
  461. tinyMCE.instances = t;
  462. // Remove from global undo/redo
  463. n = [];
  464. t = tinyMCE.undoLevels;
  465. for (i=0; i<t.length; i++) {
  466. if (t[i] != ti)
  467. n.push(t[i]);
  468. }
  469. tinyMCE.undoLevels = n;
  470. tinyMCE.undoIndex = n.length;
  471. // Dispatch remove instance call
  472. tinyMCE.dispatchCallback(ti, 'remove_instance_callback', 'removeInstance', ti);
  473. return ti;
  474. },
  475. removeMCEControl : function(editor_id) {
  476. var inst = tinyMCE.getInstanceById(editor_id), h, re, ot, tn;
  477. if (inst) {
  478. inst.switchSettings();
  479. editor_id = inst.editorId;
  480. h = tinyMCE.getContent(editor_id);
  481. this.removeInstance(inst);
  482. tinyMCE.selectedElement = null;
  483. tinyMCE.selectedInstance = null;
  484. // Remove element
  485. re = document.getElementById(editor_id + "_parent");
  486. ot = inst.oldTargetElement;
  487. tn = ot.nodeName.toLowerCase();
  488. if (tn == "textarea" || tn == "input") {
  489. re.parentNode.removeChild(re);
  490. ot.style.display = "inline";
  491. ot.value = h;
  492. } else {
  493. ot.innerHTML = h;
  494. ot.style.display = 'block';
  495. re.parentNode.insertBefore(ot, re);
  496. re.parentNode.removeChild(re);
  497. }
  498. }
  499. },
  500. triggerSave : function(skip_cleanup, skip_callback) {
  501. var inst, n;
  502. // Default to false
  503. if (typeof(skip_cleanup) == "undefined")
  504. skip_cleanup = false;
  505. // Default to false
  506. if (typeof(skip_callback) == "undefined")
  507. skip_callback = false;
  508. // Cleanup and set all form fields
  509. for (n in tinyMCE.instances) {
  510. inst = tinyMCE.instances[n];
  511. if (!tinyMCE.isInstance(inst))
  512. continue;
  513. inst.triggerSave(skip_cleanup, skip_callback);
  514. }
  515. },
  516. resetForm : function(form_index) {
  517. var i, inst, n, formObj = document.forms[form_index];
  518. for (n in tinyMCE.instances) {
  519. inst = tinyMCE.instances[n];
  520. if (!tinyMCE.isInstance(inst))
  521. continue;
  522. inst.switchSettings();
  523. for (i=0; i<formObj.elements.length; i++) {
  524. if (inst.formTargetElementId == formObj.elements[i].name)
  525. inst.getBody().innerHTML = inst.startContent;
  526. }
  527. }
  528. },
  529. execInstanceCommand : function(editor_id, command, user_interface, value, focus) {
  530. var inst = tinyMCE.getInstanceById(editor_id), r;
  531. if (inst) {
  532. r = inst.selection.getRng();
  533. if (typeof(focus) == "undefined")
  534. focus = true;
  535. // IE bug lost focus on images in absolute divs Bug #1534575
  536. if (focus && (!r || !r.item))
  537. inst.contentWindow.focus();
  538. // Reset design mode if lost
  539. inst.autoResetDesignMode();
  540. this.selectedElement = inst.getFocusElement();
  541. inst.select();
  542. tinyMCE.execCommand(command, user_interface, value);
  543. // Cancel event so it doesn't call onbeforeonunlaod
  544. if (tinyMCE.isIE && window.event != null)
  545. tinyMCE.cancelEvent(window.event);
  546. }
  547. },
  548. execCommand : function(command, user_interface, value) {
  549. var inst = tinyMCE.selectedInstance;
  550. // Default input
  551. user_interface = user_interface ? user_interface : false;
  552. value = value ? value : null;
  553. if (inst)
  554. inst.switchSettings();
  555. switch (command) {
  556. case "Undo":
  557. if (this.getParam('custom_undo_redo_global')) {
  558. if (this.undoIndex > 0) {
  559. tinyMCE.nextUndoRedoAction = 'Undo';
  560. inst = this.undoLevels[--this.undoIndex];
  561. inst.select();
  562. if (!tinyMCE.nextUndoRedoInstanceId)
  563. inst.execCommand('Undo');
  564. }
  565. } else
  566. inst.execCommand('Undo');
  567. return true;
  568. case "Redo":
  569. if (this.getParam('custom_undo_redo_global')) {
  570. if (this.undoIndex <= this.undoLevels.length - 1) {
  571. tinyMCE.nextUndoRedoAction = 'Redo';
  572. inst = this.undoLevels[this.undoIndex++];
  573. inst.select();
  574. if (!tinyMCE.nextUndoRedoInstanceId)
  575. inst.execCommand('Redo');
  576. }
  577. } else
  578. inst.execCommand('Redo');
  579. return true;
  580. case 'mceFocus':
  581. var inst = tinyMCE.getInstanceById(value);
  582. if (inst)
  583. inst.getWin().focus();
  584. return;
  585. case "mceAddControl":
  586. case "mceAddEditor":
  587. tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
  588. return;
  589. case "mceAddFrameControl":
  590. tinyMCE.addMCEControl(tinyMCE._getElementById(value['element'], value['document']), value['element'], value['document']);
  591. return;
  592. case "mceRemoveControl":
  593. case "mceRemoveEditor":
  594. tinyMCE.removeMCEControl(value);
  595. return;
  596. case "mceToggleEditor":
  597. var inst = tinyMCE.getInstanceById(value), pe, te;
  598. if (inst) {
  599. pe = document.getElementById(inst.editorId + '_parent');
  600. te = inst.oldTargetElement;
  601. if (typeof(inst.enabled) == 'undefined')
  602. inst.enabled = true;
  603. inst.enabled = !inst.enabled;
  604. if (!inst.enabled) {
  605. pe.style.display = 'none';
  606. te.value = inst.getHTML();
  607. te.style.display = inst.oldTargetDisplay;
  608. tinyMCE.dispatchCallback(inst, 'hide_instance_callback', 'hideInstance', inst);
  609. } else {
  610. pe.style.display = 'block';
  611. te.style.display = 'none';
  612. inst.setHTML(te.value);
  613. inst.useCSS = false;
  614. tinyMCE.dispatchCallback(inst, 'show_instance_callback', 'showInstance', inst);
  615. }
  616. } else
  617. tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
  618. return;
  619. case "mceResetDesignMode":
  620. // Resets the designmode state of the editors in Gecko
  621. if (!tinyMCE.isIE) {
  622. for (var n in tinyMCE.instances) {
  623. if (!tinyMCE.isInstance(tinyMCE.instances[n]))
  624. continue;
  625. try {
  626. tinyMCE.instances[n].getDoc().designMode = "on";
  627. } catch (e) {
  628. // Ignore any errors
  629. }
  630. }
  631. }
  632. return;
  633. }
  634. if (inst) {
  635. inst.execCommand(command, user_interface, value);
  636. } else if (tinyMCE.settings['focus_alert'])
  637. alert(tinyMCELang['lang_focus_alert']);
  638. },
  639. _createIFrame : function(replace_element, doc, win) {
  640. var iframe, id = replace_element.getAttribute("id");
  641. var aw, ah;
  642. if (typeof(doc) == "undefined")
  643. doc = document;
  644. if (typeof(win) == "undefined")
  645. win = window;
  646. iframe = doc.createElement("iframe");
  647. aw = "" + tinyMCE.settings['area_width'];
  648. ah = "" + tinyMCE.settings['area_height'];
  649. if (aw.indexOf('%') == -1) {
  650. aw = parseInt(aw);
  651. aw = (isNaN(aw) || aw < 0) ? 300 : aw;
  652. aw = aw + "px";
  653. }
  654. if (ah.indexOf('%') == -1) {
  655. ah = parseInt(ah);
  656. ah = (isNaN(ah) || ah < 0) ? 240 : ah;
  657. ah = ah + "px";
  658. }
  659. iframe.setAttribute("id", id);
  660. iframe.setAttribute("name", id);
  661. iframe.setAttribute("class", "mceEditorIframe");
  662. iframe.setAttribute("border", "0");
  663. iframe.setAttribute("frameBorder", "0");
  664. iframe.setAttribute("marginWidth", "0");
  665. iframe.setAttribute("marginHeight", "0");
  666. iframe.setAttribute("leftMargin", "0");
  667. iframe.setAttribute("topMargin", "0");
  668. iframe.setAttribute("width", aw);
  669. iframe.setAttribute("height", ah);
  670. iframe.setAttribute("allowtransparency", "true");
  671. iframe.className = 'mceEditorIframe';
  672. if (tinyMCE.settings["auto_resize"])
  673. iframe.setAttribute("scrolling", "no");
  674. // Must have a src element in MSIE HTTPs breaks aswell as absoute URLs
  675. if (tinyMCE.isRealIE)
  676. iframe.setAttribute("src", this.settings['default_document']);
  677. iframe.style.width = aw;
  678. iframe.style.height = ah;
  679. // Ugly hack for Gecko problem in strict mode
  680. if (tinyMCE.settings.strict_loading_mode)
  681. iframe.style.marginBottom = '-5px';
  682. // MSIE 5.0 issue
  683. if (tinyMCE.isRealIE)
  684. replace_element.outerHTML = iframe.outerHTML;
  685. else
  686. replace_element.parentNode.replaceChild(iframe, replace_element);
  687. if (tinyMCE.isRealIE)
  688. return win.frames[id];
  689. else
  690. return iframe;
  691. },
  692. setupContent : function(editor_id) {
  693. var inst = tinyMCE.instances[editor_id], i;
  694. var doc = inst.getDoc();
  695. var head = doc.getElementsByTagName('head').item(0);
  696. var content = inst.startContent;
  697. // HTML values get XML encoded in strict mode
  698. if (tinyMCE.settings.strict_loading_mode) {
  699. content = content.replace(/&lt;/g, '<');
  700. content = content.replace(/&gt;/g, '>');
  701. content = content.replace(/&quot;/g, '"');
  702. content = content.replace(/&amp;/g, '&');
  703. }
  704. tinyMCE.selectedInstance = inst;
  705. inst.switchSettings();
  706. // Not loaded correctly hit it again, Mozilla bug #997860
  707. if (!tinyMCE.isIE && tinyMCE.getParam("setupcontent_reload", false) && doc.title != "blank_page") {
  708. // This part will remove the designMode status
  709. // Failes first time in Firefox 1.5b2 on Mac
  710. try {doc.location.href = tinyMCE.baseURL + "/blank.htm";} catch (ex) {}
  711. window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 1000);
  712. return;
  713. }
  714. if (!head) {
  715. window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 10);
  716. return;
  717. }
  718. // Import theme specific content CSS the user specific
  719. tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/themes/" + inst.settings['theme'] + "/css/editor_content.css");
  720. tinyMCE.importCSS(inst.getDoc(), inst.settings['content_css']);
  721. tinyMCE.dispatchCallback(inst, 'init_instance_callback', 'initInstance', inst);
  722. // Setup keyboard shortcuts
  723. if (tinyMCE.getParam('custom_undo_redo_keyboard_shortcuts')) {
  724. inst.addShortcut('ctrl', 'z', 'lang_undo_desc', 'Undo');
  725. inst.addShortcut('ctrl', 'y', 'lang_redo_desc', 'Redo');
  726. }
  727. // BlockFormat shortcuts keys
  728. for (i=1; i<=6; i++)
  729. inst.addShortcut('ctrl', '' + i, '', 'FormatBlock', false, '<h' + i + '>');
  730. inst.addShortcut('ctrl', '7', '', 'FormatBlock', false, '<p>');
  731. inst.addShortcut('ctrl', '8', '', 'FormatBlock', false, '<div>');
  732. inst.addShortcut('ctrl', '9', '', 'FormatBlock', false, '<address>');
  733. // Add default shortcuts for gecko
  734. if (tinyMCE.isGecko) {
  735. inst.addShortcut('ctrl', 'b', 'lang_bold_desc', 'Bold');
  736. inst.addShortcut('ctrl', 'i', 'lang_italic_desc', 'Italic');
  737. inst.addShortcut('ctrl', 'u', 'lang_underline_desc', 'Underline');
  738. }
  739. // Setup span styles
  740. if (tinyMCE.getParam("convert_fonts_to_spans"))
  741. inst.getBody().setAttribute('id', 'mceSpanFonts');
  742. if (tinyMCE.settings['nowrap'])
  743. doc.body.style.whiteSpace = "nowrap";
  744. doc.body.dir = this.settings['directionality'];
  745. doc.editorId = editor_id;
  746. // Add on document element in Mozilla
  747. if (!tinyMCE.isIE)
  748. doc.documentElement.editorId = editor_id;
  749. inst.setBaseHREF(tinyMCE.settings['base_href']);
  750. // Replace new line characters to BRs
  751. if (tinyMCE.settings['convert_newlines_to_brs']) {
  752. content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi");
  753. content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi");
  754. content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi");
  755. }
  756. // Open closed anchors
  757. // content = content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
  758. // Call custom cleanup code
  759. content = tinyMCE.storeAwayURLs(content);
  760. content = tinyMCE._customCleanup(inst, "insert_to_editor", content);
  761. if (tinyMCE.isIE) {
  762. // Ugly!!!
  763. window.setInterval('try{tinyMCE.getCSSClasses(tinyMCE.instances["' + editor_id + '"].getDoc(), "' + editor_id + '");}catch(e){}', 500);
  764. if (tinyMCE.settings["force_br_newlines"])
  765. doc.styleSheets[0].addRule("p", "margin: 0;");
  766. var body = inst.getBody();
  767. body.editorId = editor_id;
  768. }
  769. content = tinyMCE.cleanupHTMLCode(content);
  770. // Fix for bug #958637
  771. if (!tinyMCE.isIE) {
  772. var contentElement = inst.getDoc().createElement("body");
  773. var doc = inst.getDoc();
  774. contentElement.innerHTML = content;
  775. // Remove weridness!
  776. if (tinyMCE.isGecko && tinyMCE.settings['remove_lt_gt'])
  777. content = content.replace(new RegExp('&lt;&gt;', 'g'), "");
  778. if (tinyMCE.settings['cleanup_on_startup'])
  779. tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement));
  780. else
  781. tinyMCE.setInnerHTML(inst.getBody(), content);
  782. tinyMCE.convertAllRelativeURLs(inst.getBody());
  783. } else {
  784. if (tinyMCE.settings['cleanup_on_startup']) {
  785. tinyMCE._setHTML(inst.getDoc(), content);
  786. // Produces permission denied error in MSIE 5.5
  787. eval('try {tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));} catch(e) {}');
  788. } else
  789. tinyMCE._setHTML(inst.getDoc(), content);
  790. }
  791. // Fix for bug #957681
  792. //inst.getDoc().designMode = inst.getDoc().designMode;
  793. tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual'], inst);
  794. tinyMCE.dispatchCallback(inst, 'setupcontent_callback', 'setupContent', editor_id, inst.getBody(), inst.getDoc());
  795. // Re-add design mode on mozilla
  796. if (!tinyMCE.isIE)
  797. tinyMCE.addEventHandlers(inst);
  798. // Add blur handler
  799. if (tinyMCE.isIE) {
  800. tinyMCE.addEvent(inst.getBody(), "blur", TinyMCE_Engine.prototype._eventPatch);
  801. tinyMCE.addEvent(inst.getBody(), "beforedeactivate", TinyMCE_Engine.prototype._eventPatch); // Bug #1439953
  802. // Workaround for drag drop/copy paste base href bug
  803. if (!tinyMCE.isOpera) {
  804. tinyMCE.addEvent(doc.body, "mousemove", TinyMCE_Engine.prototype.onMouseMove);
  805. tinyMCE.addEvent(doc.body, "beforepaste", TinyMCE_Engine.prototype._eventPatch);
  806. tinyMCE.addEvent(doc.body, "drop", TinyMCE_Engine.prototype._eventPatch);
  807. }
  808. }
  809. // Trigger node change, this call locks buttons for tables and so forth
  810. inst.select();
  811. tinyMCE.selectedElement = inst.contentWindow.document.body;
  812. // Call custom DOM cleanup
  813. tinyMCE._customCleanup(inst, "insert_to_editor_dom", inst.getBody());
  814. tinyMCE._customCleanup(inst, "setup_content_dom", inst.getBody());
  815. tinyMCE._setEventsEnabled(inst.getBody(), false);
  816. tinyMCE.cleanupAnchors(inst.getDoc());
  817. if (tinyMCE.getParam("convert_fonts_to_spans"))
  818. tinyMCE.convertSpansToFonts(inst.getDoc());
  819. inst.startContent = tinyMCE.trim(inst.getBody().innerHTML);
  820. inst.undoRedo.add({ content : inst.startContent });
  821. // Cleanup any mess left from storyAwayURLs
  822. if (tinyMCE.isGecko) {
  823. // Remove mce_src from textnodes and comments
  824. tinyMCE.selectNodes(inst.getBody(), function(n) {
  825. if (n.nodeType == 3 || n.nodeType == 8)
  826. n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
  827. return false;
  828. });
  829. }
  830. // Remove Gecko spellchecking
  831. if (tinyMCE.isGecko)
  832. inst.getBody().spellcheck = tinyMCE.getParam("gecko_spellcheck");
  833. // Cleanup any mess left from storyAwayURLs
  834. tinyMCE._removeInternal(inst.getBody());
  835. inst.select();
  836. tinyMCE.triggerNodeChange(false, true);
  837. },
  838. storeAwayURLs : function(s) {
  839. // Remove all mce_src, mce_href and replace them with new ones
  840. // s = s.replace(new RegExp('mce_src\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
  841. // s = s.replace(new RegExp('mce_href\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
  842. if (!s.match(/(mce_src|mce_href)/gi, s)) {
  843. s = s.replace(new RegExp('src\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'src="$1" mce_src="$1"');
  844. s = s.replace(new RegExp('href\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'href="$1" mce_href="$1"');
  845. }
  846. return s;
  847. },
  848. _removeInternal : function(n) {
  849. if (tinyMCE.isGecko) {
  850. // Remove mce_src from textnodes and comments
  851. tinyMCE.selectNodes(n, function(n) {
  852. if (n.nodeType == 3 || n.nodeType == 8)
  853. n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
  854. return false;
  855. });
  856. }
  857. },
  858. removeTinyMCEFormElements : function(form_obj) {
  859. var i, elementId;
  860. // Skip form element removal
  861. if (!tinyMCE.getParam('hide_selects_on_submit'))
  862. return;
  863. // Check if form is valid
  864. if (typeof(form_obj) == "undefined" || form_obj == null)
  865. return;
  866. // If not a form, find the form
  867. if (form_obj.nodeName != "FORM") {
  868. if (form_obj.form)
  869. form_obj = form_obj.form;
  870. else
  871. form_obj = tinyMCE.getParentElement(form_obj, "form");
  872. }
  873. // Still nothing
  874. if (form_obj == null)
  875. return;
  876. // Disable all UI form elements that TinyMCE created
  877. for (i=0; i<form_obj.elements.length; i++) {
  878. elementId = form_obj.elements[i].name ? form_obj.elements[i].name : form_obj.elements[i].id;
  879. if (elementId.indexOf('mce_editor_') == 0)
  880. form_obj.elements[i].disabled = true;
  881. }
  882. },
  883. handleEvent : function(e) {
  884. var inst = tinyMCE.selectedInstance;
  885. // Remove odd, error
  886. if (typeof(tinyMCE) == "undefined")
  887. return true;
  888. //tinyMCE.debug(e.type + " " + e.target.nodeName + " " + (e.relatedTarget ? e.relatedTarget.nodeName : ""));
  889. if (tinyMCE.executeCallback(tinyMCE.selectedInstance, 'handle_event_callback', 'handleEvent', e))
  890. return false;
  891. switch (e.type) {
  892. case "beforedeactivate": // Was added due to bug #1439953
  893. case "blur":
  894. if (tinyMCE.selectedInstance)
  895. tinyMCE.selectedInstance.execCommand('mceEndTyping');
  896. tinyMCE.hideMenus();
  897. return;
  898. // Workaround for drag drop/copy paste base href bug
  899. case "drop":
  900. case "beforepaste":
  901. if (tinyMCE.selectedInstance)
  902. tinyMCE.selectedInstance.setBaseHREF(null);
  903. // Fixes odd MSIE bug where drag/droping elements in a iframe with height 100% breaks
  904. // This logic forces the width/height to be in pixels while the user is drag/dropping
  905. if (tinyMCE.isRealIE) {
  906. var ife = tinyMCE.selectedInstance.iframeElement;
  907. /*if (ife.style.width.indexOf('%') != -1) {
  908. ife._oldWidth = ife.width.height;
  909. ife.style.width = ife.clientWidth;
  910. }*/
  911. if (ife.style.height.indexOf('%') != -1) {
  912. ife._oldHeight = ife.style.height;
  913. ife.style.height = ife.clientHeight;
  914. }
  915. }
  916. window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings['base_href']);tinyMCE._resetIframeHeight();", 1);
  917. return;
  918. case "submit":
  919. tinyMCE.removeTinyMCEFormElements(tinyMCE.isMSIE ? window.event.srcElement : e.target);
  920. tinyMCE.triggerSave();
  921. tinyMCE.isNotDirty = true;
  922. return;
  923. case "reset":
  924. var formObj = tinyMCE.isIE ? window.event.srcElement : e.target;
  925. for (var i=0; i<document.forms.length; i++) {
  926. if (document.forms[i] == formObj)
  927. window.setTimeout('tinyMCE.resetForm(' + i + ');', 10);
  928. }
  929. return;
  930. case "keypress":
  931. if (inst && inst.handleShortcut(e))
  932. return false;
  933. if (e.target.editorId) {
  934. tinyMCE.instances[e.target.editorId].select();
  935. } else {
  936. if (e.target.ownerDocument.editorId)
  937. tinyMCE.instances[e.target.ownerDocument.editorId].select();
  938. }
  939. if (tinyMCE.selectedInstance)
  940. tinyMCE.selectedInstance.switchSettings();
  941. // Insert P element
  942. if ((tinyMCE.isGecko || tinyMCE.isOpera || tinyMCE.isSafari) && tinyMCE.settings['force_p_newlines'] && e.keyCode == 13 && !e.shiftKey) {
  943. // Insert P element instead of BR
  944. if (TinyMCE_ForceParagraphs._insertPara(tinyMCE.selectedInstance, e)) {
  945. // Cancel event
  946. tinyMCE.execCommand("mceAddUndoLevel");
  947. return tinyMCE.cancelEvent(e);
  948. }
  949. }
  950. // Handle backspace
  951. if ((tinyMCE.isGecko && !tinyMCE.isSafari) && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {
  952. // Insert P element instead of BR
  953. if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {
  954. // Cancel event
  955. tinyMCE.execCommand("mceAddUndoLevel");
  956. return tinyMCE.cancelEvent(e);
  957. }
  958. }
  959. // Return key pressed
  960. if (tinyMCE.isIE && tinyMCE.settings['force_br_newlines'] && e.keyCode == 13) {
  961. if (e.target.editorId)
  962. tinyMCE.instances[e.target.editorId].select();
  963. if (tinyMCE.selectedInstance) {
  964. var sel = tinyMCE.selectedInstance.getDoc().selection;
  965. var rng = sel.createRange();
  966. if (tinyMCE.getParentElement(rng.parentElement(), "li") != null)
  967. return false;
  968. // Cancel event
  969. e.returnValue = false;
  970. e.cancelBubble = true;
  971. // Insert BR element
  972. rng.pasteHTML("<br />");
  973. rng.collapse(false);
  974. rng.select();
  975. tinyMCE.execCommand("mceAddUndoLevel");
  976. tinyMCE.triggerNodeChange(false);
  977. return false;
  978. }
  979. }
  980. // Backspace or delete
  981. if (e.keyCode == 8 || e.keyCode == 46) {
  982. tinyMCE.selectedElement = e.target;
  983. tinyMCE.linkElement = tinyMCE.getParentElement(e.target, "a");
  984. tinyMCE.imgElement = tinyMCE.getParentElement(e.target, "img");
  985. tinyMCE.triggerNodeChange(false);
  986. }
  987. return false;
  988. break;
  989. case "keyup":
  990. case "keydown":
  991. tinyMCE.hideMenus();
  992. tinyMCE.hasMouseMoved = false;
  993. if (inst && inst.handleShortcut(e))
  994. return false;
  995. if (e.target.editorId)
  996. tinyMCE.instances[e.target.editorId].select();
  997. if (tinyMCE.selectedInstance)
  998. tinyMCE.selectedInstance.switchSettings();
  999. var inst = tinyMCE.selectedInstance;
  1000. // Handle backspace
  1001. if (tinyMCE.isGecko && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {
  1002. // Insert P element instead of BR
  1003. if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {
  1004. // Cancel event
  1005. tinyMCE.execCommand("mceAddUndoLevel");
  1006. e.preventDefault();
  1007. return false;
  1008. }
  1009. }
  1010. tinyMCE.selectedElement = null;
  1011. tinyMCE.selectedNode = null;
  1012. var elm = tinyMCE.selectedInstance.getFocusElement();
  1013. tinyMCE.linkElement = tinyMCE.getParentElement(elm, "a");
  1014. tinyMCE.imgElement = tinyMCE.getParentElement(elm, "img");
  1015. tinyMCE.selectedElement = elm;
  1016. // Update visualaids on tabs
  1017. if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9)
  1018. tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);
  1019. // Fix empty elements on return/enter, check where enter occured
  1020. if (tinyMCE.isIE && e.type == "keydown" && e.keyCode == 13)
  1021. tinyMCE.enterKeyElement = tinyMCE.selectedInstance.getFocusElement();
  1022. // Fix empty elements on return/enter
  1023. if (tinyMCE.isIE && e.type == "keyup" && e.keyCode == 13) {
  1024. var elm = tinyMCE.enterKeyElement;
  1025. if (elm) {
  1026. var re = new RegExp('^HR|IMG|BR$','g'); // Skip these
  1027. var dre = new RegExp('^H[1-6]$','g'); // Add double on these
  1028. if (!elm.hasChildNodes() && !re.test(elm.nodeName)) {
  1029. if (dre.test(elm.nodeName))
  1030. elm.innerHTML = "&nbsp;&nbsp;";
  1031. else
  1032. elm.innerHTML = "&nbsp;";
  1033. }
  1034. }
  1035. }
  1036. // Check if it's a position key
  1037. var keys = tinyMCE.posKeyCodes;
  1038. var posKey = false;
  1039. for (var i=0; i<keys.length; i++) {
  1040. if (keys[i] == e.keyCode) {
  1041. posKey = true;
  1042. break;
  1043. }
  1044. }
  1045. // MSIE custom key handling
  1046. if (tinyMCE.isIE && tinyMCE.settings['custom_undo_redo']) {
  1047. var keys = new Array(8,46); // Backspace,Delete
  1048. for (var i=0; i<keys.length; i++) {
  1049. if (keys[i] == e.keyCode) {
  1050. if (e.type == "keyup")
  1051. tinyMCE.triggerNodeChange(false);
  1052. }
  1053. }
  1054. }
  1055. // If Ctrl key
  1056. if (e.keyCode == 17)
  1057. return true;
  1058. // Handle Undo/Redo when typing content
  1059. if (tinyMCE.isGecko) {
  1060. // Start typing (not a position key or ctrl key, but ctrl+x and ctrl+p is ok)
  1061. if (!posKey && e.type == "keyup" && !e.ctrlKey || (e.ctrlKey && (e.keyCode == 86 || e.keyCode == 88)))
  1062. tinyMCE.execCommand("mceStartTyping");
  1063. } else {
  1064. // IE seems to be working better with this setting
  1065. if (!posKey && e.type == "keyup")
  1066. tinyMCE.execCommand("mceStartTyping");
  1067. }
  1068. // Store undo bookmark
  1069. if (e.type == "keydown" && (posKey || e.ctrlKey) && inst)
  1070. inst.undoBookmark = inst.selection.getBookmark();
  1071. // End typing (position key) or some Ctrl event
  1072. if (e.type == "keyup" && (posKey || e.ctrlKey))
  1073. tinyMCE.execCommand("mceEndTyping");
  1074. if (posKey && e.type == "keyup")
  1075. tinyMCE.triggerNodeChange(false);
  1076. if (tinyMCE.isIE && e.ctrlKey)
  1077. window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
  1078. break;
  1079. case "mousedown":
  1080. case "mouseup":
  1081. case "click":
  1082. case "dblclick":
  1083. case "focus":
  1084. tinyMCE.hideMenus();
  1085. if (tinyMCE.selectedInstance) {
  1086. tinyMCE.selectedInstance.switchSettings();
  1087. tinyMCE.selectedInstance.isFocused = true;
  1088. }
  1089. // Check instance event trigged on
  1090. var targetBody = tinyMCE.getParentElement(e.target, "html");
  1091. for (var instanceName in tinyMCE.instances) {
  1092. if (!tinyMCE.isInstance(tinyMCE.instances[instanceName]))
  1093. continue;
  1094. var inst = tinyMCE.instances[instanceName];
  1095. // Reset design mode if lost (on everything just in case)
  1096. inst.autoResetDesignMode();
  1097. // Use HTML element since users might click outside of body element
  1098. if (inst.getBody().parentNode == targetBody) {
  1099. inst.select();
  1100. tinyMCE.selectedElement = e.target;
  1101. tinyMCE.linkElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "a");
  1102. tinyMCE.imgElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "img");
  1103. break;
  1104. }
  1105. }
  1106. // Add first bookmark location
  1107. if (!tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark && (e.type == "mouseup" || e.type == "dblclick"))
  1108. tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark = tinyMCE.selectedInstance.selection.getBookmark();
  1109. // Reset selected node
  1110. if (e.type != "focus")
  1111. tinyMCE.selectedNode = null;
  1112. tinyMCE.triggerNodeChange(false);
  1113. tinyMCE.execCommand("mceEndTyping");
  1114. if (e.type == "mouseup")
  1115. tinyMCE.execCommand("mceAddUndoLevel");
  1116. // Just in case
  1117. if (!tinyMCE.selectedInstance && e.target.editorId)
  1118. tinyMCE.instances[e.target.editorId].select();
  1119. return false;
  1120. break;
  1121. }
  1122. },
  1123. getButtonHTML : function(id, lang, img, cmd, ui, val) {
  1124. var h = '', m, x, io = '';
  1125. cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
  1126. if (typeof(ui) != "undefined" && ui != null)
  1127. cmd += ',' + ui;
  1128. if (typeof(val) != "undefined" && val != null)
  1129. cmd += ",'" + val + "'";
  1130. cmd += ');';
  1131. // Patch for IE7 bug with hover out not restoring correctly
  1132. if (tinyMCE.isRealIE)
  1133. io = 'onmouseover="tinyMCE.lastHover = this;"';
  1134. // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
  1135. if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = this.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
  1136. // Tiled button
  1137. x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
  1138. h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceTiledButton mceButtonNormal" target="_self">';
  1139. h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" title="{$' + lang + '}" />';
  1140. h += '</a>';
  1141. } else {
  1142. // Normal button
  1143. h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceButtonNormal" target="_self">';
  1144. h += '<img src="' + img + '" title="{$' + lang + '}" />';
  1145. h += '</a>';
  1146. }
  1147. return h;
  1148. },
  1149. getMenuButtonHTML : function(id, lang, img, mcmd, cmd, ui, val) {
  1150. var h = '', m, x;
  1151. mcmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + mcmd + '\');';
  1152. cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
  1153. if (typeof(ui) != "undefined" && ui != null)
  1154. cmd += ',' + ui;
  1155. if (typeof(val) != "undefined" && val != null)
  1156. cmd += ",'" + val + "'";
  1157. cmd += ');';
  1158. // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
  1159. if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = tinyMCE.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
  1160. x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
  1161. if (tinyMCE.isRealIE)
  1162. h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';
  1163. else
  1164. h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton">';
  1165. h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceTiledButton mceMenuButtonNormal" target="_self">';
  1166. h += '<img src="{$themeurl}/images/spacer.gif" style="width: 20px; height: 20px; background-position: ' + x + 'px 0" title="{$' + lang + '}" /></a>';
  1167. h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
  1168. h += '</a></span>';
  1169. } else {
  1170. if (tinyMCE.isRealIE)
  1171. h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';
  1172. else
  1173. h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton">';
  1174. h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">';
  1175. h += '<img src="' + img + '" title="{$' + lang + '}" /></a>';
  1176. h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
  1177. h += '</a></span>';
  1178. }
  1179. return h;
  1180. },
  1181. _menuButtonEvent : function(e, o) {
  1182. if (o.className == 'mceMenuButtonFocus')
  1183. return;
  1184. if (e == 'over')
  1185. o.className = o.className + ' mceMenuHover';
  1186. else
  1187. o.className = o.className.replace(/\s.*$/, '');
  1188. },
  1189. addButtonMap : function(m) {
  1190. var i, a = m.replace(/\s+/, '').split(',');
  1191. for (i=0; i<a.length; i++)
  1192. this.buttonMap[a[i]] = i;
  1193. },
  1194. submitPatch : function() {
  1195. tinyMCE.removeTinyMCEFormElements(this);
  1196. tinyMCE.triggerSave();
  1197. tinyMCE.isNotDirty = true;
  1198. this.mceOldSubmit();
  1199. },
  1200. onLoad : function() {
  1201. var r;
  1202. // Wait for everything to be loaded first
  1203. if (tinyMCE.settings.strict_loading_mode && this.loadingIndex != -1) {
  1204. window.setTimeout('tinyMCE.onLoad();', 1);
  1205. return;
  1206. }
  1207. if (tinyMCE.isRealIE && window.event.type == "readystatechange" && document.readyState != "complete")
  1208. return true;
  1209. if (tinyMCE.isLoaded)
  1210. return true;
  1211. tinyMCE.isLoaded = true;
  1212. // IE produces JS error if TinyMCE is placed in a frame
  1213. // It seems to have something to do with the selection not beeing
  1214. // correctly initialized in IE so this hack solves the problem
  1215. if (tinyMCE.isRealIE && document.body) {
  1216. r = document.body.createTextRange();
  1217. r.collapse(true);
  1218. r.select();
  1219. }
  1220. tinyMCE.dispatchCallback(null, 'onpageload', 'onPageLoad');
  1221. for (var c=0; c<tinyMCE.configs.length; c++) {
  1222. tinyMCE.settings = tinyMCE.configs[c];
  1223. var selector = tinyMCE.getParam("editor_selector");
  1224. var deselector = tinyMCE.getParam("editor_deselector");
  1225. var elementRefAr = new Array();
  1226. // Add submit triggers
  1227. if (document.forms && tinyMCE.settings['add_form_submit_trigger'] && !tinyMCE.submitTriggers) {
  1228. for (var i=0; i<document.forms.length; i++) {
  1229. var form = document.forms[i];
  1230. tinyMCE.addEvent(form, "submit", TinyMCE_Engine.prototype.handleEvent);
  1231. tinyMCE.addEvent(form, "reset", TinyMCE_Engine.prototype.handleEvent);
  1232. tinyMCE.submitTriggers = true; // Do it only once
  1233. // Patch the form.submit function
  1234. if (tinyMCE.settings['submit_patch']) {
  1235. try {
  1236. form.mceOldSubmit = form.submit;
  1237. form.submit = TinyMCE_Engine.prototype.submitPatch;
  1238. } catch (e) {
  1239. // Do nothing
  1240. }
  1241. }
  1242. }
  1243. }
  1244. // Add editor instances based on mode
  1245. var mode = tinyMCE.settings['mode'];
  1246. switch (mode) {
  1247. case "exact":
  1248. var elements = tinyMCE.getParam('elements', '', true, ',');
  1249. for (var i=0; i<elements.length; i++) {
  1250. var element = tinyMCE._getElementById(elements[i]);
  1251. var trigger = element ? element.getAttribute(tinyMCE.settings['textarea_trigger']) : "";
  1252. if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(element, "class")))
  1253. continue;
  1254. if (trigger == "false")
  1255. continue;
  1256. if ((tinyMCE.settings['ask'] || tinyMCE.settings['convert_on_click']) && element) {
  1257. elementRefAr[elementRefAr.length] = element;
  1258. continue;
  1259. }
  1260. if (element)
  1261. tinyMCE.addMCEControl(element, elements[i]);
  1262. else if (tinyMCE.settings['debug'])
  1263. alert("Error: Could not find element by id or name: " + elements[i]);
  1264. }
  1265. break;
  1266. case "specific_textareas":
  1267. case "textareas":
  1268. var nodeList = document.getElementsByTagName("textarea");
  1269. for (var i=0; i<nodeList.length; i++) {
  1270. var elm = nodeList.item(i);
  1271. var trigger = elm.getAttribute(tinyMCE.settings['textarea_trigger']);
  1272. if (selector != '' && !new RegExp('\\b' + selector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
  1273. continue;
  1274. if (selector != '')
  1275. trigger = selector != "" ? "true" : "";
  1276. if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
  1277. continue;
  1278. if ((mode == "specific_textareas" && trigger == "true") || (mode == "textareas" && trigger != "false"))
  1279. elementRefAr[elementRefAr.length] = elm;
  1280. }
  1281. break;
  1282. }
  1283. for (var i=0; i<elementRefAr.length; i++) {
  1284. var element = elementRefAr[i];
  1285. var elementId = element.name ? element.name : element.id;
  1286. if (tinyMCE.settings['ask'] || tinyMCE.settings['convert_on_click']) {
  1287. // Focus breaks in Mozilla
  1288. if (tinyMCE.isGecko) {
  1289. var settings = tinyMCE.settings;
  1290. tinyMCE.addEvent(element, "focus", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
  1291. if (element.nodeName != "TEXTAREA" && element.nodeName != "INPUT")
  1292. tinyMCE.addEvent(element, "click", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
  1293. // tinyMCE.addEvent(element, "mouseover", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
  1294. } else {
  1295. var settings = tinyMCE.settings;
  1296. tinyMCE.addEvent(element, "focus", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
  1297. tinyMCE.addEvent(element, "click", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
  1298. // tinyMCE.addEvent(element, "mouseenter", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
  1299. }
  1300. } else
  1301. tinyMCE.addMCEControl(element, elementId);
  1302. }
  1303. // Handle auto focus
  1304. if (tinyMCE.settings['auto_focus']) {
  1305. window.setTimeout(function () {
  1306. var inst = tinyMCE.getInstanceById(tinyMCE.settings['auto_focus']);
  1307. inst.selection.selectNode(inst.getBody(), true, true);
  1308. inst.contentWindow.focus();
  1309. }, 100);
  1310. }
  1311. tinyMCE.dispatchCallback(null, 'oninit', 'onInit');
  1312. }
  1313. },
  1314. isInstance : function(o) {
  1315. return o != null && typeof(o) == "object" && o.isTinyMCE_Control;
  1316. },
  1317. getParam : function(name, default_value, strip_whitespace, split_chr) {
  1318. var value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];
  1319. // Fix bool values
  1320. if (value == "true" || value == "false")
  1321. return (value == "true");
  1322. if (strip_whitespace)
  1323. value = tinyMCE.regexpReplace(value, "[ \t\r\n]", "");
  1324. if (typeof(split_chr) != "undefined" && split_chr != null) {
  1325. value = value.split(split_chr);
  1326. var outArray = new Array();
  1327. for (var i=0; i<value.length; i++) {
  1328. if (value[i] && value[i] != "")
  1329. outArray[outArray.length] = value[i];
  1330. }
  1331. value = outArray;
  1332. }
  1333. return value;
  1334. },
  1335. getLang : function(name, default_value, parse_entities, va) {
  1336. var v = (typeof(tinyMCELang[name]) == "undefined") ? default_value : tinyMCELang[name], n;
  1337. if (parse_entities)
  1338. v = tinyMCE.entityDecode(v);
  1339. if (va) {
  1340. for (n in va)
  1341. v = this.replaceVar(v, n, va[n]);
  1342. }
  1343. return v;
  1344. },
  1345. entityDecode : function(s) {
  1346. var e = document.createElement("div");
  1347. e.innerHTML = s;
  1348. return e.firstChild.nodeValue;
  1349. },
  1350. addToLang : function(prefix, ar) {
  1351. for (var key in ar) {
  1352. if (typeof(ar[key]) == 'function')
  1353. continue;
  1354. tinyMCELang[(key.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix != '' ? (prefix + "_") : '') + key] = ar[key];
  1355. }
  1356. this.loadNextScript();
  1357. // for (var key in ar)
  1358. // tinyMCELang[(key.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix != '' ? (prefix + "_") : '') + key] = "|" + ar[key] + "|";
  1359. },
  1360. triggerNodeChange : function(focus, setup_content) {
  1361. var elm, inst, editorId, undoIndex = -1, undoLevels = -1, doc, anySelection = false, st;
  1362. if (tinyMCE.selectedInstance) {
  1363. inst = tinyMCE.selectedInstance;
  1364. elm = (typeof(setup_content) != "undefined" && setup_content) ? tinyMCE.selectedElement : inst.getFocusElement();
  1365. /* if (elm == inst.lastTriggerEl)
  1366. return;
  1367. inst.lastTriggerEl = elm;*/
  1368. editorId = inst.editorId;
  1369. st = inst.selection.getSelectedText();
  1370. if (tinyMCE.settings.auto_resize)
  1371. inst.resizeToContent();
  1372. if (setup_content && tinyMCE.isGecko && inst.isHidden())
  1373. elm = inst.getBody();
  1374. inst.switchSettings();
  1375. if (tinyMCE.selectedElement)
  1376. anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (st && st.length > 0);
  1377. if (tinyMCE.settings['custom_undo_redo']) {
  1378. undoIndex = inst.undoRedo.undoIndex;
  1379. undoLevels = inst.undoRedo.undoLevels.length;
  1380. }
  1381. tinyMCE.dispatchCallback(inst, 'handle_node_change_callback', 'handleNodeChange', editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection, setup_content);
  1382. }
  1383. if (this.selectedInstance && (typeof(focus) == "undefined" || focus))
  1384. this.selectedInstance.contentWindow.focus();
  1385. },
  1386. _customCleanup : function(inst, type, content) {
  1387. var pl, po, i;
  1388. // Call custom cleanup
  1389. var customCleanup = tinyMCE.settings['cleanup_callback'];
  1390. if (customCleanup != "" && eval("typeof(" + customCleanup + ")") != "undefined")
  1391. content = eval(customCleanup + "(type, content, inst);");
  1392. // Trigger theme cleanup
  1393. po = tinyMCE.themes[tinyMCE.settings['theme']];
  1394. if (po && po.cleanup)
  1395. content = po.cleanup(type, content, inst);
  1396. // Trigger plugin cleanups
  1397. pl = inst.plugins;
  1398. for (i=0; i<pl.length; i++) {
  1399. po = tinyMCE.plugins[pl[i]];
  1400. if (po && po.cleanup)
  1401. content = po.cleanup(type, content, inst);
  1402. }
  1403. return content;
  1404. },
  1405. setContent : function(h) {
  1406. if (tinyMCE.selectedInstance) {
  1407. tinyMCE.selectedInstance.execCommand('mceSetContent', false, h);
  1408. tinyMCE.selectedInstance.repaint();
  1409. }
  1410. },
  1411. importThemeLanguagePack : function(name) {
  1412. if (typeof(name) == "undefined")
  1413. name = tinyMCE.settings['theme'];
  1414. tinyMCE.loadScript(tinyMCE.baseURL + '/themes/' + name + '/langs/' + tinyMCE.settings['language'] + '.js');
  1415. },
  1416. importPluginLanguagePack : function(name) {
  1417. var b = tinyMCE.baseURL + '/plugins/' + name;
  1418. if (this.plugins[name])
  1419. b = this.plugins[name].baseURL;
  1420. tinyMCE.loadScript(b + '/langs/' + tinyMCE.settings['language'] + '.js');
  1421. },
  1422. applyTemplate : function(h, as) {
  1423. return h.replace(new RegExp('\\{\\$([a-z0-9_]+)\\}', 'gi'), function(m, s) {
  1424. if (s.indexOf('lang_') == 0 && tinyMCELang[s])
  1425. return tinyMCELang[s];
  1426. if (as && as[s])
  1427. return as[s];
  1428. if (tinyMCE.settings[s])
  1429. return tinyMCE.settings[s];
  1430. if (m == 'themeurl')
  1431. return tinyMCE.themeURL;
  1432. return m;
  1433. });
  1434. },
  1435. replaceVar : function(h, r, v) {
  1436. return h.replace(new RegExp('{\\\$' + r + '}', 'g'), v);
  1437. },
  1438. openWindow : function(template, args) {
  1439. var html, width, height, x, y, resizable, scrollbars, url;
  1440. args = !args ? {} : args;
  1441. args['mce_template_file'] = template['file'];
  1442. args['mce_width'] = template['width'];
  1443. args['mce_height'] = template['height'];
  1444. tinyMCE.windowArgs = args;
  1445. html = template['html'];
  1446. if (!(width = parseInt(template['width'])))
  1447. width = 320;
  1448. if (!(height = parseInt(template['height'])))
  1449. height = 200;
  1450. // Add to height in M$ due to SP2 WHY DON'T YOU GUYS IMPLEMENT innerWidth of windows!!
  1451. if (tinyMCE.isIE)
  1452. height += 40;
  1453. else
  1454. height += 20;
  1455. x = parseInt(screen.width / 2.0) - (width / 2.0);
  1456. y = parseInt(screen.height / 2.0) - (height / 2.0);
  1457. resizable = (args && args['resizable']) ? args['resizable'] : "no";
  1458. scrollbars = (args && args['scrollbars']) ? args['scrollbars'] : "no";
  1459. if (template['file'].charAt(0) != '/' && template['file'].indexOf('://') == -1)
  1460. url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template['file'];
  1461. else
  1462. url = template['file'];
  1463. // Replace all args as variables in URL
  1464. for (var name in args) {
  1465. if (typeof(args[name]) == 'function')
  1466. continue;
  1467. url = tinyMCE.replaceVar(url, name, escape(args[name]));
  1468. }
  1469. if (html) {
  1470. html = tinyMCE.replaceVar(html, "css", this.settings['popups_css']);
  1471. html = tinyMCE.applyTemplate(html, args);
  1472. var win = window.open("", "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,minimizable=" + resizable + ",modal=yes,width=" + width + ",height=" + height + ",resizable=" + resizable);
  1473. if (win == null) {
  1474. alert(tinyMCELang['lang_popup_blocked']);
  1475. return;
  1476. }
  1477. win.document.write(html);
  1478. win.document.close();
  1479. win.resizeTo(width, height);
  1480. win.focus();
  1481. } else {
  1482. if ((tinyMCE.isRealIE) && resizable != 'yes' && tinyMCE.settings["dialog_type"] == "modal") {
  1483. height += 10;
  1484. var features = "resizable:" + resizable
  1485. + ";scroll:"
  1486. + scrollbars + ";status:yes;center:yes;help:no;dialogWidth:"
  1487. + width + "px;dialogHeight:" + height + "px;";
  1488. window.showModalDialog(url, window, features);
  1489. } else {
  1490. var modal = (resizable == "yes") ? "no" : "yes";
  1491. if (tinyMCE.isGecko && tinyMCE.isMac)
  1492. modal = "no";
  1493. if (template['close_previous'] != "no")
  1494. try {tinyMCE.lastWindow.close();} catch (ex) {}
  1495. var win = window.open(url, "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=" + modal + ",minimizable=" + resizable + ",modal=" + modal + ",width=" + width + ",height=" + height + ",resizable=" + resizable);
  1496. if (win == null) {
  1497. alert(tinyMCELang['lang_popup_blocked']);
  1498. return;
  1499. }
  1500. if (template['close_previous'] != "no")
  1501. tinyMCE.lastWindow = win;
  1502. eval('try { win.resizeTo(width, height); } catch(e) { }');
  1503. // Make it bigger if statusbar is forced
  1504. if (tinyMCE.isGecko) {
  1505. if (win.document.defaultView.statusbar.visible)
  1506. win.resizeBy(0, tinyMCE.isMac ? 10 : 24);
  1507. }
  1508. win.focus();
  1509. }
  1510. }
  1511. },
  1512. closeWindow : function(win) {
  1513. win.close();
  1514. },
  1515. getVisualAidClass : function(class_name, state) {
  1516. var aidClass = tinyMCE.settings['visual_table_class'];
  1517. if (typeof(state) == "undefined")
  1518. state = tinyMCE.settings['visual'];
  1519. // Split
  1520. var classNames = new Array();
  1521. var ar = class_name.split(' ');
  1522. for (var i=0; i<ar.length; i++) {
  1523. if (ar[i] == aidClass)
  1524. ar[i] = "";
  1525. if (ar[i] != "")
  1526. classNames[classNames.length] = ar[i];
  1527. }
  1528. if (state)
  1529. classNames[classNames.length] = aidClass;
  1530. // Glue
  1531. var className = "";
  1532. for (var i=0; i<classNames.length; i++) {
  1533. if (i > 0)
  1534. className += " ";
  1535. className += classNames[i];
  1536. }
  1537. return className;
  1538. },
  1539. handleVisualAid : function(el, deep, state, inst, skip_dispatch) {
  1540. if (!el)
  1541. return;
  1542. if (!skip_dispatch)
  1543. tinyMCE.dispatchCallback(inst, 'handle_visual_aid_callback', 'handleVisualAid', el, deep, state, inst);
  1544. var tableElement = null;
  1545. switch (el.nodeName) {
  1546. case "TABLE":
  1547. var oldW = el.style.width;
  1548. var oldH = el.style.height;
  1549. var bo = tinyMCE.getAttrib(el, "border");
  1550. bo = bo == "" || bo == "0" ? true : false;
  1551. tinyMCE.setAttrib(el, "class", tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el, "class"), state && bo));
  1552. el.style.width = oldW;
  1553. el.style.height = oldH;
  1554. for (var y=0; y<el.rows.length; y++) {
  1555. for (var x=0; x<el.rows[y].cells.length; x++) {
  1556. var cn = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x], "class"), state && bo);
  1557. tinyMCE.setAttrib(el.rows[y].cells[x], "class", cn);
  1558. }
  1559. }
  1560. break;
  1561. case "A":
  1562. var anchorName = tinyMCE.getAttrib(el, "name");
  1563. if (anchorName != '' && state) {
  1564. el.title = anchorName;
  1565. tinyMCE.addCSSClass(el, 'mceItemAnchor');
  1566. } else if (anchorName != '' && !state)
  1567. el.className = '';
  1568. break;
  1569. }
  1570. if (deep && el.hasChildNodes()) {
  1571. for (var i=0; i<el.childNodes.length; i++)
  1572. tinyMCE.handleVisualAid(el.childNodes[i], deep, state, inst, true);
  1573. }
  1574. },
  1575. /*
  1576. applyClassesToFonts : function(doc, size) {
  1577. var f = doc.getElementsByTagName("font");
  1578. for (var i=0; i<f.length; i++) {
  1579. var s = tinyMCE.getAttrib(f[i], "size");
  1580. if (s != "")
  1581. tinyMCE.setAttrib(f[i], 'class', "mceItemFont" + s);
  1582. }
  1583. if (typeof(size) != "undefined") {
  1584. var css = "";
  1585. for (var x=0; x<doc.styleSheets.length; x++) {
  1586. for (var i=0; i<doc.styleSheets[x].rules.length; i++) {
  1587. if (doc.styleSheets[x].rules[i].selectorText == '#mceSpanFonts .mceItemFont' + size) {
  1588. css = doc.styleSheets[x].rules[i].style.cssText;
  1589. break;
  1590. }
  1591. }
  1592. if (css != "")
  1593. break;
  1594. }
  1595. if (doc.styleSheets[0].rules[0].selectorText == "FONT")
  1596. doc.styleSheets[0].removeRule(0);
  1597. doc.styleSheets[0].addRule("FONT", css, 0);
  1598. }
  1599. },
  1600. */
  1601. fixGeckoBaseHREFBug : function(m, e, h) {
  1602. var xsrc, xhref;
  1603. if (tinyMCE.isGecko) {
  1604. if (m == 1) {
  1605. h = h.replace(/\ssrc=/gi, " mce_tsrc=");
  1606. h = h.replace(/\shref=/gi, " mce_thref=");
  1607. return h;
  1608. } else {
  1609. // Why bother if there is no src or href broken
  1610. if (!new RegExp('(src|href)=', 'g').test(h))
  1611. return h;
  1612. // Restore src and href that gets messed up by Gecko
  1613. tinyMCE.selectElements(e, 'A,IMG,SELECT,AREA,IFRAME,BASE,INPUT,SCRIPT,EMBED,OBJECT,LINK', function (n) {
  1614. xsrc = tinyMCE.getAttrib(n, "mce_tsrc");
  1615. xhref = tinyMCE.getAttrib(n, "mce_thref");
  1616. if (xsrc != "") {
  1617. try {
  1618. n.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xsrc);
  1619. } catch (e) {
  1620. // Ignore, Firefox cast exception if local file wasn't found
  1621. }
  1622. n.removeAttribute("mce_tsrc");
  1623. }
  1624. if (xhref != "") {
  1625. try {
  1626. n.href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xhref);
  1627. } catch (e) {
  1628. // Ignore, Firefox cast exception if local file wasn't found
  1629. }
  1630. n.removeAttribute("mce_thref");
  1631. }
  1632. return false;
  1633. });
  1634. // Restore text/comment nodes
  1635. tinyMCE.selectNodes(e, function(n) {
  1636. if (n.nodeType == 3 || n.nodeType == 8) {
  1637. n.nodeValue = n.nodeValue.replace(/\smce_tsrc=/gi, " src=");
  1638. n.nodeValue = n.nodeValue.replace(/\smce_thref=/gi, " href=");
  1639. }
  1640. return false;
  1641. });
  1642. }
  1643. }
  1644. return h;
  1645. },
  1646. _setHTML : function(doc, html_content) {
  1647. // Force closed anchors open
  1648. //html_content = html_content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
  1649. html_content = tinyMCE.cleanupHTMLCode(html_content);
  1650. // Try innerHTML if it fails use pasteHTML in MSIE
  1651. try {
  1652. tinyMCE.setInnerHTML(doc.body, html_content);
  1653. } catch (e) {
  1654. if (this.isMSIE)
  1655. doc.body.createTextRange().pasteHTML(html_content);
  1656. }
  1657. // Content duplication bug fix
  1658. if (tinyMCE.isIE && tinyMCE.settings['fix_content_duplication']) {
  1659. // Remove P elements in P elements
  1660. var paras = doc.getElementsByTagName("P");
  1661. for (var i=0; i<paras.length; i++) {
  1662. var node = paras[i];
  1663. while ((node = node.parentNode) != null) {
  1664. if (node.nodeName == "P")
  1665. node.outerHTML = node.innerHTML;
  1666. }
  1667. }
  1668. // Content duplication bug fix (Seems to be word crap)
  1669. var html = doc.body.innerHTML;
  1670. /*
  1671. if (html.indexOf('="mso') != -1) {
  1672. for (var i=0; i<doc.body.all.length; i++) {
  1673. var el = doc.body.all[i];
  1674. el.removeAttribute("className","",0);
  1675. el.removeAttribute("style","",0);
  1676. }
  1677. html = doc.body.innerHTML;
  1678. html = tinyMCE.regexpReplace(html, "<o:p><\/o:p>", "<br />");
  1679. html = tinyMCE.regexpReplace(html, "<o:p>&nbsp;<\/o:p>", "");
  1680. html = tinyMCE.regexpReplace(html, "<st1:.*?>", "");
  1681. html = tinyMCE.regexpReplace(html, "<p><\/p>", "");
  1682. html = tinyMCE.regexpReplace(html, "<p><\/p>\r\n<p><\/p>", "");
  1683. html = tinyMCE.regexpReplace(html, "<p>&nbsp;<\/p>", "<br />");
  1684. html = tinyMCE.regexpReplace(html, "<p>\s*(<p>\s*)?", "<p>");
  1685. html = tinyMCE.regexpReplace(html, "<\/p>\s*(<\/p>\s*)?", "</p>");
  1686. }*/
  1687. // Always set the htmlText output
  1688. tinyMCE.setInnerHTML(doc.body, html);
  1689. }
  1690. tinyMCE.cleanupAnchors(doc);
  1691. if (tinyMCE.getParam("convert_fonts_to_spans"))
  1692. tinyMCE.convertSpansToFonts(doc);
  1693. },
  1694. getEditorId : function(form_element) {
  1695. var inst = this.getInstanceById(form_element);
  1696. if (!inst)
  1697. return null;
  1698. return inst.editorId;
  1699. },
  1700. getInstanceById : function(editor_id) {
  1701. var inst = this.instances[editor_id];
  1702. if (!inst) {
  1703. for (var n in tinyMCE.instances) {
  1704. var instance = tinyMCE.instances[n];
  1705. if (!tinyMCE.isInstance(instance))
  1706. continue;
  1707. if (instance.formTargetElementId == editor_id) {
  1708. inst = instance;
  1709. break;
  1710. }
  1711. }
  1712. }
  1713. return inst;
  1714. },
  1715. queryInstanceCommandValue : function(editor_id, command) {
  1716. var inst = tinyMCE.getInstanceById(editor_id);
  1717. if (inst)
  1718. return inst.queryCommandValue(command);
  1719. return false;
  1720. },
  1721. queryInstanceCommandState : function(editor_id, command) {
  1722. var inst = tinyMCE.getInstanceById(editor_id);
  1723. if (inst)
  1724. return inst.queryCommandState(command);
  1725. return null;
  1726. },
  1727. setWindowArg : function(n, v) {
  1728. this.windowArgs[n] = v;
  1729. },
  1730. getWindowArg : function(n, d) {
  1731. return (typeof(this.windowArgs[n]) == "undefined") ? d : this.windowArgs[n];
  1732. },
  1733. getCSSClasses : function(editor_id, doc) {
  1734. var inst = tinyMCE.getInstanceById(editor_id);
  1735. // Is cached, use that
  1736. if (inst && inst.cssClasses.length > 0)
  1737. return inst.cssClasses;
  1738. if (typeof(editor_id) == "undefined" && typeof(doc) == "undefined") {
  1739. var instance;
  1740. for (var instanceName in tinyMCE.instances) {
  1741. instance = tinyMCE.instances[instanceName];
  1742. if (!tinyMCE.isInstance(instance))
  1743. continue;
  1744. break;
  1745. }
  1746. doc = instance.getDoc();
  1747. }
  1748. if (typeof(doc) == "undefined") {
  1749. var instance = tinyMCE.getInstanceById(editor_id);
  1750. doc = instance.getDoc();
  1751. }
  1752. if (doc) {
  1753. var styles = doc.styleSheets;
  1754. if (styles && styles.length > 0) {
  1755. for (var x=0; x<styles.length; x++) {
  1756. var csses = null;
  1757. // Just ignore any errors
  1758. eval("try {var csses = tinyMCE.isIE ? doc.styleSheets(" + x + ").rules : styles[" + x + "].cssRules;} catch(e) {}");
  1759. if (!csses)
  1760. return new Array();
  1761. for (var i=0; i<csses.length; i++) {
  1762. var selectorText = csses[i].selectorText;
  1763. // Can be multiple rules per selector
  1764. if (selectorText) {
  1765. var rules = selectorText.split(',');
  1766. for (var c=0; c<rules.length; c++) {
  1767. var rule = rules[c];
  1768. // Strip spaces between selectors
  1769. while (rule.indexOf(' ') == 0)
  1770. rule = rule.substring(1);
  1771. // Invalid rule
  1772. if (rule.indexOf(' ') != -1 || rule.indexOf(':') != -1 || rule.indexOf('mceItem') != -1)
  1773. continue;
  1774. if (rule.indexOf(tinyMCE.settings['visual_table_class']) != -1 || rule.indexOf('mceEditable') != -1 || rule.indexOf('mceNonEditable') != -1)
  1775. continue;
  1776. // Is class rule
  1777. if (rule.indexOf('.') != -1) {
  1778. var cssClass = rule.substring(rule.indexOf('.') + 1);
  1779. var addClass = true;
  1780. for (var p=0; p<inst.cssClasses.length && addClass; p++) {
  1781. if (inst.cssClasses[p] == cssClass)
  1782. addClass = false;
  1783. }
  1784. if (addClass)
  1785. inst.cssClasses[inst.cssClasses.length] = cssClass;
  1786. }
  1787. }
  1788. }
  1789. }
  1790. }
  1791. }
  1792. }
  1793. return inst.cssClasses;
  1794. },
  1795. regexpReplace : function(in_str, reg_exp, replace_str, opts) {
  1796. if (in_str == null)
  1797. return in_str;
  1798. if (typeof(opts) == "undefined")
  1799. opts = 'g';
  1800. var re = new RegExp(reg_exp, opts);
  1801. return in_str.replace(re, replace_str);
  1802. },
  1803. trim : function(s) {
  1804. return s.replace(/^\s*|\s*$/g, "");
  1805. },
  1806. cleanupEventStr : function(s) {
  1807. s = "" + s;
  1808. s = s.replace('function anonymous()\n{\n', '');
  1809. s = s.replace('\n}', '');
  1810. s = s.replace(/^return true;/gi, ''); // Remove event blocker
  1811. return s;
  1812. },
  1813. getControlHTML : function(c) {
  1814. var i, l, n, o, v, rtl = tinyMCE.getLang('lang_dir') == 'rtl';
  1815. l = tinyMCE.plugins;
  1816. for (n in l) {
  1817. o = l[n];
  1818. if (o.getControlHTML && (v = o.getControlHTML(c)) != '') {
  1819. if (rtl)
  1820. return '<span dir="rtl">' + tinyMCE.replaceVar(v, "pluginurl", o.baseURL) + '</span>';
  1821. return tinyMCE.replaceVar(v, "pluginurl", o.baseURL);
  1822. }
  1823. }
  1824. o = tinyMCE.themes[tinyMCE.settings['theme']];
  1825. if (o.getControlHTML && (v = o.getControlHTML(c)) != '') {
  1826. if (rtl)
  1827. return '<span dir="rtl">' + v + '</span>';
  1828. return v;
  1829. }
  1830. return '';
  1831. },
  1832. evalFunc : function(f, idx, a, o) {
  1833. o = !o ? window : o;
  1834. f = typeof(f) == 'function' ? f : o[f];
  1835. return f.apply(o, Array.prototype.slice.call(a, idx));
  1836. },
  1837. dispatchCallback : function(i, p, n) {
  1838. return this.callFunc(i, p, n, 0, this.dispatchCallback.arguments);
  1839. },
  1840. executeCallback : function(i, p, n) {
  1841. return this.callFunc(i, p, n, 1, this.executeCallback.arguments);
  1842. },
  1843. execCommandCallback : function(i, p, n) {
  1844. return this.callFunc(i, p, n, 2, this.execCommandCallback.arguments);
  1845. },
  1846. callFunc : function(ins, p, n, m, a) {
  1847. var l, i, on, o, s, v;
  1848. s = m == 2;
  1849. l = tinyMCE.getParam(p, '');
  1850. if (l != '' && (v = tinyMCE.evalFunc(l, 3, a)) == s && m > 0)
  1851. return true;
  1852. if (ins != null) {
  1853. for (i=0, l = ins.plugins; i<l.length; i++) {
  1854. o = tinyMCE.plugins[l[i]];
  1855. if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)
  1856. return true;
  1857. }
  1858. }
  1859. l = tinyMCE.themes;
  1860. for (on in l) {
  1861. o = l[on];
  1862. if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)
  1863. return true;
  1864. }
  1865. return false;
  1866. },
  1867. xmlEncode : function(s, skip_apos) {
  1868. return s ? ('' + s).replace(!skip_apos ? this.xmlEncodeAposRe : this.xmlEncodeRe, function (c, b) {
  1869. switch (c) {
  1870. case '&':
  1871. return '&amp;';
  1872. case '"':
  1873. return '&quot;';
  1874. case '\'':
  1875. return '&#39;'; // &apos; is not working in MSIE
  1876. case '<':
  1877. return '&lt;';
  1878. case '>':
  1879. return '&gt;';
  1880. }
  1881. return c;
  1882. }) : s;
  1883. },
  1884. extend : function(p, np) {
  1885. var o = {};
  1886. o.parent = p;
  1887. for (n in p)
  1888. o[n] = p[n];
  1889. for (n in np)
  1890. o[n] = np[n];
  1891. return o;
  1892. },
  1893. hideMenus : function() {
  1894. var e = tinyMCE.lastSelectedMenuBtn;
  1895. if (tinyMCE.lastMenu) {
  1896. tinyMCE.lastMenu.hide();
  1897. tinyMCE.lastMenu = null;
  1898. }
  1899. if (e) {
  1900. tinyMCE.switchClass(e, tinyMCE.lastMenuBtnClass);
  1901. tinyMCE.lastSelectedMenuBtn = null;
  1902. }
  1903. }
  1904. };
  1905. // Global instances
  1906. var TinyMCE = TinyMCE_Engine; // Compatiblity with gzip compressors
  1907. var tinyMCE = new TinyMCE_Engine();
  1908. var tinyMCELang = {};
  1909. /* file:jscripts/tiny_mce/classes/TinyMCE_Control.class.js */
  1910. function TinyMCE_Control(settings) {
  1911. var t, i, to, fu, p, x, fn, fu, pn, s = settings;
  1912. this.undoRedoLevel = true;
  1913. this.isTinyMCE_Control = true;
  1914. // Default settings
  1915. this.settings = s;
  1916. this.settings['theme'] = tinyMCE.getParam("theme", "default");
  1917. this.settings['width'] = tinyMCE.getParam("width", -1);
  1918. this.settings['height'] = tinyMCE.getParam("height", -1);
  1919. this.selection = new TinyMCE_Selection(this);
  1920. this.undoRedo = new TinyMCE_UndoRedo(this);
  1921. this.cleanup = new TinyMCE_Cleanup();
  1922. this.shortcuts = new Array();
  1923. this.hasMouseMoved = false;
  1924. this.foreColor = this.backColor = "#999999";
  1925. this.data = {};
  1926. this.cssClasses = [];
  1927. this.cleanup.init({
  1928. valid_elements : s.valid_elements,
  1929. extended_valid_elements : s.extended_valid_elements,
  1930. valid_child_elements : s.valid_child_elements,
  1931. entities : s.entities,
  1932. entity_encoding : s.entity_encoding,
  1933. debug : s.cleanup_debug,
  1934. indent : s.apply_source_formatting,
  1935. invalid_elements : s.invalid_elements,
  1936. verify_html : s.verify_html,
  1937. fix_content_duplication : s.fix_content_duplication,
  1938. convert_fonts_to_spans : s.convert_fonts_to_spans
  1939. });
  1940. // Wrap old theme
  1941. t = this.settings['theme'];
  1942. if (!tinyMCE.hasTheme(t)) {
  1943. fn = tinyMCE.callbacks;
  1944. to = {};
  1945. for (i=0; i<fn.length; i++) {
  1946. if ((fu = window['TinyMCE_' + t + "_" + fn[i]]))
  1947. to[fn[i]] = fu;
  1948. }
  1949. tinyMCE.addTheme(t, to);
  1950. }
  1951. // Wrap old plugins
  1952. this.plugins = new Array();
  1953. p = tinyMCE.getParam('plugins', '', true, ',');
  1954. if (p.length > 0) {
  1955. for (i=0; i<p.length; i++) {
  1956. pn = p[i];
  1957. if (pn.charAt(0) == '-')
  1958. pn = pn.substring(1);
  1959. if (!tinyMCE.hasPlugin(pn)) {
  1960. fn = tinyMCE.callbacks;
  1961. to = {};
  1962. for (x=0; x<fn.length; x++) {
  1963. if ((fu = window['TinyMCE_' + pn + "_" + fn[x]]))
  1964. to[fn[x]] = fu;
  1965. }
  1966. tinyMCE.addPlugin(pn, to);
  1967. }
  1968. this.plugins[this.plugins.length] = pn;
  1969. }
  1970. }
  1971. };
  1972. TinyMCE_Control.prototype = {
  1973. selection : null,
  1974. settings : null,
  1975. cleanup : null,
  1976. getData : function(na) {
  1977. var o = this.data[na];
  1978. if (!o)
  1979. o = this.data[na] = {};
  1980. return o;
  1981. },
  1982. hasPlugin : function(n) {
  1983. var i;
  1984. for (i=0; i<this.plugins.length; i++) {
  1985. if (this.plugins[i] == n)
  1986. return true;
  1987. }
  1988. return false;
  1989. },
  1990. addPlugin : function(n, p) {
  1991. if (!this.hasPlugin(n)) {
  1992. tinyMCE.addPlugin(n, p);
  1993. this.plugins[this.plugins.length] = n;
  1994. }
  1995. },
  1996. repaint : function() {
  1997. var s, b, ex;
  1998. if (tinyMCE.isRealIE)
  1999. return;
  2000. try {
  2001. s = this.selection;
  2002. b = s.getBookmark(true);
  2003. this.getBody().style.display = 'none';
  2004. this.getDoc().execCommand('selectall', false, null);
  2005. this.getSel().collapseToStart();
  2006. this.getBody().style.display = 'block';
  2007. s.moveToBookmark(b);
  2008. } catch (ex) {
  2009. // Ignore
  2010. }
  2011. },
  2012. switchSettings : function() {
  2013. if (tinyMCE.configs.length > 1 && tinyMCE.currentConfig != this.settings['index']) {
  2014. tinyMCE.settings = this.settings;
  2015. tinyMCE.currentConfig = this.settings['index'];
  2016. }
  2017. },
  2018. select : function() {
  2019. var oldInst = tinyMCE.selectedInstance;
  2020. if (oldInst != this) {
  2021. if (oldInst)
  2022. oldInst.execCommand('mceEndTyping');
  2023. tinyMCE.dispatchCallback(this, 'select_instance_callback', 'selectInstance', this, oldInst);
  2024. tinyMCE.selectedInstance = this;
  2025. }
  2026. },
  2027. getBody : function() {
  2028. return this.contentBody ? this.contentBody : this.getDoc().body;
  2029. },
  2030. getDoc : function() {
  2031. // return this.contentDocument ? this.contentDocument : this.contentWindow.document; // Removed due to IE 5.5 ?
  2032. return this.contentWindow.document;
  2033. },
  2034. getWin : function() {
  2035. return this.contentWindow;
  2036. },
  2037. getContainerWin : function() {
  2038. return this.containerWindow ? this.containerWindow : window;
  2039. },
  2040. getViewPort : function() {
  2041. return tinyMCE.getViewPort(this.getWin());
  2042. },
  2043. getParentNode : function(n, f) {
  2044. return tinyMCE.getParentNode(n, f, this.getBody());
  2045. },
  2046. getParentElement : function(n, na, f) {
  2047. return tinyMCE.getParentElement(n, na, f, this.getBody());
  2048. },
  2049. getParentBlockElement : function(n) {
  2050. return tinyMCE.getParentBlockElement(n, this.getBody());
  2051. },
  2052. resizeToContent : function() {
  2053. var d = this.getDoc(), b = d.body, de = d.documentElement;
  2054. this.iframeElement.style.height = (tinyMCE.isRealIE) ? b.scrollHeight : de.offsetHeight + 'px';
  2055. },
  2056. addShortcut : function(m, k, d, cmd, ui, va) {
  2057. var n = typeof(k) == "number", ie = tinyMCE.isIE, c, sc, i, scl = this.shortcuts;
  2058. if (!tinyMCE.getParam('custom_shortcuts'))
  2059. return false;
  2060. m = m.toLowerCase();
  2061. k = ie && !n ? k.toUpperCase() : k;
  2062. c = n ? null : k.charCodeAt(0);
  2063. d = d && d.indexOf('lang_') == 0 ? tinyMCE.getLang(d) : d;
  2064. sc = {
  2065. alt : m.indexOf('alt') != -1,
  2066. ctrl : m.indexOf('ctrl') != -1,
  2067. shift : m.indexOf('shift') != -1,
  2068. charCode : c,
  2069. keyCode : n ? k : (ie ? c : null),
  2070. desc : d,
  2071. cmd : cmd,
  2072. ui : ui,
  2073. val : va
  2074. };
  2075. for (i=0; i<scl.length; i++) {
  2076. if (sc.alt == scl[i].alt && sc.ctrl == scl[i].ctrl && sc.shift == scl[i].shift
  2077. && sc.charCode == scl[i].charCode && sc.keyCode == scl[i].keyCode) {
  2078. return false;
  2079. }
  2080. }
  2081. scl[scl.length] = sc;
  2082. return true;
  2083. },
  2084. handleShortcut : function(e) {
  2085. var i, s, o;
  2086. // Normal key press, then ignore it
  2087. if (!e.altKey && !e.ctrlKey)
  2088. return false;
  2089. s = this.shortcuts;
  2090. for (i=0; i<s.length; i++) {
  2091. o = s[i];
  2092. if (o.alt == e.altKey && o.ctrl == e.ctrlKey && (o.keyCode == e.keyCode || o.charCode == e.charCode)) {
  2093. if (o.cmd && (e.type == "keydown" || (e.type == "keypress" && !tinyMCE.isOpera)))
  2094. tinyMCE.execCommand(o.cmd, o.ui, o.val);
  2095. tinyMCE.cancelEvent(e);
  2096. return true;
  2097. }
  2098. }
  2099. return false;
  2100. },
  2101. autoResetDesignMode : function() {
  2102. // Add fix for tab/style.display none/block problems in Gecko
  2103. if (!tinyMCE.isIE && this.isHidden() && tinyMCE.getParam('auto_reset_designmode'))
  2104. eval('try { this.getDoc().designMode = "On"; this.useCSS = false; } catch(e) {}');
  2105. },
  2106. isHidden : function() {
  2107. var s;
  2108. if (tinyMCE.isIE)
  2109. return false;
  2110. s = this.getSel();
  2111. // Weird, wheres that cursor selection?
  2112. return (!s || !s.rangeCount || s.rangeCount == 0);
  2113. },
  2114. isDirty : function() {
  2115. // Is content modified and not in a submit procedure
  2116. return tinyMCE.trim(this.startContent) != tinyMCE.trim(this.getBody().innerHTML) && !tinyMCE.isNotDirty;
  2117. },
  2118. _mergeElements : function(scmd, pa, ch, override) {
  2119. if (scmd == "removeformat") {
  2120. pa.className = "";
  2121. pa.style.cssText = "";
  2122. ch.className = "";
  2123. ch.style.cssText = "";
  2124. return;
  2125. }
  2126. var st = tinyMCE.parseStyle(tinyMCE.getAttrib(pa, "style"));
  2127. var stc = tinyMCE.parseStyle(tinyMCE.getAttrib(ch, "style"));
  2128. var className = tinyMCE.getAttrib(pa, "class");
  2129. // Removed class adding due to bug #1478272
  2130. className = tinyMCE.getAttrib(ch, "class");
  2131. if (override) {
  2132. for (var n in st) {
  2133. if (typeof(st[n]) == 'function')
  2134. continue;
  2135. stc[n] = st[n];
  2136. }
  2137. } else {
  2138. for (var n in stc) {
  2139. if (typeof(stc[n]) == 'function')
  2140. continue;
  2141. st[n] = stc[n];
  2142. }
  2143. }
  2144. tinyMCE.setAttrib(pa, "style", tinyMCE.serializeStyle(st));
  2145. tinyMCE.setAttrib(pa, "class", tinyMCE.trim(className));
  2146. ch.className = "";
  2147. ch.style.cssText = "";
  2148. ch.removeAttribute("class");
  2149. ch.removeAttribute("style");
  2150. },
  2151. _setUseCSS : function(b) {
  2152. var d = this.getDoc();
  2153. try {d.execCommand("useCSS", false, !b);} catch (ex) {}
  2154. try {d.execCommand("styleWithCSS", false, b);} catch (ex) {}
  2155. if (!tinyMCE.getParam("table_inline_editing"))
  2156. try {d.execCommand('enableInlineTableEditing', false, "false");} catch (ex) {}
  2157. if (!tinyMCE.getParam("object_resizing"))
  2158. try {d.execCommand('enableObjectResizing', false, "false");} catch (ex) {}
  2159. },
  2160. execCommand : function(command, user_interface, value) {
  2161. var doc = this.getDoc(), win = this.getWin(), focusElm = this.getFocusElement();
  2162. // Is not a undo specific command
  2163. if (!new RegExp('mceStartTyping|mceEndTyping|mceBeginUndoLevel|mceEndUndoLevel|mceAddUndoLevel', 'gi').test(command))
  2164. this.undoBookmark = null;
  2165. // Mozilla issue
  2166. if (!tinyMCE.isIE && !this.useCSS) {
  2167. this._setUseCSS(false);
  2168. this.useCSS = true;
  2169. }
  2170. //debug("command: " + command + ", user_interface: " + user_interface + ", value: " + value);
  2171. this.contentDocument = doc; // <-- Strange, unless this is applied Mozilla 1.3 breaks
  2172. // Don't dispatch key commands
  2173. if (!/mceStartTyping|mceEndTyping/.test(command)) {
  2174. if (tinyMCE.execCommandCallback(this, 'execcommand_callback', 'execCommand', this.editorId, this.getBody(), command, user_interface, value))
  2175. return;
  2176. }
  2177. // Fix align on images
  2178. if (focusElm && focusElm.nodeName == "IMG") {
  2179. var align = focusElm.getAttribute('align');
  2180. var img = command == "JustifyCenter" ? focusElm.cloneNode(false) : focusElm;
  2181. switch (command) {
  2182. case "JustifyLeft":
  2183. if (align == 'left')
  2184. img.removeAttribute('align');
  2185. else
  2186. img.setAttribute('align', 'left');
  2187. // Remove the div
  2188. var div = focusElm.parentNode;
  2189. if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
  2190. div.parentNode.replaceChild(img, div);
  2191. this.selection.selectNode(img);
  2192. this.repaint();
  2193. tinyMCE.triggerNodeChange();
  2194. return;
  2195. case "JustifyCenter":
  2196. img.removeAttribute('align');
  2197. // Is centered
  2198. var div = tinyMCE.getParentElement(focusElm, "div");
  2199. if (div && div.style.textAlign == "center") {
  2200. // Remove div
  2201. if (div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
  2202. div.parentNode.replaceChild(img, div);
  2203. } else {
  2204. // Add div
  2205. var div = this.getDoc().createElement("div");
  2206. div.style.textAlign = 'center';
  2207. div.appendChild(img);
  2208. focusElm.parentNode.replaceChild(div, focusElm);
  2209. }
  2210. this.selection.selectNode(img);
  2211. this.repaint();
  2212. tinyMCE.triggerNodeChange();
  2213. return;
  2214. case "JustifyRight":
  2215. if (align == 'right')
  2216. img.removeAttribute('align');
  2217. else
  2218. img.setAttribute('align', 'right');
  2219. // Remove the div
  2220. var div = focusElm.parentNode;
  2221. if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
  2222. div.parentNode.replaceChild(img, div);
  2223. this.selection.selectNode(img);
  2224. this.repaint();
  2225. tinyMCE.triggerNodeChange();
  2226. return;
  2227. }
  2228. }
  2229. if (tinyMCE.settings['force_br_newlines']) {
  2230. var alignValue = "";
  2231. if (doc.selection.type != "Control") {
  2232. switch (command) {
  2233. case "JustifyLeft":
  2234. alignValue = "left";
  2235. break;
  2236. case "JustifyCenter":
  2237. alignValue = "center";
  2238. break;
  2239. case "JustifyFull":
  2240. alignValue = "justify";
  2241. break;
  2242. case "JustifyRight":
  2243. alignValue = "right";
  2244. break;
  2245. }
  2246. if (alignValue != "") {
  2247. var rng = doc.selection.createRange();
  2248. if ((divElm = tinyMCE.getParentElement(rng.parentElement(), "div")) != null)
  2249. divElm.setAttribute("align", alignValue);
  2250. else if (rng.pasteHTML && rng.htmlText.length > 0)
  2251. rng.pasteHTML('<div align="' + alignValue + '">' + rng.htmlText + "</div>");
  2252. tinyMCE.triggerNodeChange();
  2253. return;
  2254. }
  2255. }
  2256. }
  2257. switch (command) {
  2258. case "mceRepaint":
  2259. this.repaint();
  2260. return true;
  2261. case "unlink":
  2262. // Unlink if caret is inside link
  2263. if (tinyMCE.isGecko && this.getSel().isCollapsed) {
  2264. focusElm = tinyMCE.getParentElement(focusElm, 'A');
  2265. if (focusElm)
  2266. this.selection.selectNode(focusElm, false);
  2267. }
  2268. this.getDoc().execCommand(command, user_interface, value);
  2269. tinyMCE.isGecko && this.getSel().collapseToEnd();
  2270. tinyMCE.triggerNodeChange();
  2271. return true;
  2272. case "InsertUnorderedList":
  2273. case "InsertOrderedList":
  2274. this.getDoc().execCommand(command, user_interface, value);
  2275. tinyMCE.triggerNodeChange();
  2276. break;
  2277. case "Strikethrough":
  2278. this.getDoc().execCommand(command, user_interface, value);
  2279. tinyMCE.triggerNodeChange();
  2280. break;
  2281. case "mceSelectNode":
  2282. this.selection.selectNode(value);
  2283. tinyMCE.triggerNodeChange();
  2284. tinyMCE.selectedNode = value;
  2285. break;
  2286. case "FormatBlock":
  2287. if (value == null || value == "") {
  2288. var elm = tinyMCE.getParentElement(this.getFocusElement(), "p,div,h1,h2,h3,h4,h5,h6,pre,address,blockquote,dt,dl,dd,samp");
  2289. if (elm)
  2290. this.execCommand("mceRemoveNode", false, elm);
  2291. } else {
  2292. if (!this.cleanup.isValid(value))
  2293. return true;
  2294. if (tinyMCE.isGecko && new RegExp('<(div|blockquote|code|dt|dd|dl|samp)>', 'gi').test(value))
  2295. value = value.replace(/[^a-z]/gi, '');
  2296. if (tinyMCE.isIE && new RegExp('blockquote|code|samp', 'gi').test(value)) {
  2297. var b = this.selection.getBookmark();
  2298. this.getDoc().execCommand("FormatBlock", false, '<p>');
  2299. tinyMCE.renameElement(tinyMCE.getParentBlockElement(this.getFocusElement()), value);
  2300. this.selection.moveToBookmark(b);
  2301. } else
  2302. this.getDoc().execCommand("FormatBlock", false, value);
  2303. }
  2304. tinyMCE.triggerNodeChange();
  2305. break;
  2306. case "mceRemoveNode":
  2307. if (!value)
  2308. value = tinyMCE.getParentElement(this.getFocusElement());
  2309. if (tinyMCE.isIE) {
  2310. value.outerHTML = value.innerHTML;
  2311. } else {
  2312. var rng = value.ownerDocument.createRange();
  2313. rng.setStartBefore(value);
  2314. rng.setEndAfter(value);
  2315. rng.deleteContents();
  2316. rng.insertNode(rng.createContextualFragment(value.innerHTML));
  2317. }
  2318. tinyMCE.triggerNodeChange();
  2319. break;
  2320. case "mceSelectNodeDepth":
  2321. var parentNode = this.getFocusElement();
  2322. for (var i=0; parentNode; i++) {
  2323. if (parentNode.nodeName.toLowerCase() == "body")
  2324. break;
  2325. if (parentNode.nodeName.toLowerCase() == "#text") {
  2326. i--;
  2327. parentNode = parentNode.parentNode;
  2328. continue;
  2329. }
  2330. if (i == value) {
  2331. this.selection.selectNode(parentNode, false);
  2332. tinyMCE.triggerNodeChange();
  2333. tinyMCE.selectedNode = parentNode;
  2334. return;
  2335. }
  2336. parentNode = parentNode.parentNode;
  2337. }
  2338. break;
  2339. case "mceSetStyleInfo":
  2340. case "SetStyleInfo":
  2341. var rng = this.getRng();
  2342. var sel = this.getSel();
  2343. var scmd = value['command'];
  2344. var sname = value['name'];
  2345. var svalue = value['value'] == null ? '' : value['value'];
  2346. //var svalue = value['value'] == null ? '' : value['value'];
  2347. var wrapper = value['wrapper'] ? value['wrapper'] : "span";
  2348. var parentElm = null;
  2349. var invalidRe = new RegExp("^BODY|HTML$", "g");
  2350. var invalidParentsRe = tinyMCE.settings['merge_styles_invalid_parents'] != '' ? new RegExp(tinyMCE.settings['merge_styles_invalid_parents'], "gi") : null;
  2351. // Whole element selected check
  2352. if (tinyMCE.isIE) {
  2353. // Control range
  2354. if (rng.item)
  2355. parentElm = rng.item(0);
  2356. else {
  2357. var pelm = rng.parentElement();
  2358. var prng = doc.selection.createRange();
  2359. prng.moveToElementText(pelm);
  2360. if (rng.htmlText == prng.htmlText || rng.boundingWidth == 0) {
  2361. if (invalidParentsRe == null || !invalidParentsRe.test(pelm.nodeName))
  2362. parentElm = pelm;
  2363. }
  2364. }
  2365. } else {
  2366. var felm = this.getFocusElement();
  2367. if (sel.isCollapsed || (new RegExp('td|tr|tbody|table', 'gi').test(felm.nodeName) && sel.anchorNode == felm.parentNode))
  2368. parentElm = felm;
  2369. }
  2370. // Whole element selected
  2371. if (parentElm && !invalidRe.test(parentElm.nodeName)) {
  2372. if (scmd == "setstyle")
  2373. tinyMCE.setStyleAttrib(parentElm, sname, svalue);
  2374. if (scmd == "setattrib")
  2375. tinyMCE.setAttrib(parentElm, sname, svalue);
  2376. if (scmd == "removeformat") {
  2377. parentElm.style.cssText = '';
  2378. tinyMCE.setAttrib(parentElm, 'class', '');
  2379. }
  2380. // Remove style/attribs from all children
  2381. var ch = tinyMCE.getNodeTree(parentElm, new Array(), 1);
  2382. for (var z=0; z<ch.length; z++) {
  2383. if (ch[z] == parentElm)
  2384. continue;
  2385. if (scmd == "setstyle")
  2386. tinyMCE.setStyleAttrib(ch[z], sname, '');
  2387. if (scmd == "setattrib")
  2388. tinyMCE.setAttrib(ch[z], sname, '');
  2389. if (scmd == "removeformat") {
  2390. ch[z].style.cssText = '';
  2391. tinyMCE.setAttrib(ch[z], 'class', '');
  2392. }
  2393. }
  2394. } else {
  2395. this._setUseCSS(false); // Bug in FF when running in fullscreen
  2396. doc.execCommand("FontName", false, "#mce_temp_font#");
  2397. var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#");
  2398. // Change them all
  2399. for (var x=0; x<elementArray.length; x++) {
  2400. elm = elementArray[x];
  2401. if (elm) {
  2402. var spanElm = doc.createElement(wrapper);
  2403. if (scmd == "setstyle")
  2404. tinyMCE.setStyleAttrib(spanElm, sname, svalue);
  2405. if (scmd == "setattrib")
  2406. tinyMCE.setAttrib(spanElm, sname, svalue);
  2407. if (scmd == "removeformat") {
  2408. spanElm.style.cssText = '';
  2409. tinyMCE.setAttrib(spanElm, 'class', '');
  2410. }
  2411. if (elm.hasChildNodes()) {
  2412. for (var i=0; i<elm.childNodes.length; i++)
  2413. spanElm.appendChild(elm.childNodes[i].cloneNode(true));
  2414. }
  2415. spanElm.setAttribute("mce_new", "true");
  2416. elm.parentNode.replaceChild(spanElm, elm);
  2417. // Remove style/attribs from all children
  2418. var ch = tinyMCE.getNodeTree(spanElm, new Array(), 1);
  2419. for (var z=0; z<ch.length; z++) {
  2420. if (ch[z] == spanElm)
  2421. continue;
  2422. if (scmd == "setstyle")
  2423. tinyMCE.setStyleAttrib(ch[z], sname, '');
  2424. if (scmd == "setattrib")
  2425. tinyMCE.setAttrib(ch[z], sname, '');
  2426. if (scmd == "removeformat") {
  2427. ch[z].style.cssText = '';
  2428. tinyMCE.setAttrib(ch[z], 'class', '');
  2429. }
  2430. }
  2431. }
  2432. }
  2433. }
  2434. // Cleaup wrappers
  2435. var nodes = doc.getElementsByTagName(wrapper);
  2436. for (var i=nodes.length-1; i>=0; i--) {
  2437. var elm = nodes[i];
  2438. var isNew = tinyMCE.getAttrib(elm, "mce_new") == "true";
  2439. elm.removeAttribute("mce_new");
  2440. // Is only child a element
  2441. if (elm.childNodes && elm.childNodes.length == 1 && elm.childNodes[0].nodeType == 1) {
  2442. //tinyMCE.debug("merge1" + isNew);
  2443. this._mergeElements(scmd, elm, elm.childNodes[0], isNew);
  2444. continue;
  2445. }
  2446. // Is I the only child
  2447. if (elm.parentNode.childNodes.length == 1 && !invalidRe.test(elm.nodeName) && !invalidRe.test(elm.parentNode.nodeName)) {
  2448. //tinyMCE.debug("merge2" + isNew + "," + elm.nodeName + "," + elm.parentNode.nodeName);
  2449. if (invalidParentsRe == null || !invalidParentsRe.test(elm.parentNode.nodeName))
  2450. this._mergeElements(scmd, elm.parentNode, elm, false);
  2451. }
  2452. }
  2453. // Remove empty wrappers
  2454. var nodes = doc.getElementsByTagName(wrapper);
  2455. for (var i=nodes.length-1; i>=0; i--) {
  2456. var elm = nodes[i];
  2457. var isEmpty = true;
  2458. // Check if it has any attribs
  2459. var tmp = doc.createElement("body");
  2460. tmp.appendChild(elm.cloneNode(false));
  2461. // Is empty span, remove it
  2462. tmp.innerHTML = tmp.innerHTML.replace(new RegExp('style=""|class=""', 'gi'), '');
  2463. //tinyMCE.debug(tmp.innerHTML);
  2464. if (new RegExp('<span>', 'gi').test(tmp.innerHTML)) {
  2465. for (var x=0; x<elm.childNodes.length; x++) {
  2466. if (elm.parentNode != null)
  2467. elm.parentNode.insertBefore(elm.childNodes[x].cloneNode(true), elm);
  2468. }
  2469. elm.parentNode.removeChild(elm);
  2470. }
  2471. }
  2472. // Re add the visual aids
  2473. if (scmd == "removeformat")
  2474. tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
  2475. tinyMCE.triggerNodeChange();
  2476. break;
  2477. case "FontName":
  2478. if (value == null) {
  2479. var s = this.getSel();
  2480. // Find font and select it
  2481. if (tinyMCE.isGecko && s.isCollapsed) {
  2482. var f = tinyMCE.getParentElement(this.getFocusElement(), "font");
  2483. if (f != null)
  2484. this.selection.selectNode(f, false);
  2485. }
  2486. // Remove format
  2487. this.getDoc().execCommand("RemoveFormat", false, null);
  2488. // Collapse range if font was found
  2489. if (f != null && tinyMCE.isGecko) {
  2490. var r = this.getRng().cloneRange();
  2491. r.collapse(true);
  2492. s.removeAllRanges();
  2493. s.addRange(r);
  2494. }
  2495. } else
  2496. this.getDoc().execCommand('FontName', false, value);
  2497. if (tinyMCE.isGecko)
  2498. window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
  2499. return;
  2500. case "FontSize":
  2501. this.getDoc().execCommand('FontSize', false, value);
  2502. if (tinyMCE.isGecko)
  2503. window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
  2504. return;
  2505. case "forecolor":
  2506. value = value == null ? this.foreColor : value;
  2507. value = tinyMCE.trim(value);
  2508. value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;
  2509. this.foreColor = value;
  2510. this.getDoc().execCommand('forecolor', false, value);
  2511. break;
  2512. case "HiliteColor":
  2513. value = value == null ? this.backColor : value;
  2514. value = tinyMCE.trim(value);
  2515. value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;
  2516. this.backColor = value;
  2517. if (tinyMCE.isGecko) {
  2518. this._setUseCSS(true);
  2519. this.getDoc().execCommand('hilitecolor', false, value);
  2520. this._setUseCSS(false);
  2521. } else
  2522. this.getDoc().execCommand('BackColor', false, value);
  2523. break;
  2524. case "Cut":
  2525. case "Copy":
  2526. case "Paste":
  2527. var cmdFailed = false;
  2528. // Try executing command
  2529. eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}');
  2530. if (tinyMCE.isOpera && cmdFailed)
  2531. alert('Currently not supported by your browser, use keyboard shortcuts instead.');
  2532. // Alert error in gecko if command failed
  2533. if (tinyMCE.isGecko && cmdFailed) {
  2534. // Confirm more info
  2535. if (confirm(tinyMCE.entityDecode(tinyMCE.getLang('lang_clipboard_msg'))))
  2536. window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');
  2537. return;
  2538. } else
  2539. tinyMCE.triggerNodeChange();
  2540. break;
  2541. case "mceSetContent":
  2542. if (!value)
  2543. value = "";
  2544. // Call custom cleanup code
  2545. value = tinyMCE.storeAwayURLs(value);
  2546. value = tinyMCE._customCleanup(this, "insert_to_editor", value);
  2547. if (this.getBody().nodeName == 'BODY')
  2548. tinyMCE._setHTML(doc, value);
  2549. else
  2550. this.getBody().innerHTML = value;
  2551. tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, doc, this.settings, this.getBody(), false, false, false, true));
  2552. tinyMCE.convertAllRelativeURLs(this.getBody());
  2553. // Cleanup any mess left from storyAwayURLs
  2554. tinyMCE._removeInternal(this.getBody());
  2555. // When editing always use fonts internaly
  2556. if (tinyMCE.getParam("convert_fonts_to_spans"))
  2557. tinyMCE.convertSpansToFonts(doc);
  2558. tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
  2559. tinyMCE._setEventsEnabled(this.getBody(), false);
  2560. return true;
  2561. case "mceCleanup":
  2562. var b = this.selection.getBookmark();
  2563. tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML);
  2564. tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, this.contentDocument, this.settings, this.getBody(), this.visualAid));
  2565. tinyMCE.convertAllRelativeURLs(doc.body);
  2566. // When editing always use fonts internaly
  2567. if (tinyMCE.getParam("convert_fonts_to_spans"))
  2568. tinyMCE.convertSpansToFonts(doc);
  2569. tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
  2570. tinyMCE._setEventsEnabled(this.getBody(), false);
  2571. this.repaint();
  2572. this.selection.moveToBookmark(b);
  2573. tinyMCE.triggerNodeChange();
  2574. break;
  2575. case "mceReplaceContent":
  2576. // Force empty string
  2577. if (!value)
  2578. value = '';
  2579. this.getWin().focus();
  2580. var selectedText = "";
  2581. if (tinyMCE.isIE) {
  2582. var rng = doc.selection.createRange();
  2583. selectedText = rng.text;
  2584. } else
  2585. selectedText = this.getSel().toString();
  2586. if (selectedText.length > 0) {
  2587. value = tinyMCE.replaceVar(value, "selection", selectedText);
  2588. tinyMCE.execCommand('mceInsertContent', false, value);
  2589. }
  2590. tinyMCE.triggerNodeChange();
  2591. break;
  2592. case "mceSetAttribute":
  2593. if (typeof(value) == 'object') {
  2594. var targetElms = (typeof(value['targets']) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value['targets'];
  2595. var targetNode = tinyMCE.getParentElement(this.getFocusElement(), targetElms);
  2596. if (targetNode) {
  2597. targetNode.setAttribute(value['name'], value['value']);
  2598. tinyMCE.triggerNodeChange();
  2599. }
  2600. }
  2601. break;
  2602. case "mceSetCSSClass":
  2603. this.execCommand("mceSetStyleInfo", false, {command : "setattrib", name : "class", value : value});
  2604. break;
  2605. case "mceInsertRawHTML":
  2606. var key = 'tiny_mce_marker';
  2607. this.execCommand('mceBeginUndoLevel');
  2608. // Insert marker key
  2609. this.execCommand('mceInsertContent', false, key);
  2610. // Store away scroll pos
  2611. var scrollX = this.getBody().scrollLeft + this.getDoc().documentElement.scrollLeft;
  2612. var scrollY = this.getBody().scrollTop + this.getDoc().documentElement.scrollTop;
  2613. // Find marker and replace with RAW HTML
  2614. var html = this.getBody().innerHTML;
  2615. if ((pos = html.indexOf(key)) != -1)
  2616. tinyMCE.setInnerHTML(this.getBody(), html.substring(0, pos) + value + html.substring(pos + key.length));
  2617. // Restore scoll pos
  2618. this.contentWindow.scrollTo(scrollX, scrollY);
  2619. this.execCommand('mceEndUndoLevel');
  2620. break;
  2621. case "mceInsertContent":
  2622. // Force empty string
  2623. if (!value)
  2624. value = '';
  2625. var insertHTMLFailed = false;
  2626. // Removed since it produced problems in IE
  2627. // this.getWin().focus();
  2628. if (tinyMCE.isGecko || tinyMCE.isOpera) {
  2629. try {
  2630. // Is plain text or HTML, &amp;, &nbsp; etc will be encoded wrong in FF
  2631. if (value.indexOf('<') == -1 && !value.match(/(&#38;|&#160;|&#60;|&#62;)/g)) {
  2632. var r = this.getRng();
  2633. var n = this.getDoc().createTextNode(tinyMCE.entityDecode(value));
  2634. var s = this.getSel();
  2635. var r2 = r.cloneRange();
  2636. // Insert text at cursor position
  2637. s.removeAllRanges();
  2638. r.deleteContents();
  2639. r.insertNode(n);
  2640. // Move the cursor to the end of text
  2641. r2.selectNode(n);
  2642. r2.collapse(false);
  2643. s.removeAllRanges();
  2644. s.addRange(r2);
  2645. } else {
  2646. value = tinyMCE.fixGeckoBaseHREFBug(1, this.getDoc(), value);
  2647. this.getDoc().execCommand('inserthtml', false, value);
  2648. tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);
  2649. }
  2650. } catch (ex) {
  2651. insertHTMLFailed = true;
  2652. }
  2653. if (!insertHTMLFailed) {
  2654. tinyMCE.triggerNodeChange();
  2655. return;
  2656. }
  2657. }
  2658. if (!tinyMCE.isIE) {
  2659. var isHTML = value.indexOf('<') != -1;
  2660. var sel = this.getSel();
  2661. var rng = this.getRng();
  2662. if (isHTML) {
  2663. if (tinyMCE.isSafari) {
  2664. var tmpRng = this.getDoc().createRange();
  2665. tmpRng.setStart(this.getBody(), 0);
  2666. tmpRng.setEnd(this.getBody(), 0);
  2667. value = tmpRng.createContextualFragment(value);
  2668. } else
  2669. value = rng.createContextualFragment(value);
  2670. } else {
  2671. // Setup text node
  2672. var el = document.createElement("div");
  2673. el.innerHTML = value;
  2674. value = el.firstChild.nodeValue;
  2675. value = doc.createTextNode(value);
  2676. }
  2677. // Insert plain text in Safari
  2678. if (tinyMCE.isSafari && !isHTML) {
  2679. this.execCommand('InsertText', false, value.nodeValue);
  2680. tinyMCE.triggerNodeChange();
  2681. return true;
  2682. } else if (tinyMCE.isSafari && isHTML) {
  2683. rng.deleteContents();
  2684. rng.insertNode(value);
  2685. tinyMCE.triggerNodeChange();
  2686. return true;
  2687. }
  2688. rng.deleteContents();
  2689. // If target node is text do special treatment, (Mozilla 1.3 fix)
  2690. if (rng.startContainer.nodeType == 3) {
  2691. var node = rng.startContainer.splitText(rng.startOffset);
  2692. node.parentNode.insertBefore(value, node);
  2693. } else
  2694. rng.insertNode(value);
  2695. if (!isHTML) {
  2696. // Removes weird selection trails
  2697. sel.selectAllChildren(doc.body);
  2698. sel.removeAllRanges();
  2699. // Move cursor to end of content
  2700. var rng = doc.createRange();
  2701. rng.selectNode(value);
  2702. rng.collapse(false);
  2703. sel.addRange(rng);
  2704. } else
  2705. rng.collapse(false);
  2706. tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);
  2707. } else {
  2708. var rng = doc.selection.createRange(), tmpRng = null;
  2709. var c = value.indexOf('<!--') != -1;
  2710. // Fix comment bug, add tag before comments
  2711. if (c)
  2712. value = tinyMCE.uniqueTag + value;
  2713. // tmpRng = rng.duplicate(); // Store away range (Fixes Undo bookmark bug in IE)
  2714. if (rng.item)
  2715. rng.item(0).outerHTML = value;
  2716. else
  2717. rng.pasteHTML(value);
  2718. //if (tmpRng)
  2719. // tmpRng.select(); // Restore range (Fixes Undo bookmark bug in IE)
  2720. // Remove unique tag
  2721. if (c) {
  2722. var e = this.getDoc().getElementById('mceTMPElement');
  2723. e.parentNode.removeChild(e);
  2724. }
  2725. }
  2726. tinyMCE.execCommand("mceAddUndoLevel");
  2727. tinyMCE.triggerNodeChange();
  2728. break;
  2729. case "mceStartTyping":
  2730. if (tinyMCE.settings['custom_undo_redo'] && this.undoRedo.typingUndoIndex == -1) {
  2731. this.undoRedo.typingUndoIndex = this.undoRedo.undoIndex;
  2732. tinyMCE.typingUndoIndex = tinyMCE.undoIndex;
  2733. this.execCommand('mceAddUndoLevel');
  2734. }
  2735. break;
  2736. case "mceEndTyping":
  2737. if (tinyMCE.settings['custom_undo_redo'] && this.undoRedo.typingUndoIndex != -1) {
  2738. this.execCommand('mceAddUndoLevel');
  2739. this.undoRedo.typingUndoIndex = -1;
  2740. }
  2741. tinyMCE.typingUndoIndex = -1;
  2742. break;
  2743. case "mceBeginUndoLevel":
  2744. this.undoRedoLevel = false;
  2745. break;
  2746. case "mceEndUndoLevel":
  2747. this.undoRedoLevel = true;
  2748. this.execCommand('mceAddUndoLevel');
  2749. break;
  2750. case "mceAddUndoLevel":
  2751. if (tinyMCE.settings['custom_undo_redo'] && this.undoRedoLevel) {
  2752. if (this.undoRedo.add())
  2753. tinyMCE.triggerNodeChange(false);
  2754. }
  2755. break;
  2756. case "Undo":
  2757. if (tinyMCE.settings['custom_undo_redo']) {
  2758. tinyMCE.execCommand("mceEndTyping");
  2759. this.undoRedo.undo();
  2760. tinyMCE.triggerNodeChange();
  2761. } else
  2762. this.getDoc().execCommand(command, user_interface, value);
  2763. break;
  2764. case "Redo":
  2765. if (tinyMCE.settings['custom_undo_redo']) {
  2766. tinyMCE.execCommand("mceEndTyping");
  2767. this.undoRedo.redo();
  2768. tinyMCE.triggerNodeChange();
  2769. } else
  2770. this.getDoc().execCommand(command, user_interface, value);
  2771. break;
  2772. case "mceToggleVisualAid":
  2773. this.visualAid = !this.visualAid;
  2774. tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
  2775. tinyMCE.triggerNodeChange();
  2776. break;
  2777. case "Indent":
  2778. this.getDoc().execCommand(command, user_interface, value);
  2779. tinyMCE.triggerNodeChange();
  2780. if (tinyMCE.isIE) {
  2781. var n = tinyMCE.getParentElement(this.getFocusElement(), "blockquote");
  2782. do {
  2783. if (n && n.nodeName == "BLOCKQUOTE") {
  2784. n.removeAttribute("dir");
  2785. n.removeAttribute("style");
  2786. }
  2787. } while (n != null && (n = n.parentNode) != null);
  2788. }
  2789. break;
  2790. case "RemoveFormat":
  2791. case "removeformat":
  2792. var text = this.selection.getSelectedText();
  2793. if (tinyMCE.isOpera) {
  2794. this.getDoc().execCommand("RemoveFormat", false, null);
  2795. return;
  2796. }
  2797. if (tinyMCE.isIE) {
  2798. try {
  2799. var rng = doc.selection.createRange();
  2800. rng.execCommand("RemoveFormat", false, null);
  2801. } catch (e) {
  2802. // Do nothing
  2803. }
  2804. this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});
  2805. } else {
  2806. this.getDoc().execCommand(command, user_interface, value);
  2807. this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});
  2808. }
  2809. // Remove class
  2810. if (text.length == 0)
  2811. this.execCommand("mceSetCSSClass", false, "");
  2812. tinyMCE.triggerNodeChange();
  2813. break;
  2814. default:
  2815. this.getDoc().execCommand(command, user_interface, value);
  2816. if (tinyMCE.isGecko)
  2817. window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
  2818. else
  2819. tinyMCE.triggerNodeChange();
  2820. }
  2821. // Add undo level after modification
  2822. if (command != "mceAddUndoLevel" && command != "Undo" && command != "Redo" && command != "mceStartTyping" && command != "mceEndTyping")
  2823. tinyMCE.execCommand("mceAddUndoLevel");
  2824. },
  2825. queryCommandValue : function(c) {
  2826. try {
  2827. return this.getDoc().queryCommandValue(c);
  2828. } catch (e) {
  2829. return null;
  2830. }
  2831. },
  2832. queryCommandState : function(c) {
  2833. return this.getDoc().queryCommandState(c);
  2834. },
  2835. _onAdd : function(replace_element, form_element_name, target_document) {
  2836. var hc, th, to, editorTemplate;
  2837. th = this.settings['theme'];
  2838. to = tinyMCE.themes[th];
  2839. var targetDoc = target_document ? target_document : document;
  2840. this.targetDoc = targetDoc;
  2841. tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings['theme'];
  2842. this.settings['themeurl'] = tinyMCE.themeURL;
  2843. if (!replace_element) {
  2844. alert("Error: Could not find the target element.");
  2845. return false;
  2846. }
  2847. if (to.getEditorTemplate)
  2848. editorTemplate = to.getEditorTemplate(this.settings, this.editorId);
  2849. var deltaWidth = editorTemplate['delta_width'] ? editorTemplate['delta_width'] : 0;
  2850. var deltaHeight = editorTemplate['delta_height'] ? editorTemplate['delta_height'] : 0;
  2851. var html = '<span id="' + this.editorId + '_parent" class="mceEditorContainer">' + editorTemplate['html'];
  2852. html = tinyMCE.replaceVar(html, "editor_id", this.editorId);
  2853. this.settings['default_document'] = tinyMCE.baseURL + "/blank.htm";
  2854. this.settings['old_width'] = this.settings['width'];
  2855. this.settings['old_height'] = this.settings['height'];
  2856. // Set default width, height
  2857. if (this.settings['width'] == -1)
  2858. this.settings['width'] = replace_element.offsetWidth;
  2859. if (this.settings['height'] == -1)
  2860. this.settings['height'] = replace_element.offsetHeight;
  2861. // Try the style width
  2862. if (this.settings['width'] == 0)
  2863. this.settings['width'] = replace_element.style.width;
  2864. // Try the style height
  2865. if (this.settings['height'] == 0)
  2866. this.settings['height'] = replace_element.style.height;
  2867. // If no width/height then default to 320x240, better than nothing
  2868. if (this.settings['width'] == 0)
  2869. this.settings['width'] = 320;
  2870. if (this.settings['height'] == 0)
  2871. this.settings['height'] = 240;
  2872. this.settings['area_width'] = parseInt(this.settings['width']);
  2873. this.settings['area_height'] = parseInt(this.settings['height']);
  2874. this.settings['area_width'] += deltaWidth;
  2875. this.settings['area_height'] += deltaHeight;
  2876. this.settings['width_style'] = "" + this.settings['width'];
  2877. this.settings['height_style'] = "" + this.settings['height'];
  2878. // Special % handling
  2879. if (("" + this.settings['width']).indexOf('%') != -1)
  2880. this.settings['area_width'] = "100%";
  2881. else
  2882. this.settings['width_style'] += 'px';
  2883. if (("" + this.settings['height']).indexOf('%') != -1)
  2884. this.settings['area_height'] = "100%";
  2885. else
  2886. this.settings['height_style'] += 'px';
  2887. if (("" + replace_element.style.width).indexOf('%') != -1) {
  2888. this.settings['width'] = replace_element.style.width;
  2889. this.settings['area_width'] = "100%";
  2890. this.settings['width_style'] = "100%";
  2891. }
  2892. if (("" + replace_element.style.height).indexOf('%') != -1) {
  2893. this.settings['height'] = replace_element.style.height;
  2894. this.settings['area_height'] = "100%";
  2895. this.settings['height_style'] = "100%";
  2896. }
  2897. html = tinyMCE.applyTemplate(html);
  2898. this.settings['width'] = this.settings['old_width'];
  2899. this.settings['height'] = this.settings['old_height'];
  2900. this.visualAid = this.settings['visual'];
  2901. this.formTargetElementId = form_element_name;
  2902. // Get replace_element contents
  2903. if (replace_element.nodeName == "TEXTAREA" || replace_element.nodeName == "INPUT")
  2904. this.startContent = replace_element.value;
  2905. else
  2906. this.startContent = replace_element.innerHTML;
  2907. // If not text area or input
  2908. if (replace_element.nodeName != "TEXTAREA" && replace_element.nodeName != "INPUT") {
  2909. this.oldTargetElement = replace_element;
  2910. // Debug mode
  2911. if (tinyMCE.settings['debug']) {
  2912. hc = '<textarea wrap="off" id="' + form_element_name + '" name="' + form_element_name + '" cols="100" rows="15"></textarea>';
  2913. } else {
  2914. hc = '<input type="hidden" id="' + form_element_name + '" name="' + form_element_name + '" />';
  2915. this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');
  2916. this.oldTargetElement.style.display = "none";
  2917. }
  2918. html += '</span>';
  2919. if (tinyMCE.isGecko)
  2920. html = hc + html;
  2921. else
  2922. html += hc;
  2923. // Output HTML and set editable
  2924. if (tinyMCE.isGecko) {
  2925. var rng = replace_element.ownerDocument.createRange();
  2926. rng.setStartBefore(replace_element);
  2927. var fragment = rng.createContextualFragment(html);
  2928. tinyMCE.insertAfter(fragment, replace_element);
  2929. } else
  2930. replace_element.insertAdjacentHTML("beforeBegin", html);
  2931. } else {
  2932. html += '</span>';
  2933. // Just hide the textarea element
  2934. this.oldTargetElement = replace_element;
  2935. if (!tinyMCE.settings['debug']) {
  2936. this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');
  2937. this.oldTargetElement.style.display = "none";
  2938. }
  2939. // Output HTML and set editable
  2940. if (tinyMCE.isGecko) {
  2941. var rng = replace_element.ownerDocument.createRange();
  2942. rng.setStartBefore(replace_element);
  2943. var fragment = rng.createContextualFragment(html);
  2944. tinyMCE.insertAfter(fragment, replace_element);
  2945. } else
  2946. replace_element.insertAdjacentHTML("beforeBegin", html);
  2947. }
  2948. // Setup iframe
  2949. var dynamicIFrame = false;
  2950. var tElm = targetDoc.getElementById(this.editorId);
  2951. if (!tinyMCE.isIE) {
  2952. // Node case is preserved in XML strict mode
  2953. if (tElm && (tElm.nodeName == "SPAN" || tElm.nodeName == "span")) {
  2954. tElm = tinyMCE._createIFrame(tElm, targetDoc);
  2955. dynamicIFrame = true;
  2956. }
  2957. this.targetElement = tElm;
  2958. this.iframeElement = tElm;
  2959. this.contentDocument = tElm.contentDocument;
  2960. this.contentWindow = tElm.contentWindow;
  2961. //this.getDoc().designMode = "on";
  2962. } else {
  2963. if (tElm && tElm.nodeName == "SPAN")
  2964. tElm = tinyMCE._createIFrame(tElm, targetDoc, targetDoc.parentWindow);
  2965. else
  2966. tElm = targetDoc.frames[this.editorId];
  2967. this.targetElement = tElm;
  2968. this.iframeElement = targetDoc.getElementById(this.editorId);
  2969. if (tinyMCE.isOpera) {
  2970. this.contentDocument = this.iframeElement.contentDocument;
  2971. this.contentWindow = this.iframeElement.contentWindow;
  2972. dynamicIFrame = true;
  2973. } else {
  2974. this.contentDocument = tElm.window.document;
  2975. this.contentWindow = tElm.window;
  2976. }
  2977. this.getDoc().designMode = "on";
  2978. }
  2979. // Setup base HTML
  2980. var doc = this.contentDocument;
  2981. if (dynamicIFrame) {
  2982. var html = tinyMCE.getParam('doctype') + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + tinyMCE.settings['base_href'] + '" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>';
  2983. try {
  2984. if (!this.isHidden())
  2985. this.getDoc().designMode = "on";
  2986. doc.open();
  2987. doc.write(html);
  2988. doc.close();
  2989. } catch (e) {
  2990. // Failed Mozilla 1.3
  2991. this.getDoc().location.href = tinyMCE.baseURL + "/blank.htm";
  2992. }
  2993. }
  2994. // This timeout is needed in MSIE 5.5 for some odd reason
  2995. // it seems that the document.frames isn't initialized yet?
  2996. if (tinyMCE.isIE)
  2997. window.setTimeout("tinyMCE.addEventHandlers(tinyMCE.instances[\"" + this.editorId + "\"]);", 1);
  2998. // Setup element references
  2999. var parentElm = this.targetDoc.getElementById(this.editorId + '_parent');
  3000. this.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling;
  3001. tinyMCE.setupContent(this.editorId, true);
  3002. return true;
  3003. },
  3004. setBaseHREF : function(u) {
  3005. var h, b, d, nl;
  3006. d = this.getDoc();
  3007. nl = d.getElementsByTagName("base");
  3008. b = nl.length > 0 ? nl[0] : null;
  3009. if (!b) {
  3010. nl = d.getElementsByTagName("head");
  3011. h = nl.length > 0 ? nl[0] : null;
  3012. b = d.createElement("base");
  3013. b.setAttribute('href', u);
  3014. h.appendChild(b);
  3015. } else {
  3016. if (u == "" || u == null)
  3017. b.parentNode.removeChild(b);
  3018. else
  3019. b.setAttribute('href', u);
  3020. }
  3021. },
  3022. getHTML : function(r) {
  3023. var h, d = this.getDoc(), b = this.getBody();
  3024. if (r)
  3025. return b.innerHTML;
  3026. h = tinyMCE._cleanupHTML(this, d, this.settings, b, false, true, false, true);
  3027. if (tinyMCE.getParam("convert_fonts_to_spans"))
  3028. tinyMCE.convertSpansToFonts(d);
  3029. return h;
  3030. },
  3031. setHTML : function(h) {
  3032. this.execCommand('mceSetContent', false, h);
  3033. this.repaint();
  3034. },
  3035. getFocusElement : function() {
  3036. return this.selection.getFocusElement();
  3037. },
  3038. getSel : function() {
  3039. return this.selection.getSel();
  3040. },
  3041. getRng : function() {
  3042. return this.selection.getRng();
  3043. },
  3044. triggerSave : function(skip_cleanup, skip_callback) {
  3045. var e, nl = [], i, s;
  3046. this.switchSettings();
  3047. s = tinyMCE.settings;
  3048. // Force hidden tabs visible while serializing
  3049. if (tinyMCE.isRealIE) {
  3050. e = this.iframeElement;
  3051. do {
  3052. if (e.style && e.style.display == 'none') {
  3053. e.style.display = 'block';
  3054. nl[nl.length] = {elm : e, type : 'style'};
  3055. }
  3056. if (e.style && s.hidden_tab_class.length > 0 && e.className.indexOf(s.hidden_tab_class) != -1) {
  3057. e.className = s.display_tab_class;
  3058. nl[nl.length] = {elm : e, type : 'class'};
  3059. }
  3060. } while ((e = e.parentNode) != null)
  3061. }
  3062. tinyMCE.settings['preformatted'] = false;
  3063. // Default to false
  3064. if (typeof(skip_cleanup) == "undefined")
  3065. skip_cleanup = false;
  3066. // Default to false
  3067. if (typeof(skip_callback) == "undefined")
  3068. skip_callback = false;
  3069. tinyMCE._setHTML(this.getDoc(), this.getBody().innerHTML);
  3070. // Remove visual aids when cleanup is disabled
  3071. if (this.settings['cleanup'] == false) {
  3072. tinyMCE.handleVisualAid(this.getBody(), true, false, this);
  3073. tinyMCE._setEventsEnabled(this.getBody(), true);
  3074. }
  3075. tinyMCE._customCleanup(this, "submit_content_dom", this.contentWindow.document.body);
  3076. var htm = skip_cleanup ? this.getBody().innerHTML : tinyMCE._cleanupHTML(this, this.getDoc(), this.settings, this.getBody(), tinyMCE.visualAid, true, true);
  3077. htm = tinyMCE._customCleanup(this, "submit_content", htm);
  3078. if (!skip_callback && tinyMCE.settings['save_callback'] != "")
  3079. var content = eval(tinyMCE.settings['save_callback'] + "(this.formTargetElementId,htm,this.getBody());");
  3080. // Use callback content if available
  3081. if ((typeof(content) != "undefined") && content != null)
  3082. htm = content;
  3083. // Replace some weird entities (Bug: #1056343)
  3084. htm = tinyMCE.regexpReplace(htm, "&#40;", "(", "gi");
  3085. htm = tinyMCE.regexpReplace(htm, "&#41;", ")", "gi");
  3086. htm = tinyMCE.regexpReplace(htm, "&#59;", ";", "gi");
  3087. htm = tinyMCE.regexpReplace(htm, "&#34;", "&quot;", "gi");
  3088. htm = tinyMCE.regexpReplace(htm, "&#94;", "^", "gi");
  3089. if (this.formElement)
  3090. this.formElement.value = htm;
  3091. if (tinyMCE.isSafari && this.formElement)
  3092. this.formElement.innerText = htm;
  3093. // Hide them again (tabs in MSIE)
  3094. for (i=0; i<nl.length; i++) {
  3095. if (nl[i].type == 'style')
  3096. nl[i].elm.style.display = 'none';
  3097. else
  3098. nl[i].elm.className = s.hidden_tab_class;
  3099. }
  3100. }
  3101. };
  3102. /* file:jscripts/tiny_mce/classes/TinyMCE_Cleanup.class.js */
  3103. TinyMCE_Engine.prototype.cleanupHTMLCode = function(s) {
  3104. s = s.replace(new RegExp('<p \\/>', 'gi'), '<p>&nbsp;</p>');
  3105. s = s.replace(new RegExp('<p>\\s*<\\/p>', 'gi'), '<p>&nbsp;</p>');
  3106. // Fix close BR elements
  3107. s = s.replace(new RegExp('<br>\\s*<\\/br>', 'gi'), '<br />');
  3108. // Open closed tags like <b/> to <b></b>
  3109. s = s.replace(new RegExp('<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|font|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\\\|>]*)\\/>', 'gi'), '<$1$2$3></$1$2>');
  3110. // Remove trailing space <b > to <b>
  3111. s = s.replace(new RegExp('\\s+></', 'gi'), '></');
  3112. // Close tags <img></img> to <img/>
  3113. s = s.replace(new RegExp('<(img|br|hr)([^>]*)><\\/(img|br|hr)>', 'gi'), '<$1$2 />');
  3114. // Weird MSIE bug, <p><hr /></p> breaks runtime?
  3115. if (tinyMCE.isIE)
  3116. s = s.replace(new RegExp('<p><hr \\/><\\/p>', 'gi'), "<hr>");
  3117. // Weird tags will make IE error #bug: 1538495
  3118. if (tinyMCE.isIE)
  3119. s = s.replace(/<!(\s*)\/>/g, '');
  3120. // Convert relative anchors to absolute URLs ex: #something to file.htm#something
  3121. // Removed: Since local document anchors should never be forced absolute example edit.php?id=something
  3122. //if (tinyMCE.getParam('convert_urls'))
  3123. // s = s.replace(new RegExp('(href=\"{0,1})(\\s*#)', 'gi'), '$1' + tinyMCE.settings['document_base_url'] + "#");
  3124. return s;
  3125. };
  3126. TinyMCE_Engine.prototype.parseStyle = function(str) {
  3127. var ar = new Array();
  3128. if (str == null)
  3129. return ar;
  3130. var st = str.split(';');
  3131. tinyMCE.clearArray(ar);
  3132. for (var i=0; i<st.length; i++) {
  3133. if (st[i] == '')
  3134. continue;
  3135. var re = new RegExp('^\\s*([^:]*):\\s*(.*)\\s*$');
  3136. var pa = st[i].replace(re, '$1||$2').split('||');
  3137. //tinyMCE.debug(str, pa[0] + "=" + pa[1], st[i].replace(re, '$1||$2'));
  3138. if (pa.length == 2)
  3139. ar[pa[0].toLowerCase()] = pa[1];
  3140. }
  3141. return ar;
  3142. };
  3143. TinyMCE_Engine.prototype.compressStyle = function(ar, pr, sf, res) {
  3144. var box = new Array();
  3145. box[0] = ar[pr + '-top' + sf];
  3146. box[1] = ar[pr + '-left' + sf];
  3147. box[2] = ar[pr + '-right' + sf];
  3148. box[3] = ar[pr + '-bottom' + sf];
  3149. for (var i=0; i<box.length; i++) {
  3150. if (box[i] == null)
  3151. return;
  3152. for (var a=0; a<box.length; a++) {
  3153. if (box[a] != box[i])
  3154. return;
  3155. }
  3156. }
  3157. // They are all the same
  3158. ar[res] = box[0];
  3159. ar[pr + '-top' + sf] = null;
  3160. ar[pr + '-left' + sf] = null;
  3161. ar[pr + '-right' + sf] = null;
  3162. ar[pr + '-bottom' + sf] = null;
  3163. };
  3164. TinyMCE_Engine.prototype.serializeStyle = function(ar) {
  3165. var str = "";
  3166. // Compress box
  3167. tinyMCE.compressStyle(ar, "border", "", "border");
  3168. tinyMCE.compressStyle(ar, "border", "-width", "border-width");
  3169. tinyMCE.compressStyle(ar, "border", "-color", "border-color");
  3170. tinyMCE.compressStyle(ar, "border", "-style", "border-style");
  3171. tinyMCE.compressStyle(ar, "padding", "", "padding");
  3172. tinyMCE.compressStyle(ar, "margin", "", "margin");
  3173. for (var key in ar) {
  3174. var val = ar[key];
  3175. if (typeof(val) == 'function')
  3176. continue;
  3177. if (key.indexOf('mso-') == 0)
  3178. continue;
  3179. if (val != null && val != '') {
  3180. val = '' + val; // Force string
  3181. // Fix style URL
  3182. val = val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)", 'gi'), "url('$1')");
  3183. // Convert URL
  3184. if (val.indexOf('url(') != -1 && tinyMCE.getParam('convert_urls')) {
  3185. var m = new RegExp("url\\('(.*?)'\\)").exec(val);
  3186. if (m.length > 1)
  3187. val = "url('" + eval(tinyMCE.getParam('urlconverter_callback') + "(m[1], null, true);") + "')";
  3188. }
  3189. // Force HEX colors
  3190. if (tinyMCE.getParam("force_hex_style_colors"))
  3191. val = tinyMCE.convertRGBToHex(val, true);
  3192. val = val.replace(/\"/g, '\'');
  3193. if (val != "url('')")
  3194. str += key.toLowerCase() + ": " + val + "; ";
  3195. }
  3196. }
  3197. if (new RegExp('; $').test(str))
  3198. str = str.substring(0, str.length - 2);
  3199. return str;
  3200. };
  3201. TinyMCE_Engine.prototype.convertRGBToHex = function(s, k) {
  3202. if (s.toLowerCase().indexOf('rgb') != -1) {
  3203. var re = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");
  3204. var rgb = s.replace(re, "$1,$2,$3,$4,$5").split(',');
  3205. if (rgb.length == 5) {
  3206. r = parseInt(rgb[1]).toString(16);
  3207. g = parseInt(rgb[2]).toString(16);
  3208. b = parseInt(rgb[3]).toString(16);
  3209. r = r.length == 1 ? '0' + r : r;
  3210. g = g.length == 1 ? '0' + g : g;
  3211. b = b.length == 1 ? '0' + b : b;
  3212. s = "#" + r + g + b;
  3213. if (k)
  3214. s = rgb[0] + s + rgb[4];
  3215. }
  3216. }
  3217. return s;
  3218. };
  3219. TinyMCE_Engine.prototype.convertHexToRGB = function(s) {
  3220. if (s.indexOf('#') != -1) {
  3221. s = s.replace(new RegExp('[^0-9A-F]', 'gi'), '');
  3222. return "rgb(" + parseInt(s.substring(0, 2), 16) + "," + parseInt(s.substring(2, 4), 16) + "," + parseInt(s.substring(4, 6), 16) + ")";
  3223. }
  3224. return s;
  3225. };
  3226. TinyMCE_Engine.prototype.convertSpansToFonts = function(doc) {
  3227. var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');
  3228. /*var h = doc.body.innerHTML;
  3229. h = h.replace(/<span/gi, '<font');
  3230. h = h.replace(/<\/span/gi, '</font');
  3231. tinyMCE.setInnerHTML(doc.body, h);*/
  3232. var s = tinyMCE.selectElements(doc, 'span,font');
  3233. for (var i=0; i<s.length; i++) {
  3234. var size = tinyMCE.trim(s[i].style.fontSize).toLowerCase();
  3235. var fSize = 0;
  3236. for (var x=0; x<sizes.length; x++) {
  3237. if (sizes[x] == size) {
  3238. fSize = x + 1;
  3239. break;
  3240. }
  3241. }
  3242. if (fSize > 0) {
  3243. tinyMCE.setAttrib(s[i], 'size', fSize);
  3244. s[i].style.fontSize = '';
  3245. }
  3246. var fFace = s[i].style.fontFamily;
  3247. if (fFace != null && fFace != "") {
  3248. tinyMCE.setAttrib(s[i], 'face', fFace);
  3249. s[i].style.fontFamily = '';
  3250. }
  3251. var fColor = s[i].style.color;
  3252. if (fColor != null && fColor != "") {
  3253. tinyMCE.setAttrib(s[i], 'color', tinyMCE.convertRGBToHex(fColor));
  3254. s[i].style.color = '';
  3255. }
  3256. }
  3257. };
  3258. TinyMCE_Engine.prototype.convertFontsToSpans = function(doc) {
  3259. var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');
  3260. /* var h = doc.body.innerHTML;
  3261. h = h.replace(/<font/gi, '<span');
  3262. h = h.replace(/<\/font/gi, '</span');
  3263. tinyMCE.setInnerHTML(doc.body, h);*/
  3264. var fsClasses = tinyMCE.getParam('font_size_classes');
  3265. if (fsClasses != '')
  3266. fsClasses = fsClasses.replace(/\s+/, '').split(',');
  3267. else
  3268. fsClasses = null;
  3269. var s = tinyMCE.selectElements(doc, 'span,font');
  3270. for (var i=0; i<s.length; i++) {
  3271. var fSize, fFace, fColor;
  3272. fSize = tinyMCE.getAttrib(s[i], 'size');
  3273. fFace = tinyMCE.getAttrib(s[i], 'face');
  3274. fColor = tinyMCE.getAttrib(s[i], 'color');
  3275. if (fSize != "") {
  3276. fSize = parseInt(fSize);
  3277. if (fSize > 0 && fSize < 8) {
  3278. if (fsClasses != null)
  3279. tinyMCE.setAttrib(s[i], 'class', fsClasses[fSize-1]);
  3280. else
  3281. s[i].style.fontSize = sizes[fSize-1];
  3282. }
  3283. s[i].removeAttribute('size');
  3284. }
  3285. if (fFace != "") {
  3286. s[i].style.fontFamily = fFace;
  3287. s[i].removeAttribute('face');
  3288. }
  3289. if (fColor != "") {
  3290. s[i].style.color = fColor;
  3291. s[i].removeAttribute('color');
  3292. }
  3293. }
  3294. };
  3295. TinyMCE_Engine.prototype.cleanupAnchors = function(doc) {
  3296. var i, cn, x, an = doc.getElementsByTagName("a");
  3297. // Loops backwards due to bug #1467987
  3298. for (i=an.length-1; i>=0; i--) {
  3299. if (tinyMCE.getAttrib(an[i], "name") != "" && tinyMCE.getAttrib(an[i], "href") == "") {
  3300. cn = an[i].childNodes;
  3301. for (x=cn.length-1; x>=0; x--)
  3302. tinyMCE.insertAfter(cn[x], an[i]);
  3303. }
  3304. }
  3305. };
  3306. TinyMCE_Engine.prototype.getContent = function(editor_id) {
  3307. if (typeof(editor_id) != "undefined")
  3308. tinyMCE.getInstanceById(editor_id).select();
  3309. if (tinyMCE.selectedInstance)
  3310. return tinyMCE.selectedInstance.getHTML();
  3311. return null;
  3312. };
  3313. TinyMCE_Engine.prototype._fixListElements = function(d) {
  3314. var nl, x, a = ['ol', 'ul'], i, n, p, r = new RegExp('^(OL|UL)$'), np;
  3315. for (x=0; x<a.length; x++) {
  3316. nl = d.getElementsByTagName(a[x]);
  3317. for (i=0; i<nl.length; i++) {
  3318. n = nl[i];
  3319. p = n.parentNode;
  3320. if (r.test(p.nodeName)) {
  3321. np = tinyMCE.prevNode(n, 'LI');
  3322. if (!np) {
  3323. np = d.createElement('li');
  3324. np.innerHTML = '&nbsp;';
  3325. np.appendChild(n);
  3326. p.insertBefore(np, p.firstChild);
  3327. } else
  3328. np.appendChild(n);
  3329. }
  3330. }
  3331. }
  3332. };
  3333. TinyMCE_Engine.prototype._fixTables = function(d) {
  3334. var nl, i, n, p, np, x, t;
  3335. nl = d.getElementsByTagName('table');
  3336. for (i=0; i<nl.length; i++) {
  3337. n = nl[i];
  3338. if ((p = tinyMCE.getParentElement(n, 'p,h1,h2,h3,h4,h5,h6')) != null) {
  3339. np = p.cloneNode(false);
  3340. np.removeAttribute('id');
  3341. t = n;
  3342. while ((n = n.nextSibling))
  3343. np.appendChild(n);
  3344. tinyMCE.insertAfter(np, p);
  3345. tinyMCE.insertAfter(t, p);
  3346. }
  3347. }
  3348. };
  3349. TinyMCE_Engine.prototype._cleanupHTML = function(inst, doc, config, elm, visual, on_save, on_submit, inn) {
  3350. var h, d, t1, t2, t3, t4, t5, c, s, nb;
  3351. if (!tinyMCE.getParam('cleanup'))
  3352. return elm.innerHTML;
  3353. on_save = typeof(on_save) == 'undefined' ? false : on_save;
  3354. c = inst.cleanup;
  3355. s = inst.settings;
  3356. d = c.settings.debug;
  3357. if (d)
  3358. t1 = new Date().getTime();
  3359. if (tinyMCE.getParam("convert_fonts_to_spans"))
  3360. tinyMCE.convertFontsToSpans(doc);
  3361. if (tinyMCE.getParam("fix_list_elements"))
  3362. tinyMCE._fixListElements(doc);
  3363. if (tinyMCE.getParam("fix_table_elements"))
  3364. tinyMCE._fixTables(doc);
  3365. // Call custom cleanup code
  3366. tinyMCE._customCleanup(inst, on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body);
  3367. if (d)
  3368. t2 = new Date().getTime();
  3369. c.settings.on_save = on_save;
  3370. //for (var i=0; i<100; i++)
  3371. c.idCount = 0;
  3372. c.serializationId++;
  3373. c.serializedNodes = new Array();
  3374. c.sourceIndex = -1;
  3375. if (s.cleanup_serializer == "xml")
  3376. h = c.serializeNodeAsXML(elm, inn);
  3377. else
  3378. h = c.serializeNodeAsHTML(elm, inn);
  3379. if (d)
  3380. t3 = new Date().getTime();
  3381. // Post processing
  3382. nb = tinyMCE.getParam('entity_encoding') == 'numeric' ? '&#160;' : '&nbsp;';
  3383. h = h.replace(/<\/?(body|head|html)[^>]*>/gi, '');
  3384. h = h.replace(new RegExp(' (rowspan="1"|colspan="1")', 'g'), '');
  3385. h = h.replace(/<p><hr \/><\/p>/g, '<hr />');
  3386. h = h.replace(/<p>(&nbsp;|&#160;)<\/p><hr \/><p>(&nbsp;|&#160;)<\/p>/g, '<hr />');
  3387. h = h.replace(/<td>\s*<br \/>\s*<\/td>/g, '<td>' + nb + '</td>');
  3388. h = h.replace(/<p>\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');
  3389. h = h.replace(/<br \/>$/, ''); // Remove last BR for Gecko
  3390. h = h.replace(/<br \/><\/p>/g, '</p>'); // Remove last BR in P tags for Gecko
  3391. h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*(&nbsp;|&#160;)\s*<\/p>/g, '<p>' + nb + '</p>');
  3392. h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');
  3393. h = h.replace(/<p>\s*<br \/>\s*&nbsp;\s*<\/p>/g, '<p>' + nb + '</p>');
  3394. h = h.replace(new RegExp('<a>(.*?)<\\/a>', 'g'), '$1');
  3395. h = h.replace(/<p([^>]*)>\s*<\/p>/g, '<p$1>' + nb + '</p>');
  3396. // Clean body
  3397. if (/^\s*(<br \/>|<p>&nbsp;<\/p>|<p>&#160;<\/p>|<p><\/p>)\s*$/.test(h))
  3398. h = '';
  3399. // If preformatted
  3400. if (s.preformatted) {
  3401. h = h.replace(/^<pre>/, '');
  3402. h = h.replace(/<\/pre>$/, '');
  3403. h = '<pre>' + h + '</pre>';
  3404. }
  3405. // Gecko specific processing
  3406. if (tinyMCE.isGecko) {
  3407. h = h.replace(/<o:p _moz-userdefined="" \/>/g, '');
  3408. h = h.replace(/<td([^>]*)>\s*<br \/>\s*<\/td>/g, '<td$1>' + nb + '</td>');
  3409. }
  3410. if (s.force_br_newlines)
  3411. h = h.replace(/<p>(&nbsp;|&#160;)<\/p>/g, '<br />');
  3412. // Call custom cleanup code
  3413. h = tinyMCE._customCleanup(inst, on_save ? "get_from_editor" : "insert_to_editor", h);
  3414. // Remove internal classes
  3415. if (on_save) {
  3416. h = h.replace(new RegExp(' ?(mceItem[a-zA-Z0-9]*|' + s.visual_table_class + ')', 'g'), '');
  3417. h = h.replace(new RegExp(' ?class=""', 'g'), '');
  3418. }
  3419. if (s.remove_linebreaks && !c.settings.indent)
  3420. h = h.replace(/\n|\r/g, ' ');
  3421. if (d)
  3422. t4 = new Date().getTime();
  3423. if (on_save && c.settings.indent)
  3424. h = c.formatHTML(h);
  3425. // If encoding (not recommended option)
  3426. if (on_submit && (s.encoding == "xml" || s.encoding == "html"))
  3427. h = c.xmlEncode(h);
  3428. if (d)
  3429. t5 = new Date().getTime();
  3430. if (c.settings.debug)
  3431. tinyMCE.debug("Cleanup in ms: Pre=" + (t2-t1) + ", Serialize: " + (t3-t2) + ", Post: " + (t4-t3) + ", Format: " + (t5-t4) + ", Sum: " + (t5-t1) + ".");
  3432. return h;
  3433. };
  3434. function TinyMCE_Cleanup() {
  3435. this.isIE = (navigator.appName == "Microsoft Internet Explorer");
  3436. this.rules = tinyMCE.clearArray(new Array());
  3437. // Default config
  3438. this.settings = {
  3439. indent_elements : 'head,table,tbody,thead,tfoot,form,tr,ul,ol,blockquote,object',
  3440. newline_before_elements : 'h1,h2,h3,h4,h5,h6,pre,address,div,ul,ol,li,meta,option,area,title,link,base,script,td',
  3441. newline_after_elements : 'br,hr,p,pre,address,div,ul,ol,meta,option,area,link,base,script',
  3442. newline_before_after_elements : 'html,head,body,table,thead,tbody,tfoot,tr,form,ul,ol,blockquote,p,object,param,hr,div',
  3443. indent_char : '\t',
  3444. indent_levels : 1,
  3445. entity_encoding : 'raw',
  3446. valid_elements : '*[*]',
  3447. entities : '',
  3448. url_converter : '',
  3449. invalid_elements : '',
  3450. verify_html : false
  3451. };
  3452. this.vElements = tinyMCE.clearArray(new Array());
  3453. this.vElementsRe = '';
  3454. this.closeElementsRe = /^(IMG|BR|HR|LINK|META|BASE|INPUT|AREA)$/;
  3455. this.codeElementsRe = /^(SCRIPT|STYLE)$/;
  3456. this.serializationId = 0;
  3457. this.mceAttribs = {
  3458. href : 'mce_href',
  3459. src : 'mce_src',
  3460. type : 'mce_type'
  3461. };
  3462. }
  3463. TinyMCE_Cleanup.prototype = {
  3464. init : function(s) {
  3465. var n, a, i, ir, or, st;
  3466. for (n in s)
  3467. this.settings[n] = s[n];
  3468. // Setup code formating
  3469. s = this.settings;
  3470. // Setup regexps
  3471. this.inRe = this._arrayToRe(s.indent_elements.split(','), '', '^<(', ')[^>]*');
  3472. this.ouRe = this._arrayToRe(s.indent_elements.split(','), '', '^<\\/(', ')[^>]*');
  3473. this.nlBeforeRe = this._arrayToRe(s.newline_before_elements.split(','), 'gi', '<(', ')([^>]*)>');
  3474. this.nlAfterRe = this._arrayToRe(s.newline_after_elements.split(','), 'gi', '<(', ')([^>]*)>');
  3475. this.nlBeforeAfterRe = this._arrayToRe(s.newline_before_after_elements.split(','), 'gi', '<(\\/?)(', ')([^>]*)>');
  3476. this.serializedNodes = [];
  3477. if (s.invalid_elements != '')
  3478. this.iveRe = this._arrayToRe(s.invalid_elements.toUpperCase().split(','), 'g', '^(', ')$');
  3479. else
  3480. this.iveRe = null;
  3481. // Setup separator
  3482. st = '';
  3483. for (i=0; i<s.indent_levels; i++)
  3484. st += s.indent_char;
  3485. this.inStr = st;
  3486. // If verify_html if false force *[*]
  3487. if (!s.verify_html) {
  3488. s.valid_elements = '*[*]';
  3489. s.extended_valid_elements = '';
  3490. }
  3491. this.fillStr = s.entity_encoding == "named" ? "&nbsp;" : "&#160;";
  3492. this.idCount = 0;
  3493. this.xmlEncodeRe = new RegExp('[\u007F-\uFFFF<>&"]', 'g');
  3494. this.xmlEncodeAposRe = new RegExp('[\u007F-\uFFFF<>&"\']', 'g');
  3495. },
  3496. addRuleStr : function(s) {
  3497. var r = this.parseRuleStr(s);
  3498. var n;
  3499. for (n in r) {
  3500. if (r[n])
  3501. this.rules[n] = r[n];
  3502. }
  3503. this.vElements = tinyMCE.clearArray(new Array());
  3504. for (n in this.rules) {
  3505. if (this.rules[n])
  3506. this.vElements[this.vElements.length] = this.rules[n].tag;
  3507. }
  3508. this.vElementsRe = this._arrayToRe(this.vElements, '');
  3509. },
  3510. isValid : function(n) {
  3511. this._setupRules(); // Will initialize cleanup rules
  3512. // Empty is true since it removes formatting
  3513. if (!n)
  3514. return true;
  3515. // Clean the name up a bit
  3516. n = n.replace(/[^a-z0-9]+/gi, '').toUpperCase();
  3517. return !tinyMCE.getParam('cleanup') || this.vElementsRe.test(n);
  3518. },
  3519. addChildRemoveRuleStr : function(s) {
  3520. var x, y, p, i, t, tn, ta, cl, r;
  3521. if (!s)
  3522. return;
  3523. ta = s.split(',');
  3524. for (x=0; x<ta.length; x++) {
  3525. s = ta[x];
  3526. // Split tag/children
  3527. p = this.split(/\[|\]/, s);
  3528. if (p == null || p.length < 1)
  3529. t = s.toUpperCase();
  3530. else
  3531. t = p[0].toUpperCase();
  3532. // Handle all tag names
  3533. tn = this.split('/', t);
  3534. for (y=0; y<tn.length; y++) {
  3535. r = "^(";
  3536. // Build regex
  3537. cl = this.split(/\|/, p[1]);
  3538. for (i=0; i<cl.length; i++) {
  3539. if (cl[i] == '%istrict')
  3540. r += tinyMCE.inlineStrict;
  3541. else if (cl[i] == '%itrans')
  3542. r += tinyMCE.inlineTransitional;
  3543. else if (cl[i] == '%istrict_na')
  3544. r += tinyMCE.inlineStrict.substring(2);
  3545. else if (cl[i] == '%itrans_na')
  3546. r += tinyMCE.inlineTransitional.substring(2);
  3547. else if (cl[i] == '%btrans')
  3548. r += tinyMCE.blockElms;
  3549. else if (cl[i] == '%strict')
  3550. r += tinyMCE.blockStrict;
  3551. else
  3552. r += (cl[i].charAt(0) != '#' ? cl[i].toUpperCase() : cl[i]);
  3553. r += (i != cl.length - 1 ? '|' : '');
  3554. }
  3555. r += ')$';
  3556. //tinyMCE.debug(t + "=" + r);
  3557. if (this.childRules == null)
  3558. this.childRules = tinyMCE.clearArray(new Array());
  3559. this.childRules[tn[y]] = new RegExp(r);
  3560. if (p.length > 1)
  3561. this.childRules[tn[y]].wrapTag = p[2];
  3562. }
  3563. }
  3564. },
  3565. parseRuleStr : function(s) {
  3566. var ta, p, r, a, i, x, px, t, tn, y, av, or = tinyMCE.clearArray(new Array()), dv;
  3567. if (s == null || s.length == 0)
  3568. return or;
  3569. ta = s.split(',');
  3570. for (x=0; x<ta.length; x++) {
  3571. s = ta[x];
  3572. if (s.length == 0)
  3573. continue;
  3574. // Split tag/attrs
  3575. p = this.split(/\[|\]/, s);
  3576. if (p == null || p.length < 1)
  3577. t = s.toUpperCase();
  3578. else
  3579. t = p[0].toUpperCase();
  3580. // Handle all tag names
  3581. tn = this.split('/', t);
  3582. for (y=0; y<tn.length; y++) {
  3583. r = {};
  3584. r.tag = tn[y];
  3585. r.forceAttribs = null;
  3586. r.defaultAttribs = null;
  3587. r.validAttribValues = null;
  3588. // Handle prefixes
  3589. px = r.tag.charAt(0);
  3590. r.forceOpen = px == '+';
  3591. r.removeEmpty = px == '-';
  3592. r.fill = px == '#';
  3593. r.tag = r.tag.replace(/\+|-|#/g, '');
  3594. r.oTagName = tn[0].replace(/\+|-|#/g, '').toLowerCase();
  3595. r.isWild = new RegExp('\\*|\\?|\\+', 'g').test(r.tag);
  3596. r.validRe = new RegExp(this._wildcardToRe('^' + r.tag + '$'));
  3597. // Setup valid attributes
  3598. if (p.length > 1) {
  3599. r.vAttribsRe = '^(';
  3600. a = this.split(/\|/, p[1]);
  3601. for (i=0; i<a.length; i++) {
  3602. t = a[i];
  3603. if (t.charAt(0) == '!') {
  3604. a[i] = t = t.substring(1);
  3605. if (!r.reqAttribsRe)
  3606. r.reqAttribsRe = '\\s+(' + t;
  3607. else
  3608. r.reqAttribsRe += '|' + t;
  3609. }
  3610. av = new RegExp('(=|:|<)(.*?)$').exec(t);
  3611. t = t.replace(new RegExp('(=|:|<).*?$'), '');
  3612. if (av && av.length > 0) {
  3613. if (av[0].charAt(0) == ':') {
  3614. if (!r.forceAttribs)
  3615. r.forceAttribs = tinyMCE.clearArray(new Array());
  3616. r.forceAttribs[t.toLowerCase()] = av[0].substring(1);
  3617. } else if (av[0].charAt(0) == '=') {
  3618. if (!r.defaultAttribs)
  3619. r.defaultAttribs = tinyMCE.clearArray(new Array());
  3620. dv = av[0].substring(1);
  3621. r.defaultAttribs[t.toLowerCase()] = dv == "" ? "mce_empty" : dv;
  3622. } else if (av[0].charAt(0) == '<') {
  3623. if (!r.validAttribValues)
  3624. r.validAttribValues = tinyMCE.clearArray(new Array());
  3625. r.validAttribValues[t.toLowerCase()] = this._arrayToRe(this.split('?', av[0].substring(1)), 'i');
  3626. }
  3627. }
  3628. r.vAttribsRe += '' + t.toLowerCase() + (i != a.length - 1 ? '|' : '');
  3629. a[i] = t.toLowerCase();
  3630. }
  3631. if (r.reqAttribsRe)
  3632. r.reqAttribsRe = new RegExp(r.reqAttribsRe + ')=\"', 'g');
  3633. r.vAttribsRe += ')$';
  3634. r.vAttribsRe = this._wildcardToRe(r.vAttribsRe);
  3635. r.vAttribsReIsWild = new RegExp('\\*|\\?|\\+', 'g').test(r.vAttribsRe);
  3636. r.vAttribsRe = new RegExp(r.vAttribsRe);
  3637. r.vAttribs = a.reverse();
  3638. //tinyMCE.debug(r.tag, r.oTagName, r.vAttribsRe, r.vAttribsReWC);
  3639. } else {
  3640. r.vAttribsRe = '';
  3641. r.vAttribs = tinyMCE.clearArray(new Array());
  3642. r.vAttribsReIsWild = false;
  3643. }
  3644. or[r.tag] = r;
  3645. }
  3646. }
  3647. return or;
  3648. },
  3649. serializeNodeAsXML : function(n) {
  3650. var s, b;
  3651. if (!this.xmlDoc) {
  3652. if (this.isIE) {
  3653. try {this.xmlDoc = new ActiveXObject('MSXML2.DOMDocument');} catch (e) {}
  3654. if (!this.xmlDoc)
  3655. try {this.xmlDoc = new ActiveXObject('Microsoft.XmlDom');} catch (e) {}
  3656. } else
  3657. this.xmlDoc = document.implementation.createDocument('', '', null);
  3658. if (!this.xmlDoc)
  3659. alert("Error XML Parser could not be found.");
  3660. }
  3661. if (this.xmlDoc.firstChild)
  3662. this.xmlDoc.removeChild(this.xmlDoc.firstChild);
  3663. b = this.xmlDoc.createElement("html");
  3664. b = this.xmlDoc.appendChild(b);
  3665. this._convertToXML(n, b);
  3666. if (this.isIE)
  3667. return this.xmlDoc.xml;
  3668. else
  3669. return new XMLSerializer().serializeToString(this.xmlDoc);
  3670. },
  3671. _convertToXML : function(n, xn) {
  3672. var xd, el, i, l, cn, at, no, hc = false;
  3673. if (tinyMCE.isRealIE && this._isDuplicate(n))
  3674. return;
  3675. xd = this.xmlDoc;
  3676. switch (n.nodeType) {
  3677. case 1: // Element
  3678. hc = n.hasChildNodes();
  3679. el = xd.createElement(n.nodeName.toLowerCase());
  3680. at = n.attributes;
  3681. for (i=at.length-1; i>-1; i--) {
  3682. no = at[i];
  3683. if (no.specified && no.nodeValue)
  3684. el.setAttribute(no.nodeName.toLowerCase(), no.nodeValue);
  3685. }
  3686. if (!hc && !this.closeElementsRe.test(n.nodeName))
  3687. el.appendChild(xd.createTextNode(""));
  3688. xn = xn.appendChild(el);
  3689. break;
  3690. case 3: // Text
  3691. xn.appendChild(xd.createTextNode(n.nodeValue));
  3692. return;
  3693. case 8: // Comment
  3694. xn.appendChild(xd.createComment(n.nodeValue));
  3695. return;
  3696. }
  3697. if (hc) {
  3698. cn = n.childNodes;
  3699. for (i=0, l=cn.length; i<l; i++)
  3700. this._convertToXML(cn[i], xn);
  3701. }
  3702. },
  3703. serializeNodeAsHTML : function(n, inn) {
  3704. var en, no, h = '', i, l, t, st, r, cn, va = false, f = false, at, hc, cr, nn;
  3705. this._setupRules(); // Will initialize cleanup rules
  3706. if (tinyMCE.isRealIE && this._isDuplicate(n))
  3707. return '';
  3708. // Skip non valid child elements
  3709. if (n.parentNode && this.childRules != null) {
  3710. cr = this.childRules[n.parentNode.nodeName];
  3711. if (typeof(cr) != "undefined" && !cr.test(n.nodeName)) {
  3712. st = true;
  3713. t = null;
  3714. }
  3715. }
  3716. switch (n.nodeType) {
  3717. case 1: // Element
  3718. hc = n.hasChildNodes();
  3719. if (st)
  3720. break;
  3721. // MSIE sometimes produces <//tag>
  3722. if ((tinyMCE.isRealIE) && n.nodeName.indexOf('/') != -1)
  3723. break;
  3724. nn = n.nodeName;
  3725. // Convert fonts to spans
  3726. if (this.settings.convert_fonts_to_spans) {
  3727. // On get content FONT -> SPAN
  3728. if (this.settings.on_save && nn == 'FONT')
  3729. nn = 'SPAN';
  3730. // On insert content SPAN -> FONT
  3731. if (!this.settings.on_save && nn == 'SPAN')
  3732. nn = 'FONT';
  3733. }
  3734. if (this.vElementsRe.test(nn) && (!this.iveRe || !this.iveRe.test(nn)) && !inn) {
  3735. va = true;
  3736. r = this.rules[nn];
  3737. if (!r) {
  3738. at = this.rules;
  3739. for (no in at) {
  3740. if (at[no] && at[no].validRe.test(nn)) {
  3741. r = at[no];
  3742. break;
  3743. }
  3744. }
  3745. }
  3746. en = r.isWild ? nn.toLowerCase() : r.oTagName;
  3747. f = r.fill;
  3748. if (r.removeEmpty && !hc)
  3749. return "";
  3750. t = '<' + en;
  3751. if (r.vAttribsReIsWild) {
  3752. // Serialize wildcard attributes
  3753. at = n.attributes;
  3754. for (i=at.length-1; i>-1; i--) {
  3755. no = at[i];
  3756. if (no.specified && r.vAttribsRe.test(no.nodeName))
  3757. t += this._serializeAttribute(n, r, no.nodeName);
  3758. }
  3759. } else {
  3760. // Serialize specific attributes
  3761. for (i=r.vAttribs.length-1; i>-1; i--)
  3762. t += this._serializeAttribute(n, r, r.vAttribs[i]);
  3763. }
  3764. // Serialize mce_ atts
  3765. if (!this.settings.on_save) {
  3766. at = this.mceAttribs;
  3767. for (no in at) {
  3768. if (at[no])
  3769. t += this._serializeAttribute(n, r, at[no]);
  3770. }
  3771. }
  3772. // Check for required attribs
  3773. if (r.reqAttribsRe && !t.match(r.reqAttribsRe))
  3774. t = null;
  3775. // Close these
  3776. if (t != null && this.closeElementsRe.test(nn))
  3777. return t + ' />';
  3778. if (t != null)
  3779. h += t + '>';
  3780. if (this.isIE && this.codeElementsRe.test(nn))
  3781. h += n.innerHTML;
  3782. }
  3783. break;
  3784. case 3: // Text
  3785. if (st)
  3786. break;
  3787. if (n.parentNode && this.codeElementsRe.test(n.parentNode.nodeName))
  3788. return this.isIE ? '' : n.nodeValue;
  3789. return this.xmlEncode(n.nodeValue);
  3790. case 8: // Comment
  3791. if (st)
  3792. break;
  3793. return "<!--" + this._trimComment(n.nodeValue) + "-->";
  3794. }
  3795. if (hc) {
  3796. cn = n.childNodes;
  3797. for (i=0, l=cn.length; i<l; i++)
  3798. h += this.serializeNodeAsHTML(cn[i]);
  3799. }
  3800. // Fill empty nodes
  3801. if (f && !hc)
  3802. h += this.fillStr;
  3803. // End element
  3804. if (t != null && va)
  3805. h += '</' + en + '>';
  3806. return h;
  3807. },
  3808. _serializeAttribute : function(n, r, an) {
  3809. var av = '', t, os = this.settings.on_save;
  3810. if (os && (an.indexOf('mce_') == 0 || an.indexOf('_moz') == 0))
  3811. return '';
  3812. if (os && this.mceAttribs[an])
  3813. av = this._getAttrib(n, this.mceAttribs[an]);
  3814. if (av.length == 0)
  3815. av = this._getAttrib(n, an);
  3816. if (av.length == 0 && r.defaultAttribs && (t = r.defaultAttribs[an])) {
  3817. av = t;
  3818. if (av == "mce_empty")
  3819. return " " + an + '=""';
  3820. }
  3821. if (r.forceAttribs && (t = r.forceAttribs[an]))
  3822. av = t;
  3823. if (os && av.length != 0 && /^(src|href|longdesc)$/.test(an))
  3824. av = this._urlConverter(this, n, av);
  3825. if (av.length != 0 && r.validAttribValues && r.validAttribValues[an] && !r.validAttribValues[an].test(av))
  3826. return "";
  3827. if (av.length != 0 && av == "{$uid}")
  3828. av = "uid_" + (this.idCount++);
  3829. if (av.length != 0) {
  3830. if (an.indexOf('on') != 0)
  3831. av = this.xmlEncode(av, 1);
  3832. return " " + an + "=" + '"' + av + '"';
  3833. }
  3834. return "";
  3835. },
  3836. formatHTML : function(h) {
  3837. var s = this.settings, p = '', i = 0, li = 0, o = '', l;
  3838. // Replace BR in pre elements to \n
  3839. h = h.replace(/<pre([^>]*)>(.*?)<\/pre>/gi, function (a, b, c) {
  3840. c = c.replace(/<br\s*\/>/gi, '\n');
  3841. return '<pre' + b + '>' + c + '</pre>';
  3842. });
  3843. h = h.replace(/\r/g, ''); // Windows sux, isn't carriage return a thing of the past :)
  3844. h = '\n' + h;
  3845. h = h.replace(new RegExp('\\n\\s+', 'gi'), '\n'); // Remove previous formatting
  3846. h = h.replace(this.nlBeforeRe, '\n<$1$2>');
  3847. h = h.replace(this.nlAfterRe, '<$1$2>\n');
  3848. h = h.replace(this.nlBeforeAfterRe, '\n<$1$2$3>\n');
  3849. h += '\n';
  3850. //tinyMCE.debug(h);
  3851. while ((i = h.indexOf('\n', i + 1)) != -1) {
  3852. if ((l = h.substring(li + 1, i)).length != 0) {
  3853. if (this.ouRe.test(l) && p.length >= s.indent_levels)
  3854. p = p.substring(s.indent_levels);
  3855. o += p + l + '\n';
  3856. if (this.inRe.test(l))
  3857. p += this.inStr;
  3858. }
  3859. li = i;
  3860. }
  3861. //tinyMCE.debug(h);
  3862. return o;
  3863. },
  3864. xmlEncode : function(s, skip_apos) {
  3865. var cl = this, re = !skip_apos ? this.xmlEncodeAposRe : this.xmlEncodeRe;
  3866. this._setupEntities(); // Will intialize lookup table
  3867. switch (this.settings.entity_encoding) {
  3868. case "raw":
  3869. return tinyMCE.xmlEncode(s, skip_apos);
  3870. case "named":
  3871. return s.replace(re, function (c, b) {
  3872. b = cl.entities[c.charCodeAt(0)];
  3873. return b ? '&' + b + ';' : c;
  3874. });
  3875. case "numeric":
  3876. return s.replace(re, function (c, b) {
  3877. return b ? '&#' + c.charCodeAt(0) + ';' : c;
  3878. });
  3879. }
  3880. return s;
  3881. },
  3882. split : function(re, s) {
  3883. var c = s.split(re);
  3884. var i, l, o = new Array();
  3885. for (i=0, l=c.length; i<l; i++) {
  3886. if (c[i] != '')
  3887. o[i] = c[i];
  3888. }
  3889. return o;
  3890. },
  3891. _trimComment : function(s) {
  3892. // Remove mce_src, mce_href
  3893. s = s.replace(new RegExp('\\smce_src=\"[^\"]*\"', 'gi'), "");
  3894. s = s.replace(new RegExp('\\smce_href=\"[^\"]*\"', 'gi'), "");
  3895. return s;
  3896. },
  3897. _getAttrib : function(e, n, d) {
  3898. var v, ex, nn;
  3899. if (typeof(d) == "undefined")
  3900. d = "";
  3901. if (!e || e.nodeType != 1)
  3902. return d;
  3903. try {
  3904. v = e.getAttribute(n, 0);
  3905. } catch (ex) {
  3906. // IE 7 may cast exception on invalid attributes
  3907. v = e.getAttribute(n, 2);
  3908. }
  3909. if (n == "class" && !v)
  3910. v = e.className;
  3911. if (this.isIE) {
  3912. if (n == "http-equiv")
  3913. v = e.httpEquiv;
  3914. nn = e.nodeName;
  3915. // Skip the default values that IE returns
  3916. if (nn == "FORM" && n == "enctype" && v == "application/x-www-form-urlencoded")
  3917. v = "";
  3918. if (nn == "INPUT" && n == "size" && v == "20")
  3919. v = "";
  3920. if (nn == "INPUT" && n == "maxlength" && v == "2147483647")
  3921. v = "";
  3922. }
  3923. if (n == 'style' && v) {
  3924. if (!tinyMCE.isOpera)
  3925. v = e.style.cssText;
  3926. v = tinyMCE.serializeStyle(tinyMCE.parseStyle(v));
  3927. }
  3928. if (this.settings.on_save && n.indexOf('on') != -1 && this.settings.on_save && v && v != "")
  3929. v = tinyMCE.cleanupEventStr(v);
  3930. return (v && v != "") ? '' + v : d;
  3931. },
  3932. _urlConverter : function(c, n, v) {
  3933. if (!c.settings.on_save)
  3934. return tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, v);
  3935. else if (tinyMCE.getParam('convert_urls')) {
  3936. if (!this.urlConverter)
  3937. this.urlConverter = eval(tinyMCE.settings.urlconverter_callback);
  3938. return this.urlConverter(v, n, true);
  3939. }
  3940. return v;
  3941. },
  3942. _arrayToRe : function(a, op, be, af) {
  3943. var i, r;
  3944. op = typeof(op) == "undefined" ? "gi" : op;
  3945. be = typeof(be) == "undefined" ? "^(" : be;
  3946. af = typeof(af) == "undefined" ? ")$" : af;
  3947. r = be;
  3948. for (i=0; i<a.length; i++)
  3949. r += this._wildcardToRe(a[i]) + (i != a.length-1 ? "|" : "");
  3950. r += af;
  3951. return new RegExp(r, op);
  3952. },
  3953. _wildcardToRe : function(s) {
  3954. s = s.replace(/\?/g, '(\\S?)');
  3955. s = s.replace(/\+/g, '(\\S+)');
  3956. s = s.replace(/\*/g, '(\\S*)');
  3957. return s;
  3958. },
  3959. _setupEntities : function() {
  3960. var n, a, i, s = this.settings;
  3961. // Setup entities
  3962. if (!this.entitiesDone) {
  3963. if (s.entity_encoding == "named") {
  3964. n = tinyMCE.clearArray(new Array());
  3965. a = this.split(',', s.entities);
  3966. for (i=0; i<a.length; i+=2)
  3967. n[a[i]] = a[i+1];
  3968. this.entities = n;
  3969. }
  3970. this.entitiesDone = true;
  3971. }
  3972. },
  3973. _setupRules : function() {
  3974. var s = this.settings;
  3975. // Setup default rule
  3976. if (!this.rulesDone) {
  3977. this.addRuleStr(s.valid_elements);
  3978. this.addRuleStr(s.extended_valid_elements);
  3979. this.addChildRemoveRuleStr(s.valid_child_elements);
  3980. this.rulesDone = true;
  3981. }
  3982. },
  3983. _isDuplicate : function(n) {
  3984. var i;
  3985. if (!this.settings.fix_content_duplication)
  3986. return false;
  3987. if (tinyMCE.isRealIE && n.nodeType == 1) {
  3988. // Mark elements
  3989. if (n.mce_serialized == this.serializationId)
  3990. return true;
  3991. n.setAttribute('mce_serialized', this.serializationId);
  3992. } else {
  3993. // Search lookup table for text nodes and comments
  3994. for (i=0; i<this.serializedNodes.length; i++) {
  3995. if (this.serializedNodes[i] == n)
  3996. return true;
  3997. }
  3998. this.serializedNodes[this.serializedNodes.length] = n;
  3999. }
  4000. return false;
  4001. }
  4002. };
  4003. /* file:jscripts/tiny_mce/classes/TinyMCE_DOMUtils.class.js */
  4004. TinyMCE_Engine.prototype.createTagHTML = function(tn, a, h) {
  4005. var o = '', f = tinyMCE.xmlEncode;
  4006. o = '<' + tn;
  4007. if (a) {
  4008. for (n in a) {
  4009. if (typeof(a[n]) != 'function' && a[n] != null)
  4010. o += ' ' + f(n) + '="' + f('' + a[n]) + '"';
  4011. }
  4012. }
  4013. o += !h ? ' />' : '>' + h + '</' + tn + '>';
  4014. return o;
  4015. };
  4016. TinyMCE_Engine.prototype.createTag = function(d, tn, a, h) {
  4017. var o = d.createElement(tn);
  4018. if (a) {
  4019. for (n in a) {
  4020. if (typeof(a[n]) != 'function' && a[n] != null)
  4021. tinyMCE.setAttrib(o, n, a[n]);
  4022. }
  4023. }
  4024. if (h)
  4025. o.innerHTML = h;
  4026. return o;
  4027. };
  4028. TinyMCE_Engine.prototype.getElementByAttributeValue = function(n, e, a, v) {
  4029. return (n = this.getElementsByAttributeValue(n, e, a, v)).length == 0 ? null : n[0];
  4030. };
  4031. TinyMCE_Engine.prototype.getElementsByAttributeValue = function(n, e, a, v) {
  4032. var i, nl = n.getElementsByTagName(e), o = new Array();
  4033. for (i=0; i<nl.length; i++) {
  4034. if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1)
  4035. o[o.length] = nl[i];
  4036. }
  4037. return o;
  4038. };
  4039. TinyMCE_Engine.prototype.isBlockElement = function(n) {
  4040. return n != null && n.nodeType == 1 && this.blockRegExp.test(n.nodeName);
  4041. };
  4042. TinyMCE_Engine.prototype.getParentBlockElement = function(n, r) {
  4043. return this.getParentNode(n, function(n) {
  4044. return tinyMCE.isBlockElement(n);
  4045. }, r);
  4046. return null;
  4047. };
  4048. TinyMCE_Engine.prototype.insertAfter = function(n, r){
  4049. if (r.nextSibling)
  4050. r.parentNode.insertBefore(n, r.nextSibling);
  4051. else
  4052. r.parentNode.appendChild(n);
  4053. };
  4054. TinyMCE_Engine.prototype.setInnerHTML = function(e, h) {
  4055. var i, nl, n;
  4056. // Convert all strong/em to b/i in Gecko
  4057. if (tinyMCE.isGecko) {
  4058. h = h.replace(/<embed([^>]*)>/gi, '<tmpembed$1>');
  4059. h = h.replace(/<em([^>]*)>/gi, '<i$1>');
  4060. h = h.replace(/<tmpembed([^>]*)>/gi, '<embed$1>');
  4061. h = h.replace(/<strong([^>]*)>/gi, '<b$1>');
  4062. h = h.replace(/<\/strong>/gi, '</b>');
  4063. h = h.replace(/<\/em>/gi, '</i>');
  4064. }
  4065. if (tinyMCE.isRealIE) {
  4066. // Since MSIE handles invalid HTML better that valid XHTML we
  4067. // need to make some things invalid. <hr /> gets converted to <hr>.
  4068. h = h.replace(/\s\/>/g, '>');
  4069. // Since MSIE auto generated emtpy P tags some times we must tell it to keep the real ones
  4070. h = h.replace(/<p([^>]*)>\u00A0?<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
  4071. h = h.replace(/<p([^>]*)>\s*&nbsp;\s*<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
  4072. h = h.replace(/<p([^>]*)>\s+<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
  4073. // Remove first comment
  4074. e.innerHTML = tinyMCE.uniqueTag + h;
  4075. e.firstChild.removeNode(true);
  4076. // Remove weird auto generated empty paragraphs unless it's supposed to be there
  4077. nl = e.getElementsByTagName("p");
  4078. for (i=nl.length-1; i>=0; i--) {
  4079. n = nl[i];
  4080. if (n.nodeName == 'P' && !n.hasChildNodes() && !n.mce_keep)
  4081. n.parentNode.removeChild(n);
  4082. }
  4083. } else {
  4084. h = this.fixGeckoBaseHREFBug(1, e, h);
  4085. e.innerHTML = h;
  4086. this.fixGeckoBaseHREFBug(2, e, h);
  4087. }
  4088. };
  4089. TinyMCE_Engine.prototype.getOuterHTML = function(e) {
  4090. if (tinyMCE.isIE)
  4091. return e.outerHTML;
  4092. var d = e.ownerDocument.createElement("body");
  4093. d.appendChild(e.cloneNode(true));
  4094. return d.innerHTML;
  4095. };
  4096. TinyMCE_Engine.prototype.setOuterHTML = function(e, h, d) {
  4097. var d = typeof(d) == "undefined" ? e.ownerDocument : d, i, nl, t;
  4098. if (tinyMCE.isIE && e.nodeType == 1)
  4099. e.outerHTML = h;
  4100. else {
  4101. t = d.createElement("body");
  4102. t.innerHTML = h;
  4103. for (i=0, nl=t.childNodes; i<nl.length; i++)
  4104. e.parentNode.insertBefore(nl[i].cloneNode(true), e);
  4105. e.parentNode.removeChild(e);
  4106. }
  4107. };
  4108. TinyMCE_Engine.prototype._getElementById = function(id, d) {
  4109. var e, i, j, f;
  4110. if (typeof(d) == "undefined")
  4111. d = document;
  4112. e = d.getElementById(id);
  4113. if (!e) {
  4114. f = d.forms;
  4115. for (i=0; i<f.length; i++) {
  4116. for (j=0; j<f[i].elements.length; j++) {
  4117. if (f[i].elements[j].name == id) {
  4118. e = f[i].elements[j];
  4119. break;
  4120. }
  4121. }
  4122. }
  4123. }
  4124. return e;
  4125. };
  4126. TinyMCE_Engine.prototype.getNodeTree = function(n, na, t, nn) {
  4127. return this.selectNodes(n, function(n) {
  4128. return (!t || n.nodeType == t) && (!nn || n.nodeName == nn);
  4129. }, na ? na : new Array());
  4130. };
  4131. TinyMCE_Engine.prototype.getParentElement = function(n, na, f, r) {
  4132. var re = na ? new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$') : 0, v;
  4133. // Compatiblity with old scripts where f param was a attribute string
  4134. if (f && typeof(f) == 'string')
  4135. return this.getParentElement(n, na, function(no) {return tinyMCE.getAttrib(no, f) != '';});
  4136. return this.getParentNode(n, function(n) {
  4137. return ((n.nodeType == 1 && !re) || (re && re.test(n.nodeName))) && (!f || f(n));
  4138. }, r);
  4139. };
  4140. TinyMCE_Engine.prototype.getParentNode = function(n, f, r) {
  4141. while (n) {
  4142. if (n == r)
  4143. return null;
  4144. if (f(n))
  4145. return n;
  4146. n = n.parentNode;
  4147. }
  4148. return null;
  4149. };
  4150. TinyMCE_Engine.prototype.getAttrib = function(elm, name, dv) {
  4151. var v;
  4152. if (typeof(dv) == "undefined")
  4153. dv = "";
  4154. // Not a element
  4155. if (!elm || elm.nodeType != 1)
  4156. return dv;
  4157. try {
  4158. v = elm.getAttribute(name, 0);
  4159. } catch (ex) {
  4160. // IE 7 may cast exception on invalid attributes
  4161. v = elm.getAttribute(name, 2);
  4162. }
  4163. // Try className for class attrib
  4164. if (name == "class" && !v)
  4165. v = elm.className;
  4166. // Workaround for a issue with Firefox 1.5rc2+
  4167. if (tinyMCE.isGecko && name == "src" && elm.src != null && elm.src != "")
  4168. v = elm.src;
  4169. // Workaround for a issue with Firefox 1.5rc2+
  4170. if (tinyMCE.isGecko && name == "href" && elm.href != null && elm.href != "")
  4171. v = elm.href;
  4172. if (name == "http-equiv" && tinyMCE.isIE)
  4173. v = elm.httpEquiv;
  4174. if (name == "style" && !tinyMCE.isOpera)
  4175. v = elm.style.cssText;
  4176. return (v && v != "") ? v : dv;
  4177. };
  4178. TinyMCE_Engine.prototype.setAttrib = function(el, name, va, fix) {
  4179. if (typeof(va) == "number" && va != null)
  4180. va = "" + va;
  4181. if (fix) {
  4182. if (va == null)
  4183. va = "";
  4184. va = va.replace(/[^0-9%]/g, '');
  4185. }
  4186. if (name == "style")
  4187. el.style.cssText = va;
  4188. if (name == "class")
  4189. el.className = va;
  4190. if (va != null && va != "" && va != -1)
  4191. el.setAttribute(name, va);
  4192. else
  4193. el.removeAttribute(name);
  4194. };
  4195. TinyMCE_Engine.prototype.setStyleAttrib = function(e, n, v) {
  4196. e.style[n] = v;
  4197. // Style attrib deleted in IE
  4198. if (tinyMCE.isIE && v == null || v == '') {
  4199. v = tinyMCE.serializeStyle(tinyMCE.parseStyle(e.style.cssText));
  4200. e.style.cssText = v;
  4201. e.setAttribute("style", v);
  4202. }
  4203. };
  4204. TinyMCE_Engine.prototype.switchClass = function(ei, c) {
  4205. var e;
  4206. if (tinyMCE.switchClassCache[ei])
  4207. e = tinyMCE.switchClassCache[ei];
  4208. else
  4209. e = tinyMCE.switchClassCache[ei] = document.getElementById(ei);
  4210. if (e) {
  4211. // Keep tile mode
  4212. if (tinyMCE.settings.button_tile_map && e.className && e.className.indexOf('mceTiledButton') == 0)
  4213. c = 'mceTiledButton ' + c;
  4214. e.className = c;
  4215. }
  4216. };
  4217. TinyMCE_Engine.prototype.getAbsPosition = function(n, cn) {
  4218. var l = 0, t = 0;
  4219. while (n && n != cn) {
  4220. l += n.offsetLeft;
  4221. t += n.offsetTop;
  4222. n = n.offsetParent;
  4223. }
  4224. return {absLeft : l, absTop : t};
  4225. };
  4226. TinyMCE_Engine.prototype.prevNode = function(e, n) {
  4227. var a = n.split(','), i;
  4228. while ((e = e.previousSibling) != null) {
  4229. for (i=0; i<a.length; i++) {
  4230. if (e.nodeName == a[i])
  4231. return e;
  4232. }
  4233. }
  4234. return null;
  4235. };
  4236. TinyMCE_Engine.prototype.nextNode = function(e, n) {
  4237. var a = n.split(','), i;
  4238. while ((e = e.nextSibling) != null) {
  4239. for (i=0; i<a.length; i++) {
  4240. if (e.nodeName == a[i])
  4241. return e;
  4242. }
  4243. }
  4244. return null;
  4245. };
  4246. TinyMCE_Engine.prototype.selectElements = function(n, na, f) {
  4247. var i, a = [], nl, x;
  4248. for (x=0, na = na.split(','); x<na.length; x++)
  4249. for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++)
  4250. (!f || f(nl[i])) && a.push(nl[i]);
  4251. return a;
  4252. };
  4253. TinyMCE_Engine.prototype.selectNodes = function(n, f, a) {
  4254. var i;
  4255. if (!a)
  4256. a = new Array();
  4257. if (f(n))
  4258. a[a.length] = n;
  4259. if (n.hasChildNodes()) {
  4260. for (i=0; i<n.childNodes.length; i++)
  4261. tinyMCE.selectNodes(n.childNodes[i], f, a);
  4262. }
  4263. return a;
  4264. };
  4265. TinyMCE_Engine.prototype.addCSSClass = function(e, c, b) {
  4266. var o = this.removeCSSClass(e, c);
  4267. return e.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c;
  4268. };
  4269. TinyMCE_Engine.prototype.removeCSSClass = function(e, c) {
  4270. c = e.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' ');
  4271. return e.className = c != ' ' ? c : '';
  4272. };
  4273. TinyMCE_Engine.prototype.hasCSSClass = function(n, c) {
  4274. return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
  4275. };
  4276. TinyMCE_Engine.prototype.renameElement = function(e, n, d) {
  4277. var ne, i, ar;
  4278. d = typeof(d) == "undefined" ? tinyMCE.selectedInstance.getDoc() : d;
  4279. if (e) {
  4280. ne = d.createElement(n);
  4281. ar = e.attributes;
  4282. for (i=ar.length-1; i>-1; i--) {
  4283. if (ar[i].specified && ar[i].nodeValue)
  4284. ne.setAttribute(ar[i].nodeName.toLowerCase(), ar[i].nodeValue);
  4285. }
  4286. ar = e.childNodes;
  4287. for (i=0; i<ar.length; i++)
  4288. ne.appendChild(ar[i].cloneNode(true));
  4289. e.parentNode.replaceChild(ne, e);
  4290. }
  4291. };
  4292. TinyMCE_Engine.prototype.getViewPort = function(w) {
  4293. var d = w.document, m = d.compatMode == 'CSS1Compat', b = d.body, de = d.documentElement;
  4294. return {
  4295. left : w.pageXOffset || (m ? de.scrollLeft : b.scrollLeft),
  4296. top : w.pageYOffset || (m ? de.scrollTop : b.scrollTop),
  4297. width : w.innerWidth || (m ? de.clientWidth : b.clientWidth),
  4298. height : w.innerHeight || (m ? de.clientHeight : b.clientHeight)
  4299. };
  4300. };
  4301. TinyMCE_Engine.prototype.getStyle = function(n, na, d) {
  4302. if (!n)
  4303. return false;
  4304. // Gecko
  4305. if (tinyMCE.isGecko && n.ownerDocument.defaultView) {
  4306. try {
  4307. return n.ownerDocument.defaultView.getComputedStyle(n, null).getPropertyValue(na);
  4308. } catch (n) {
  4309. // Old safari might fail
  4310. return null;
  4311. }
  4312. }
  4313. // Camelcase it, if needed
  4314. na = na.replace(/-(\D)/g, function(a, b){
  4315. return b.toUpperCase();
  4316. });
  4317. // IE & Opera
  4318. if (n.currentStyle)
  4319. return n.currentStyle[na];
  4320. return false;
  4321. };
  4322. /* file:jscripts/tiny_mce/classes/TinyMCE_URL.class.js */
  4323. TinyMCE_Engine.prototype.parseURL = function(url_str) {
  4324. var urlParts = new Array();
  4325. if (url_str) {
  4326. var pos, lastPos;
  4327. // Parse protocol part
  4328. pos = url_str.indexOf('://');
  4329. if (pos != -1) {
  4330. urlParts['protocol'] = url_str.substring(0, pos);
  4331. lastPos = pos + 3;
  4332. }
  4333. // Find port or path start
  4334. for (var i=lastPos; i<url_str.length; i++) {
  4335. var chr = url_str.charAt(i);
  4336. if (chr == ':')
  4337. break;
  4338. if (chr == '/')
  4339. break;
  4340. }
  4341. pos = i;
  4342. // Get host
  4343. urlParts['host'] = url_str.substring(lastPos, pos);
  4344. // Get port
  4345. urlParts['port'] = "";
  4346. lastPos = pos;
  4347. if (url_str.charAt(pos) == ':') {
  4348. pos = url_str.indexOf('/', lastPos);
  4349. urlParts['port'] = url_str.substring(lastPos+1, pos);
  4350. }
  4351. // Get path
  4352. lastPos = pos;
  4353. pos = url_str.indexOf('?', lastPos);
  4354. if (pos == -1)
  4355. pos = url_str.indexOf('#', lastPos);
  4356. if (pos == -1)
  4357. pos = url_str.length;
  4358. urlParts['path'] = url_str.substring(lastPos, pos);
  4359. // Get query
  4360. lastPos = pos;
  4361. if (url_str.charAt(pos) == '?') {
  4362. pos = url_str.indexOf('#');
  4363. pos = (pos == -1) ? url_str.length : pos;
  4364. urlParts['query'] = url_str.substring(lastPos+1, pos);
  4365. }
  4366. // Get anchor
  4367. lastPos = pos;
  4368. if (url_str.charAt(pos) == '#') {
  4369. pos = url_str.length;
  4370. urlParts['anchor'] = url_str.substring(lastPos+1, pos);
  4371. }
  4372. }
  4373. return urlParts;
  4374. };
  4375. TinyMCE_Engine.prototype.serializeURL = function(up) {
  4376. var o = "";
  4377. if (up['protocol'])
  4378. o += up['protocol'] + "://";
  4379. if (up['host'])
  4380. o += up['host'];
  4381. if (up['port'])
  4382. o += ":" + up['port'];
  4383. if (up['path'])
  4384. o += up['path'];
  4385. if (up['query'])
  4386. o += "?" + up['query'];
  4387. if (up['anchor'])
  4388. o += "#" + up['anchor'];
  4389. return o;
  4390. };
  4391. TinyMCE_Engine.prototype.convertAbsoluteURLToRelativeURL = function(base_url, url_to_relative) {
  4392. var baseURL = this.parseURL(base_url);
  4393. var targetURL = this.parseURL(url_to_relative);
  4394. var strTok1;
  4395. var strTok2;
  4396. var breakPoint = 0;
  4397. var outPath = "";
  4398. var forceSlash = false;
  4399. if (targetURL.path == "")
  4400. targetURL.path = "/";
  4401. else
  4402. forceSlash = true;
  4403. // Crop away last path part
  4404. base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/'));
  4405. strTok1 = base_url.split('/');
  4406. strTok2 = targetURL.path.split('/');
  4407. if (strTok1.length >= strTok2.length) {
  4408. for (var i=0; i<strTok1.length; i++) {
  4409. if (i >= strTok2.length || strTok1[i] != strTok2[i]) {
  4410. breakPoint = i + 1;
  4411. break;
  4412. }
  4413. }
  4414. }
  4415. if (strTok1.length < strTok2.length) {
  4416. for (var i=0; i<strTok2.length; i++) {
  4417. if (i >= strTok1.length || strTok1[i] != strTok2[i]) {
  4418. breakPoint = i + 1;
  4419. break;
  4420. }
  4421. }
  4422. }
  4423. if (breakPoint == 1)
  4424. return targetURL.path;
  4425. for (var i=0; i<(strTok1.length-(breakPoint-1)); i++)
  4426. outPath += "../";
  4427. for (var i=breakPoint-1; i<strTok2.length; i++) {
  4428. if (i != (breakPoint-1))
  4429. outPath += "/" + strTok2[i];
  4430. else
  4431. outPath += strTok2[i];
  4432. }
  4433. targetURL.protocol = null;
  4434. targetURL.host = null;
  4435. targetURL.port = null;
  4436. targetURL.path = outPath == "" && forceSlash ? "/" : outPath;
  4437. // Remove document prefix from local anchors
  4438. var fileName = baseURL.path;
  4439. var pos;
  4440. if ((pos = fileName.lastIndexOf('/')) != -1)
  4441. fileName = fileName.substring(pos + 1);
  4442. // Is local anchor
  4443. if (fileName == targetURL.path && targetURL.anchor != "")
  4444. targetURL.path = "";
  4445. // If empty and not local anchor force filename or slash
  4446. if (targetURL.path == "" && !targetURL.anchor)
  4447. targetURL.path = fileName != "" ? fileName : "/";
  4448. return this.serializeURL(targetURL);
  4449. };
  4450. TinyMCE_Engine.prototype.convertRelativeToAbsoluteURL = function(base_url, relative_url) {
  4451. var baseURL = this.parseURL(base_url), baseURLParts, relURLParts;
  4452. var relURL = this.parseURL(relative_url);
  4453. if (relative_url == "" || relative_url.indexOf('://') != -1 || /^(mailto:|javascript:|#|\/)/.test(relative_url))
  4454. return relative_url;
  4455. // Split parts
  4456. baseURLParts = baseURL['path'].split('/');
  4457. relURLParts = relURL['path'].split('/');
  4458. // Remove empty chunks
  4459. var newBaseURLParts = new Array();
  4460. for (var i=baseURLParts.length-1; i>=0; i--) {
  4461. if (baseURLParts[i].length == 0)
  4462. continue;
  4463. newBaseURLParts[newBaseURLParts.length] = baseURLParts[i];
  4464. }
  4465. baseURLParts = newBaseURLParts.reverse();
  4466. // Merge relURLParts chunks
  4467. var newRelURLParts = new Array();
  4468. var numBack = 0;
  4469. for (var i=relURLParts.length-1; i>=0; i--) {
  4470. if (relURLParts[i].length == 0 || relURLParts[i] == ".")
  4471. continue;
  4472. if (relURLParts[i] == '..') {
  4473. numBack++;
  4474. continue;
  4475. }
  4476. if (numBack > 0) {
  4477. numBack--;
  4478. continue;
  4479. }
  4480. newRelURLParts[newRelURLParts.length] = relURLParts[i];
  4481. }
  4482. relURLParts = newRelURLParts.reverse();
  4483. // Remove end from absolute path
  4484. var len = baseURLParts.length-numBack;
  4485. var absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/');
  4486. var start = "", end = "";
  4487. // Build output URL
  4488. relURL.protocol = baseURL.protocol;
  4489. relURL.host = baseURL.host;
  4490. relURL.port = baseURL.port;
  4491. // Re-add trailing slash if it's removed
  4492. if (relURL.path.charAt(relURL.path.length-1) == "/")
  4493. absPath += "/";
  4494. relURL.path = absPath;
  4495. return this.serializeURL(relURL);
  4496. };
  4497. TinyMCE_Engine.prototype.convertURL = function(url, node, on_save) {
  4498. var prot = document.location.protocol;
  4499. var host = document.location.hostname;
  4500. var port = document.location.port;
  4501. // Pass through file protocol
  4502. if (prot == "file:")
  4503. return url;
  4504. // Something is wrong, remove weirdness
  4505. url = tinyMCE.regexpReplace(url, '(http|https):///', '/');
  4506. // Mailto link or anchor (Pass through)
  4507. if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || tinyMCE.regexpReplace(url,'[ \t\r\n\+]|%20','').charAt(0) == "#")
  4508. return url;
  4509. // Fix relative/Mozilla
  4510. if (!tinyMCE.isIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/')
  4511. return tinyMCE.settings['base_href'] + url;
  4512. // Handle relative URLs
  4513. if (on_save && tinyMCE.getParam('relative_urls')) {
  4514. var curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url);
  4515. if (curl.charAt(0) == '/')
  4516. curl = tinyMCE.settings['document_base_prefix'] + curl;
  4517. var urlParts = tinyMCE.parseURL(curl);
  4518. var tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings['document_base_url']);
  4519. // Force relative
  4520. if (urlParts['host'] == tmpUrlParts['host'] && (urlParts['port'] == tmpUrlParts['port']))
  4521. return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings['document_base_url'], curl);
  4522. }
  4523. // Handle absolute URLs
  4524. if (!tinyMCE.getParam('relative_urls')) {
  4525. var urlParts = tinyMCE.parseURL(url);
  4526. var baseUrlParts = tinyMCE.parseURL(tinyMCE.settings['base_href']);
  4527. // Force absolute URLs from relative URLs
  4528. url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url);
  4529. // If anchor and path is the same page
  4530. if (urlParts['anchor'] && urlParts['path'] == baseUrlParts['path'])
  4531. return "#" + urlParts['anchor'];
  4532. }
  4533. // Remove current domain
  4534. if (tinyMCE.getParam('remove_script_host')) {
  4535. var start = "", portPart = "";
  4536. if (port != "")
  4537. portPart = ":" + port;
  4538. start = prot + "//" + host + portPart + "/";
  4539. if (url.indexOf(start) == 0)
  4540. url = url.substring(start.length-1);
  4541. }
  4542. return url;
  4543. };
  4544. TinyMCE_Engine.prototype.convertAllRelativeURLs = function(body) {
  4545. var i, elms, src, href, mhref, msrc;
  4546. // Convert all image URL:s to absolute URL
  4547. elms = body.getElementsByTagName("img");
  4548. for (i=0; i<elms.length; i++) {
  4549. src = tinyMCE.getAttrib(elms[i], 'src');
  4550. msrc = tinyMCE.getAttrib(elms[i], 'mce_src');
  4551. if (msrc != "")
  4552. src = msrc;
  4553. if (src != "") {
  4554. src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src);
  4555. elms[i].setAttribute("src", src);
  4556. }
  4557. }
  4558. // Convert all link URL:s to absolute URL
  4559. elms = body.getElementsByTagName("a");
  4560. for (i=0; i<elms.length; i++) {
  4561. href = tinyMCE.getAttrib(elms[i], 'href');
  4562. mhref = tinyMCE.getAttrib(elms[i], 'mce_href');
  4563. if (mhref != "")
  4564. href = mhref;
  4565. if (href && href != "") {
  4566. href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], href);
  4567. elms[i].setAttribute("href", href);
  4568. }
  4569. }
  4570. };
  4571. /* file:jscripts/tiny_mce/classes/TinyMCE_Array.class.js */
  4572. TinyMCE_Engine.prototype.clearArray = function(a) {
  4573. var n;
  4574. for (n in a)
  4575. a[n] = null;
  4576. return a;
  4577. };
  4578. TinyMCE_Engine.prototype.explode = function(d, s) {
  4579. var ar = s.split(d), oar = new Array(), i;
  4580. for (i = 0; i<ar.length; i++) {
  4581. if (ar[i] != "")
  4582. oar[oar.length] = ar[i];
  4583. }
  4584. return oar;
  4585. };
  4586. /* file:jscripts/tiny_mce/classes/TinyMCE_Event.class.js */
  4587. TinyMCE_Engine.prototype._setEventsEnabled = function(node, state) {
  4588. var evs, x, y, elms, i, event;
  4589. var events = ['onfocus','onblur','onclick','ondblclick',
  4590. 'onmousedown','onmouseup','onmouseover','onmousemove',
  4591. 'onmouseout','onkeypress','onkeydown','onkeydown','onkeyup'];
  4592. evs = tinyMCE.settings['event_elements'].split(',');
  4593. for (y=0; y<evs.length; y++){
  4594. elms = node.getElementsByTagName(evs[y]);
  4595. for (i=0; i<elms.length; i++) {
  4596. event = "";
  4597. for (x=0; x<events.length; x++) {
  4598. if ((event = tinyMCE.getAttrib(elms[i], events[x])) != '') {
  4599. event = tinyMCE.cleanupEventStr("" + event);
  4600. if (!state)
  4601. event = "return true;" + event;
  4602. else
  4603. event = event.replace(/^return true;/gi, '');
  4604. elms[i].removeAttribute(events[x]);
  4605. elms[i].setAttribute(events[x], event);
  4606. }
  4607. }
  4608. }
  4609. }
  4610. };
  4611. TinyMCE_Engine.prototype._eventPatch = function(editor_id) {
  4612. var n, inst, win, e;
  4613. // Remove odd, error
  4614. if (typeof(tinyMCE) == "undefined")
  4615. return true;
  4616. try {
  4617. // Try selected instance first
  4618. if (tinyMCE.selectedInstance) {
  4619. win = tinyMCE.selectedInstance.getWin();
  4620. if (win && win.event) {
  4621. e = win.event;
  4622. if (!e.target)
  4623. e.target = e.srcElement;
  4624. TinyMCE_Engine.prototype.handleEvent(e);
  4625. return;
  4626. }
  4627. }
  4628. // Search for it
  4629. for (n in tinyMCE.instances) {
  4630. inst = tinyMCE.instances[n];
  4631. if (!tinyMCE.isInstance(inst))
  4632. continue;
  4633. inst.select();
  4634. win = inst.getWin();
  4635. if (win && win.event) {
  4636. e = win.event;
  4637. if (!e.target)
  4638. e.target = e.srcElement;
  4639. TinyMCE_Engine.prototype.handleEvent(e);
  4640. return;
  4641. }
  4642. }
  4643. } catch (ex) {
  4644. // Ignore error if iframe is pointing to external URL
  4645. }
  4646. };
  4647. TinyMCE_Engine.prototype.findEvent = function(e) {
  4648. var n, inst;
  4649. if (e)
  4650. return e;
  4651. for (n in tinyMCE.instances) {
  4652. inst = tinyMCE.instances[n];
  4653. if (tinyMCE.isInstance(inst) && inst.getWin().event)
  4654. return inst.getWin().event;
  4655. }
  4656. return null;
  4657. };
  4658. TinyMCE_Engine.prototype.unloadHandler = function() {
  4659. tinyMCE.triggerSave(true, true);
  4660. };
  4661. TinyMCE_Engine.prototype.addEventHandlers = function(inst) {
  4662. this.setEventHandlers(inst, 1);
  4663. };
  4664. TinyMCE_Engine.prototype.setEventHandlers = function(inst, s) {
  4665. var doc = inst.getDoc(), ie, ot, i, f = s ? tinyMCE.addEvent : tinyMCE.removeEvent;
  4666. ie = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'controlselect', 'dblclick'];
  4667. ot = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'focus', 'blur', 'dragdrop'];
  4668. inst.switchSettings();
  4669. if (tinyMCE.isIE) {
  4670. for (i=0; i<ie.length; i++)
  4671. f(doc, ie[i], TinyMCE_Engine.prototype._eventPatch);
  4672. } else {
  4673. for (i=0; i<ot.length; i++)
  4674. f(doc, ot[i], tinyMCE.handleEvent);
  4675. // Force designmode
  4676. try {
  4677. doc.designMode = "On";
  4678. } catch (e) {
  4679. // Ignore
  4680. }
  4681. }
  4682. };
  4683. TinyMCE_Engine.prototype.onMouseMove = function() {
  4684. var inst, lh;
  4685. // Fix for IE7 bug where it's not restoring hover on anchors correctly
  4686. if (tinyMCE.lastHover) {
  4687. lh = tinyMCE.lastHover;
  4688. // Call out on menus and refresh class on normal buttons
  4689. if (lh.className.indexOf('mceMenu') != -1)
  4690. tinyMCE._menuButtonEvent('out', lh);
  4691. else
  4692. lh.className = lh.className;
  4693. tinyMCE.lastHover = null;
  4694. }
  4695. if (!tinyMCE.hasMouseMoved) {
  4696. inst = tinyMCE.selectedInstance;
  4697. // Workaround for bug #1437457 (Odd MSIE bug)
  4698. if (inst.isFocused) {
  4699. inst.undoBookmark = inst.selection.getBookmark();
  4700. tinyMCE.hasMouseMoved = true;
  4701. }
  4702. }
  4703. // tinyMCE.cancelEvent(inst.getWin().event);
  4704. // return false;
  4705. };
  4706. TinyMCE_Engine.prototype.cancelEvent = function(e) {
  4707. if (!e)
  4708. return false;
  4709. if (tinyMCE.isIE) {
  4710. e.returnValue = false;
  4711. e.cancelBubble = true;
  4712. } else {
  4713. e.preventDefault();
  4714. e.stopPropagation && e.stopPropagation();
  4715. }
  4716. return false;
  4717. };
  4718. TinyMCE_Engine.prototype.addEvent = function(o, n, h) {
  4719. // Add cleanup for all non unload events
  4720. if (n != 'unload') {
  4721. function clean() {
  4722. var ex;
  4723. try {
  4724. tinyMCE.removeEvent(o, n, h);
  4725. tinyMCE.removeEvent(window, 'unload', clean);
  4726. o = n = h = null;
  4727. } catch (ex) {
  4728. // IE may produce access denied exception on unload
  4729. }
  4730. }
  4731. // Add memory cleaner
  4732. tinyMCE.addEvent(window, 'unload', clean);
  4733. }
  4734. if (o.attachEvent)
  4735. o.attachEvent("on" + n, h);
  4736. else
  4737. o.addEventListener(n, h, false);
  4738. };
  4739. TinyMCE_Engine.prototype.removeEvent = function(o, n, h) {
  4740. if (o.detachEvent)
  4741. o.detachEvent("on" + n, h);
  4742. else
  4743. o.removeEventListener(n, h, false);
  4744. };
  4745. TinyMCE_Engine.prototype.addSelectAccessibility = function(e, s, w) {
  4746. // Add event handlers
  4747. if (!s._isAccessible) {
  4748. s.onkeydown = tinyMCE.accessibleEventHandler;
  4749. s.onblur = tinyMCE.accessibleEventHandler;
  4750. s._isAccessible = true;
  4751. s._win = w;
  4752. }
  4753. return false;
  4754. };
  4755. TinyMCE_Engine.prototype.accessibleEventHandler = function(e) {
  4756. var win = this._win;
  4757. e = tinyMCE.isIE ? win.event : e;
  4758. var elm = tinyMCE.isIE ? e.srcElement : e.target;
  4759. // Unpiggyback onchange on blur
  4760. if (e.type == "blur") {
  4761. if (elm.oldonchange) {
  4762. elm.onchange = elm.oldonchange;
  4763. elm.oldonchange = null;
  4764. }
  4765. return true;
  4766. }
  4767. // Piggyback onchange
  4768. if (elm.nodeName == "SELECT" && !elm.oldonchange) {
  4769. elm.oldonchange = elm.onchange;
  4770. elm.onchange = null;
  4771. }
  4772. // Execute onchange and remove piggyback
  4773. if (e.keyCode == 13 || e.keyCode == 32) {
  4774. elm.onchange = elm.oldonchange;
  4775. elm.onchange();
  4776. elm.oldonchange = null;
  4777. tinyMCE.cancelEvent(e);
  4778. return false;
  4779. }
  4780. return true;
  4781. };
  4782. TinyMCE_Engine.prototype._resetIframeHeight = function() {
  4783. var ife;
  4784. if (tinyMCE.isRealIE) {
  4785. ife = tinyMCE.selectedInstance.iframeElement;
  4786. /* if (ife._oldWidth) {
  4787. ife.style.width = ife._oldWidth;
  4788. ife.width = ife._oldWidth;
  4789. }*/
  4790. if (ife._oldHeight) {
  4791. ife.style.height = ife._oldHeight;
  4792. ife.height = ife._oldHeight;
  4793. }
  4794. }
  4795. };
  4796. /* file:jscripts/tiny_mce/classes/TinyMCE_Selection.class.js */
  4797. function TinyMCE_Selection(inst) {
  4798. this.instance = inst;
  4799. };
  4800. TinyMCE_Selection.prototype = {
  4801. getSelectedHTML : function() {
  4802. var inst = this.instance;
  4803. var e, r = this.getRng(), h;
  4804. if (!r)
  4805. return null;
  4806. e = document.createElement("body");
  4807. if (r.cloneContents)
  4808. e.appendChild(r.cloneContents());
  4809. else if (typeof(r.item) != 'undefined' || typeof(r.htmlText) != 'undefined')
  4810. e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
  4811. else
  4812. e.innerHTML = r.toString(); // Failed, use text for now
  4813. h = tinyMCE._cleanupHTML(inst, inst.contentDocument, inst.settings, e, e, false, true, false);
  4814. // When editing always use fonts internaly
  4815. //if (tinyMCE.getParam("convert_fonts_to_spans"))
  4816. // tinyMCE.convertSpansToFonts(inst.getDoc());
  4817. return h;
  4818. },
  4819. getSelectedText : function() {
  4820. var inst = this.instance;
  4821. var d, r, s, t;
  4822. if (tinyMCE.isIE) {
  4823. d = inst.getDoc();
  4824. if (d.selection.type == "Text") {
  4825. r = d.selection.createRange();
  4826. t = r.text;
  4827. } else
  4828. t = '';
  4829. } else {
  4830. s = this.getSel();
  4831. if (s && s.toString)
  4832. t = s.toString();
  4833. else
  4834. t = '';
  4835. }
  4836. return t;
  4837. },
  4838. getBookmark : function(simple) {
  4839. var inst = this.instance;
  4840. var rng = this.getRng();
  4841. var doc = inst.getDoc(), b = inst.getBody();
  4842. var sp, le, s, e, nl, i, si, ei, w;
  4843. var trng, sx, sy, xx = -999999999, vp = inst.getViewPort();
  4844. sx = vp.left;
  4845. sy = vp.top;
  4846. if (tinyMCE.isSafari || tinyMCE.isOpera || simple)
  4847. return {rng : rng, scrollX : sx, scrollY : sy};
  4848. if (tinyMCE.isIE) {
  4849. if (rng.item) {
  4850. e = rng.item(0);
  4851. nl = b.getElementsByTagName(e.nodeName);
  4852. for (i=0; i<nl.length; i++) {
  4853. if (e == nl[i]) {
  4854. sp = i;
  4855. break;
  4856. }
  4857. }
  4858. return {
  4859. tag : e.nodeName,
  4860. index : sp,
  4861. scrollX : sx,
  4862. scrollY : sy
  4863. };
  4864. } else {
  4865. trng = doc.body.createTextRange();
  4866. trng.moveToElementText(inst.getBody());
  4867. trng.collapse(true);
  4868. bp = Math.abs(trng.move('character', xx));
  4869. trng = rng.duplicate();
  4870. trng.collapse(true);
  4871. sp = Math.abs(trng.move('character', xx));
  4872. trng = rng.duplicate();
  4873. trng.collapse(false);
  4874. le = Math.abs(trng.move('character', xx)) - sp;
  4875. return {
  4876. start : sp - bp,
  4877. length : le,
  4878. scrollX : sx,
  4879. scrollY : sy
  4880. };
  4881. }
  4882. }
  4883. if (tinyMCE.isGecko) {
  4884. s = this.getSel();
  4885. e = this.getFocusElement();
  4886. if (!s)
  4887. return null;
  4888. if (e && e.nodeName == 'IMG') {
  4889. /*nl = b.getElementsByTagName('IMG');
  4890. for (i=0; i<nl.length; i++) {
  4891. if (e == nl[i]) {
  4892. sp = i;
  4893. break;
  4894. }
  4895. }*/
  4896. return {
  4897. start : -1,
  4898. end : -1,
  4899. index : sp,
  4900. scrollX : sx,
  4901. scrollY : sy
  4902. };
  4903. }
  4904. // Caret or selection
  4905. if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {
  4906. e = this._getPosText(b, s.anchorNode, s.focusNode);
  4907. if (!e)
  4908. return {scrollX : sx, scrollY : sy};
  4909. return {
  4910. start : e.start + s.anchorOffset,
  4911. end : e.end + s.focusOffset,
  4912. scrollX : sx,
  4913. scrollY : sy
  4914. };
  4915. } else {
  4916. e = this._getPosText(b, rng.startContainer, rng.endContainer);
  4917. if (!e)
  4918. return {scrollX : sx, scrollY : sy};
  4919. return {
  4920. start : e.start + rng.startOffset,
  4921. end : e.end + rng.endOffset,
  4922. scrollX : sx,
  4923. scrollY : sy
  4924. };
  4925. }
  4926. }
  4927. return null;
  4928. },
  4929. moveToBookmark : function(bookmark) {
  4930. var inst = this.instance;
  4931. var rng, nl, i, ex, b = inst.getBody(), sd;
  4932. var doc = inst.getDoc();
  4933. var win = inst.getWin();
  4934. var sel = this.getSel();
  4935. if (!bookmark)
  4936. return false;
  4937. if (tinyMCE.isSafari) {
  4938. sel.setBaseAndExtent(bookmark.rng.startContainer, bookmark.rng.startOffset, bookmark.rng.endContainer, bookmark.rng.endOffset);
  4939. return true;
  4940. }
  4941. if (tinyMCE.isRealIE) {
  4942. if (bookmark.rng) {
  4943. try {
  4944. bookmark.rng.select();
  4945. } catch (ex) {
  4946. // Ignore
  4947. }
  4948. return true;
  4949. }
  4950. win.focus();
  4951. if (bookmark.tag) {
  4952. rng = b.createControlRange();
  4953. nl = b.getElementsByTagName(bookmark.tag);
  4954. if (nl.length > bookmark.index) {
  4955. try {
  4956. rng.addElement(nl[bookmark.index]);
  4957. } catch (ex) {
  4958. // Might be thrown if the node no longer exists
  4959. }
  4960. }
  4961. } else {
  4962. // Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs
  4963. try {
  4964. // Incorrect bookmark
  4965. if (bookmark.start < 0)
  4966. return true;
  4967. rng = inst.getSel().createRange();
  4968. rng.moveToElementText(inst.getBody());
  4969. rng.collapse(true);
  4970. rng.moveStart('character', bookmark.start);
  4971. rng.moveEnd('character', bookmark.length);
  4972. } catch (ex) {
  4973. return true;
  4974. }
  4975. }
  4976. rng.select();
  4977. win.scrollTo(bookmark.scrollX, bookmark.scrollY);
  4978. return true;
  4979. }
  4980. if (tinyMCE.isGecko || tinyMCE.isOpera) {
  4981. if (!sel)
  4982. return false;
  4983. if (bookmark.rng) {
  4984. sel.removeAllRanges();
  4985. sel.addRange(bookmark.rng);
  4986. }
  4987. if (bookmark.start != -1 && bookmark.end != -1) {
  4988. try {
  4989. sd = this._getTextPos(b, bookmark.start, bookmark.end);
  4990. rng = doc.createRange();
  4991. rng.setStart(sd.startNode, sd.startOffset);
  4992. rng.setEnd(sd.endNode, sd.endOffset);
  4993. sel.removeAllRanges();
  4994. sel.addRange(rng);
  4995. win.focus();
  4996. } catch (ex) {
  4997. // Ignore
  4998. }
  4999. }
  5000. /*
  5001. if (typeof(bookmark.index) != 'undefined') {
  5002. tinyMCE.selectElements(b, 'IMG', function (n) {
  5003. if (bookmark.index-- == 0) {
  5004. // Select image in Gecko here
  5005. }
  5006. return false;
  5007. });
  5008. }
  5009. */
  5010. win.scrollTo(bookmark.scrollX, bookmark.scrollY);
  5011. return true;
  5012. }
  5013. return false;
  5014. },
  5015. _getPosText : function(r, sn, en) {
  5016. var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
  5017. while ((n = w.nextNode()) != null) {
  5018. if (n == sn)
  5019. d.start = p;
  5020. if (n == en) {
  5021. d.end = p;
  5022. return d;
  5023. }
  5024. p += n.nodeValue ? n.nodeValue.length : 0;
  5025. }
  5026. return null;
  5027. },
  5028. _getTextPos : function(r, sp, ep) {
  5029. var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
  5030. while ((n = w.nextNode()) != null) {
  5031. p += n.nodeValue ? n.nodeValue.length : 0;
  5032. if (p >= sp && !d.startNode) {
  5033. d.startNode = n;
  5034. d.startOffset = sp - (p - n.nodeValue.length);
  5035. }
  5036. if (p >= ep) {
  5037. d.endNode = n;
  5038. d.endOffset = ep - (p - n.nodeValue.length);
  5039. return d;
  5040. }
  5041. }
  5042. return null;
  5043. },
  5044. selectNode : function(node, collapse, select_text_node, to_start) {
  5045. var inst = this.instance, sel, rng, nodes;
  5046. if (!node)
  5047. return;
  5048. if (typeof(collapse) == "undefined")
  5049. collapse = true;
  5050. if (typeof(select_text_node) == "undefined")
  5051. select_text_node = false;
  5052. if (typeof(to_start) == "undefined")
  5053. to_start = true;
  5054. if (inst.settings.auto_resize)
  5055. inst.resizeToContent();
  5056. if (tinyMCE.isRealIE) {
  5057. rng = inst.getDoc().body.createTextRange();
  5058. try {
  5059. rng.moveToElementText(node);
  5060. if (collapse)
  5061. rng.collapse(to_start);
  5062. rng.select();
  5063. } catch (e) {
  5064. // Throws illigal agrument in MSIE some times
  5065. }
  5066. } else {
  5067. sel = this.getSel();
  5068. if (!sel)
  5069. return;
  5070. if (tinyMCE.isSafari) {
  5071. sel.setBaseAndExtent(node, 0, node, node.innerText.length);
  5072. if (collapse) {
  5073. if (to_start)
  5074. sel.collapseToStart();
  5075. else
  5076. sel.collapseToEnd();
  5077. }
  5078. this.scrollToNode(node);
  5079. return;
  5080. }
  5081. rng = inst.getDoc().createRange();
  5082. if (select_text_node) {
  5083. // Find first textnode in tree
  5084. nodes = tinyMCE.getNodeTree(node, new Array(), 3);
  5085. if (nodes.length > 0)
  5086. rng.selectNodeContents(nodes[0]);
  5087. else
  5088. rng.selectNodeContents(node);
  5089. } else
  5090. rng.selectNode(node);
  5091. if (collapse) {
  5092. // Special treatment of textnode collapse
  5093. if (!to_start && node.nodeType == 3) {
  5094. rng.setStart(node, node.nodeValue.length);
  5095. rng.setEnd(node, node.nodeValue.length);
  5096. } else
  5097. rng.collapse(to_start);
  5098. }
  5099. sel.removeAllRanges();
  5100. sel.addRange(rng);
  5101. }
  5102. this.scrollToNode(node);
  5103. // Set selected element
  5104. tinyMCE.selectedElement = null;
  5105. if (node.nodeType == 1)
  5106. tinyMCE.selectedElement = node;
  5107. },
  5108. scrollToNode : function(node) {
  5109. var inst = this.instance, w = inst.getWin(), vp = inst.getViewPort(), pos = tinyMCE.getAbsPosition(node), cvp, p, cwin;
  5110. // Only scroll if out of visible area
  5111. if (pos.absLeft < vp.left || pos.absLeft > vp.left + vp.width || pos.absTop < vp.top || pos.absTop > vp.top + (vp.height-25))
  5112. w.scrollTo(pos.absLeft, pos.absTop - vp.height + 25);
  5113. // Scroll container window
  5114. if (inst.settings.auto_resize) {
  5115. cwin = inst.getContainerWin();
  5116. cvp = tinyMCE.getViewPort(cwin);
  5117. p = this.getAbsPosition(node);
  5118. if (p.absLeft < cvp.left || p.absLeft > cvp.left + cvp.width || p.absTop < cvp.top || p.absTop > cvp.top + cvp.height)
  5119. cwin.scrollTo(p.absLeft, p.absTop - cvp.height + 25);
  5120. }
  5121. },
  5122. getAbsPosition : function(n) {
  5123. var pos = tinyMCE.getAbsPosition(n), ipos = tinyMCE.getAbsPosition(this.instance.iframeElement);
  5124. return {
  5125. absLeft : ipos.absLeft + pos.absLeft,
  5126. absTop : ipos.absTop + pos.absTop
  5127. };
  5128. },
  5129. getSel : function() {
  5130. var inst = this.instance;
  5131. if (tinyMCE.isRealIE)
  5132. return inst.getDoc().selection;
  5133. return inst.contentWindow.getSelection();
  5134. },
  5135. getRng : function() {
  5136. var s = this.getSel();
  5137. if (s == null)
  5138. return null;
  5139. if (tinyMCE.isRealIE)
  5140. return s.createRange();
  5141. if (tinyMCE.isSafari && !s.getRangeAt)
  5142. return '' + window.getSelection();
  5143. if (s.rangeCount > 0)
  5144. return s.getRangeAt(0);
  5145. return null;
  5146. },
  5147. isCollapsed : function() {
  5148. var r = this.getRng();
  5149. if (r.item)
  5150. return false;
  5151. return r.boundingWidth == 0 || this.getSel().isCollapsed;
  5152. },
  5153. collapse : function(b) {
  5154. var r = this.getRng(), s = this.getSel();
  5155. if (r.select) {
  5156. r.collapse(b);
  5157. r.select();
  5158. } else {
  5159. if (b)
  5160. s.collapseToStart();
  5161. else
  5162. s.collapseToEnd();
  5163. }
  5164. },
  5165. getFocusElement : function() {
  5166. var inst = this.instance, doc, rng, sel, elm;
  5167. if (tinyMCE.isRealIE) {
  5168. doc = inst.getDoc();
  5169. rng = doc.selection.createRange();
  5170. // if (rng.collapse)
  5171. // rng.collapse(true);
  5172. elm = rng.item ? rng.item(0) : rng.parentElement();
  5173. } else {
  5174. if (!tinyMCE.isSafari && inst.isHidden())
  5175. return inst.getBody();
  5176. sel = this.getSel();
  5177. rng = this.getRng();
  5178. if (!sel || !rng)
  5179. return null;
  5180. elm = rng.commonAncestorContainer;
  5181. //elm = (sel && sel.anchorNode) ? sel.anchorNode : null;
  5182. // Handle selection a image or other control like element such as anchors
  5183. if (!rng.collapsed) {
  5184. // Is selection small
  5185. if (rng.startContainer == rng.endContainer) {
  5186. if (rng.startOffset - rng.endOffset < 2) {
  5187. if (rng.startContainer.hasChildNodes())
  5188. elm = rng.startContainer.childNodes[rng.startOffset];
  5189. }
  5190. }
  5191. }
  5192. // Get the element parent of the node
  5193. elm = tinyMCE.getParentElement(elm);
  5194. //if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img")
  5195. // elm = tinyMCE.selectedElement;
  5196. }
  5197. return elm;
  5198. }
  5199. };
  5200. /* file:jscripts/tiny_mce/classes/TinyMCE_UndoRedo.class.js */
  5201. function TinyMCE_UndoRedo(inst) {
  5202. this.instance = inst;
  5203. this.undoLevels = new Array();
  5204. this.undoIndex = 0;
  5205. this.typingUndoIndex = -1;
  5206. this.undoRedo = true;
  5207. };
  5208. TinyMCE_UndoRedo.prototype = {
  5209. add : function(l) {
  5210. var b, customUndoLevels, newHTML, inst = this.instance, i, ul, ur;
  5211. if (l) {
  5212. this.undoLevels[this.undoLevels.length] = l;
  5213. return true;
  5214. }
  5215. if (this.typingUndoIndex != -1) {
  5216. this.undoIndex = this.typingUndoIndex;
  5217. if (tinyMCE.typingUndoIndex != -1)
  5218. tinyMCE.undoIndex = tinyMCE.typingUndoIndex;
  5219. }
  5220. newHTML = tinyMCE.trim(inst.getBody().innerHTML);
  5221. if (this.undoLevels[this.undoIndex] && newHTML != this.undoLevels[this.undoIndex].content) {
  5222. //tinyMCE.debug(newHTML, this.undoLevels[this.undoIndex].content);
  5223. tinyMCE.dispatchCallback(inst, 'onchange_callback', 'onChange', inst);
  5224. // Time to compress
  5225. customUndoLevels = tinyMCE.settings['custom_undo_redo_levels'];
  5226. if (customUndoLevels != -1 && this.undoLevels.length > customUndoLevels) {
  5227. for (i=0; i<this.undoLevels.length-1; i++)
  5228. this.undoLevels[i] = this.undoLevels[i+1];
  5229. this.undoLevels.length--;
  5230. this.undoIndex--;
  5231. // Todo: Implement global undo/redo logic here
  5232. }
  5233. b = inst.undoBookmark;
  5234. if (!b)
  5235. b = inst.selection.getBookmark();
  5236. this.undoIndex++;
  5237. this.undoLevels[this.undoIndex] = {
  5238. content : newHTML,
  5239. bookmark : b
  5240. };
  5241. // Remove all above from global undo/redo
  5242. ul = tinyMCE.undoLevels;
  5243. for (i=tinyMCE.undoIndex + 1; i<ul.length; i++) {
  5244. ur = ul[i].undoRedo;
  5245. if (ur.undoIndex == ur.undoLevels.length -1)
  5246. ur.undoIndex--;
  5247. ur.undoLevels.length--;
  5248. }
  5249. // Add global undo level
  5250. tinyMCE.undoLevels[tinyMCE.undoIndex++] = inst;
  5251. tinyMCE.undoLevels.length = tinyMCE.undoIndex;
  5252. this.undoLevels.length = this.undoIndex + 1;
  5253. return true;
  5254. }
  5255. return false;
  5256. },
  5257. undo : function() {
  5258. var inst = this.instance;
  5259. // Do undo
  5260. if (this.undoIndex > 0) {
  5261. this.undoIndex--;
  5262. tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);
  5263. inst.repaint();
  5264. if (inst.settings.custom_undo_redo_restore_selection)
  5265. inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);
  5266. }
  5267. },
  5268. redo : function() {
  5269. var inst = this.instance;
  5270. tinyMCE.execCommand("mceEndTyping");
  5271. if (this.undoIndex < (this.undoLevels.length-1)) {
  5272. this.undoIndex++;
  5273. tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);
  5274. inst.repaint();
  5275. if (inst.settings.custom_undo_redo_restore_selection)
  5276. inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);
  5277. }
  5278. tinyMCE.triggerNodeChange();
  5279. }
  5280. };
  5281. /* file:jscripts/tiny_mce/classes/TinyMCE_ForceParagraphs.class.js */
  5282. var TinyMCE_ForceParagraphs = {
  5283. _insertPara : function(inst, e) {
  5284. var doc = inst.getDoc(), sel = inst.getSel(), body = inst.getBody(), win = inst.contentWindow, rng = sel.getRangeAt(0);
  5285. var rootElm = doc.documentElement, blockName = "P", startNode, endNode, startBlock, endBlock;
  5286. var rngBefore, rngAfter, direct, startNode, startOffset, endNode, endOffset, b = tinyMCE.isOpera ? inst.selection.getBookmark() : null;
  5287. var paraBefore, paraAfter, startChop, endChop, contents;
  5288. function isEmpty(para) {
  5289. function isEmptyHTML(html) {
  5290. return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == "";
  5291. }
  5292. // Check for images
  5293. if (para.getElementsByTagName("img").length > 0)
  5294. return false;
  5295. // Check for tables
  5296. if (para.getElementsByTagName("table").length > 0)
  5297. return false;
  5298. // Check for HRs
  5299. if (para.getElementsByTagName("hr").length > 0)
  5300. return false;
  5301. // Check all textnodes
  5302. var nodes = tinyMCE.getNodeTree(para, new Array(), 3);
  5303. for (var i=0; i<nodes.length; i++) {
  5304. if (!isEmptyHTML(nodes[i].nodeValue))
  5305. return false;
  5306. }
  5307. // No images, no tables, no hrs, no text content then it's empty
  5308. return true;
  5309. }
  5310. // tinyMCE.debug(body.innerHTML);
  5311. // debug(e.target, sel.anchorNode.nodeName, sel.focusNode.nodeName, rng.startContainer, rng.endContainer, rng.commonAncestorContainer, sel.anchorOffset, sel.focusOffset, rng.toString());
  5312. // Setup before range
  5313. rngBefore = doc.createRange();
  5314. rngBefore.setStart(sel.anchorNode, sel.anchorOffset);
  5315. rngBefore.collapse(true);
  5316. // Setup after range
  5317. rngAfter = doc.createRange();
  5318. rngAfter.setStart(sel.focusNode, sel.focusOffset);
  5319. rngAfter.collapse(true);
  5320. // Setup start/end points
  5321. direct = rngBefore.compareBoundaryPoints(rngBefore.START_TO_END, rngAfter) < 0;
  5322. startNode = direct ? sel.anchorNode : sel.focusNode;
  5323. startOffset = direct ? sel.anchorOffset : sel.focusOffset;
  5324. endNode = direct ? sel.focusNode : sel.anchorNode;
  5325. endOffset = direct ? sel.focusOffset : sel.anchorOffset;
  5326. startNode = startNode.nodeName == "BODY" ? startNode.firstChild : startNode;
  5327. endNode = endNode.nodeName == "BODY" ? endNode.firstChild : endNode;
  5328. // Get block elements
  5329. startBlock = inst.getParentBlockElement(startNode);
  5330. endBlock = inst.getParentBlockElement(endNode);
  5331. // If absolute force paragraph generation within
  5332. if (startBlock && new RegExp('absolute|relative|static', 'gi').test(startBlock.style.position))
  5333. startBlock = null;
  5334. if (endBlock && new RegExp('absolute|relative|static', 'gi').test(endBlock.style.position))
  5335. endBlock = null;
  5336. // Use current block name
  5337. if (startBlock != null) {
  5338. blockName = startBlock.nodeName;
  5339. // Use P instead
  5340. if (blockName == "TD" || blockName == "TABLE" || (blockName == "DIV" && new RegExp('left|right', 'gi').test(startBlock.style.cssFloat)))
  5341. blockName = "P";
  5342. }
  5343. // Within a list use normal behaviour
  5344. if (tinyMCE.getParentElement(startBlock, "OL,UL", null, body) != null)
  5345. return false;
  5346. // Within a table create new paragraphs
  5347. if ((startBlock != null && startBlock.nodeName == "TABLE") || (endBlock != null && endBlock.nodeName == "TABLE"))
  5348. startBlock = endBlock = null;
  5349. // Setup new paragraphs
  5350. paraBefore = (startBlock != null && startBlock.nodeName == blockName) ? startBlock.cloneNode(false) : doc.createElement(blockName);
  5351. paraAfter = (endBlock != null && endBlock.nodeName == blockName) ? endBlock.cloneNode(false) : doc.createElement(blockName);
  5352. // Is header, then force paragraph under
  5353. if (/^(H[1-6])$/.test(blockName))
  5354. paraAfter = doc.createElement("p");
  5355. // Setup chop nodes
  5356. startChop = startNode;
  5357. endChop = endNode;
  5358. // Get startChop node
  5359. node = startChop;
  5360. do {
  5361. if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))
  5362. break;
  5363. startChop = node;
  5364. } while ((node = node.previousSibling ? node.previousSibling : node.parentNode));
  5365. // Get endChop node
  5366. node = endChop;
  5367. do {
  5368. if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))
  5369. break;
  5370. endChop = node;
  5371. } while ((node = node.nextSibling ? node.nextSibling : node.parentNode));
  5372. // Fix when only a image is within the TD
  5373. if (startChop.nodeName == "TD")
  5374. startChop = startChop.firstChild;
  5375. if (endChop.nodeName == "TD")
  5376. endChop = endChop.lastChild;
  5377. // If not in a block element
  5378. if (startBlock == null) {
  5379. // Delete selection
  5380. rng.deleteContents();
  5381. if (!tinyMCE.isSafari)
  5382. sel.removeAllRanges();
  5383. if (startChop != rootElm && endChop != rootElm) {
  5384. // Insert paragraph before
  5385. rngBefore = rng.cloneRange();
  5386. if (startChop == body)
  5387. rngBefore.setStart(startChop, 0);
  5388. else
  5389. rngBefore.setStartBefore(startChop);
  5390. paraBefore.appendChild(rngBefore.cloneContents());
  5391. // Insert paragraph after
  5392. if (endChop.parentNode.nodeName == blockName)
  5393. endChop = endChop.parentNode;
  5394. // If not after image
  5395. //if (rng.startContainer.nodeName != "BODY" && rng.endContainer.nodeName != "BODY")
  5396. rng.setEndAfter(endChop);
  5397. if (endChop.nodeName != "#text" && endChop.nodeName != "BODY")
  5398. rngBefore.setEndAfter(endChop);
  5399. contents = rng.cloneContents();
  5400. if (contents.firstChild && (contents.firstChild.nodeName == blockName || contents.firstChild.nodeName == "BODY"))
  5401. paraAfter.innerHTML = contents.firstChild.innerHTML;
  5402. else
  5403. paraAfter.appendChild(contents);
  5404. // Check if it's a empty paragraph
  5405. if (isEmpty(paraBefore))
  5406. paraBefore.innerHTML = "&nbsp;";
  5407. // Check if it's a empty paragraph
  5408. if (isEmpty(paraAfter))
  5409. paraAfter.innerHTML = "&nbsp;";
  5410. // Delete old contents
  5411. rng.deleteContents();
  5412. rngAfter.deleteContents();
  5413. rngBefore.deleteContents();
  5414. // Insert new paragraphs
  5415. if (tinyMCE.isOpera) {
  5416. paraBefore.normalize();
  5417. rngBefore.insertNode(paraBefore);
  5418. paraAfter.normalize();
  5419. rngBefore.insertNode(paraAfter);
  5420. } else {
  5421. paraAfter.normalize();
  5422. rngBefore.insertNode(paraAfter);
  5423. paraBefore.normalize();
  5424. rngBefore.insertNode(paraBefore);
  5425. }
  5426. //tinyMCE.debug("1: ", paraBefore.innerHTML, paraAfter.innerHTML);
  5427. } else {
  5428. body.innerHTML = "<" + blockName + ">&nbsp;</" + blockName + "><" + blockName + ">&nbsp;</" + blockName + ">";
  5429. paraAfter = body.childNodes[1];
  5430. }
  5431. inst.selection.moveToBookmark(b);
  5432. inst.selection.selectNode(paraAfter, true, true);
  5433. return true;
  5434. }
  5435. // Place first part within new paragraph
  5436. if (startChop.nodeName == blockName)
  5437. rngBefore.setStart(startChop, 0);
  5438. else
  5439. rngBefore.setStartBefore(startChop);
  5440. rngBefore.setEnd(startNode, startOffset);
  5441. paraBefore.appendChild(rngBefore.cloneContents());
  5442. // Place secound part within new paragraph
  5443. rngAfter.setEndAfter(endChop);
  5444. rngAfter.setStart(endNode, endOffset);
  5445. contents = rngAfter.cloneContents();
  5446. if (contents.firstChild && contents.firstChild.nodeName == blockName) {
  5447. /* var nodes = contents.firstChild.childNodes;
  5448. for (var i=0; i<nodes.length; i++) {
  5449. //tinyMCE.debug(nodes[i].nodeName);
  5450. if (nodes[i].nodeName != "BODY")
  5451. paraAfter.appendChild(nodes[i]);
  5452. }
  5453. */
  5454. paraAfter.innerHTML = contents.firstChild.innerHTML;
  5455. } else
  5456. paraAfter.appendChild(contents);
  5457. // Check if it's a empty paragraph
  5458. if (isEmpty(paraBefore))
  5459. paraBefore.innerHTML = "&nbsp;";
  5460. // Check if it's a empty paragraph
  5461. if (isEmpty(paraAfter))
  5462. paraAfter.innerHTML = "&nbsp;";
  5463. // Create a range around everything
  5464. rng = doc.createRange();
  5465. if (!startChop.previousSibling && startChop.parentNode.nodeName.toUpperCase() == blockName) {
  5466. rng.setStartBefore(startChop.parentNode);
  5467. } else {
  5468. if (rngBefore.startContainer.nodeName.toUpperCase() == blockName && rngBefore.startOffset == 0)
  5469. rng.setStartBefore(rngBefore.startContainer);
  5470. else
  5471. rng.setStart(rngBefore.startContainer, rngBefore.startOffset);
  5472. }
  5473. if (!endChop.nextSibling && endChop.parentNode.nodeName.toUpperCase() == blockName)
  5474. rng.setEndAfter(endChop.parentNode);
  5475. else
  5476. rng.setEnd(rngAfter.endContainer, rngAfter.endOffset);
  5477. // Delete all contents and insert new paragraphs
  5478. rng.deleteContents();
  5479. if (tinyMCE.isOpera) {
  5480. rng.insertNode(paraBefore);
  5481. rng.insertNode(paraAfter);
  5482. } else {
  5483. rng.insertNode(paraAfter);
  5484. rng.insertNode(paraBefore);
  5485. }
  5486. //tinyMCE.debug("2", paraBefore.innerHTML, paraAfter.innerHTML);
  5487. // Normalize
  5488. paraAfter.normalize();
  5489. paraBefore.normalize();
  5490. inst.selection.moveToBookmark(b);
  5491. inst.selection.selectNode(paraAfter, true, true);
  5492. return true;
  5493. },
  5494. _handleBackSpace : function(inst) {
  5495. var r = inst.getRng(), sn = r.startContainer, nv, s = false;
  5496. // Added body check for bug #1527787
  5497. if (sn && sn.nextSibling && sn.nextSibling.nodeName == "BR" && sn.parentNode.nodeName != "BODY") {
  5498. nv = sn.nodeValue;
  5499. // Handle if a backspace is pressed after a space character #bug 1466054 removed since fix for #1527787
  5500. /*if (nv != null && nv.length >= r.startOffset && nv.charAt(r.startOffset - 1) == ' ')
  5501. s = true;*/
  5502. // Only remove BRs if we are at the end of line #bug 1464152
  5503. if (nv != null && r.startOffset == nv.length)
  5504. sn.nextSibling.parentNode.removeChild(sn.nextSibling);
  5505. }
  5506. if (inst.settings.auto_resize)
  5507. inst.resizeToContent();
  5508. return s;
  5509. }
  5510. };
  5511. /* file:jscripts/tiny_mce/classes/TinyMCE_Layer.class.js */
  5512. function TinyMCE_Layer(id, bm) {
  5513. this.id = id;
  5514. this.blockerElement = null;
  5515. this.events = false;
  5516. this.element = null;
  5517. this.blockMode = typeof(bm) != 'undefined' ? bm : true;
  5518. this.doc = document;
  5519. };
  5520. TinyMCE_Layer.prototype = {
  5521. moveRelativeTo : function(re, p) {
  5522. var rep = this.getAbsPosition(re);
  5523. var w = parseInt(re.offsetWidth);
  5524. var h = parseInt(re.offsetHeight);
  5525. var e = this.getElement();
  5526. var ew = parseInt(e.offsetWidth);
  5527. var eh = parseInt(e.offsetHeight);
  5528. var x, y;
  5529. switch (p) {
  5530. case "tl":
  5531. x = rep.absLeft;
  5532. y = rep.absTop;
  5533. break;
  5534. case "tr":
  5535. x = rep.absLeft + w;
  5536. y = rep.absTop;
  5537. break;
  5538. case "bl":
  5539. x = rep.absLeft;
  5540. y = rep.absTop + h;
  5541. break;
  5542. case "br":
  5543. x = rep.absLeft + w;
  5544. y = rep.absTop + h;
  5545. break;
  5546. case "cc":
  5547. x = rep.absLeft + (w / 2) - (ew / 2);
  5548. y = rep.absTop + (h / 2) - (eh / 2);
  5549. break;
  5550. }
  5551. this.moveTo(x, y);
  5552. },
  5553. moveBy : function(x, y) {
  5554. var e = this.getElement();
  5555. this.moveTo(parseInt(e.style.left) + x, parseInt(e.style.top) + y);
  5556. },
  5557. moveTo : function(x, y) {
  5558. var e = this.getElement();
  5559. e.style.left = x + "px";
  5560. e.style.top = y + "px";
  5561. this.updateBlocker();
  5562. },
  5563. resizeBy : function(w, h) {
  5564. var e = this.getElement();
  5565. this.resizeTo(parseInt(e.style.width) + w, parseInt(e.style.height) + h);
  5566. },
  5567. resizeTo : function(w, h) {
  5568. var e = this.getElement();
  5569. if (w != null)
  5570. e.style.width = w + "px";
  5571. if (h != null)
  5572. e.style.height = h + "px";
  5573. this.updateBlocker();
  5574. },
  5575. show : function() {
  5576. var el = this.getElement();
  5577. if (el) {
  5578. el.style.display = 'block';
  5579. this.updateBlocker();
  5580. }
  5581. },
  5582. hide : function() {
  5583. var el = this.getElement();
  5584. if (el) {
  5585. el.style.display = 'none';
  5586. this.updateBlocker();
  5587. }
  5588. },
  5589. isVisible : function() {
  5590. return this.getElement().style.display == 'block';
  5591. },
  5592. getElement : function() {
  5593. if (!this.element)
  5594. this.element = this.doc.getElementById(this.id);
  5595. return this.element;
  5596. },
  5597. setBlockMode : function(s) {
  5598. this.blockMode = s;
  5599. },
  5600. updateBlocker : function() {
  5601. var e, b, x, y, w, h;
  5602. b = this.getBlocker();
  5603. if (b) {
  5604. if (this.blockMode) {
  5605. e = this.getElement();
  5606. x = this.parseInt(e.style.left);
  5607. y = this.parseInt(e.style.top);
  5608. w = this.parseInt(e.offsetWidth);
  5609. h = this.parseInt(e.offsetHeight);
  5610. b.style.left = x + 'px';
  5611. b.style.top = y + 'px';
  5612. b.style.width = w + 'px';
  5613. b.style.height = h + 'px';
  5614. b.style.display = e.style.display;
  5615. } else
  5616. b.style.display = 'none';
  5617. }
  5618. },
  5619. getBlocker : function() {
  5620. var d, b;
  5621. if (!this.blockerElement && this.blockMode) {
  5622. d = this.doc;
  5623. b = d.getElementById(this.id + "_blocker");
  5624. if (!b) {
  5625. b = d.createElement("iframe");
  5626. b.setAttribute('id', this.id + "_blocker");
  5627. b.style.cssText = 'display: none; position: absolute; left: 0; top: 0';
  5628. b.src = 'javascript:false;';
  5629. b.frameBorder = '0';
  5630. b.scrolling = 'no';
  5631. d.body.appendChild(b);
  5632. }
  5633. this.blockerElement = b;
  5634. }
  5635. return this.blockerElement;
  5636. },
  5637. getAbsPosition : function(n) {
  5638. var p = {absLeft : 0, absTop : 0};
  5639. while (n) {
  5640. p.absLeft += n.offsetLeft;
  5641. p.absTop += n.offsetTop;
  5642. n = n.offsetParent;
  5643. }
  5644. return p;
  5645. },
  5646. create : function(n, c, p, h) {
  5647. var d = this.doc, e = d.createElement(n);
  5648. e.setAttribute('id', this.id);
  5649. if (c)
  5650. e.className = c;
  5651. if (!p)
  5652. p = d.body;
  5653. if (h)
  5654. e.innerHTML = h;
  5655. p.appendChild(e);
  5656. return this.element = e;
  5657. },
  5658. exists : function() {
  5659. return this.doc.getElementById(this.id) != null;
  5660. },
  5661. parseInt : function(s) {
  5662. if (s == null || s == '')
  5663. return 0;
  5664. return parseInt(s);
  5665. },
  5666. remove : function() {
  5667. var e = this.getElement(), b = this.getBlocker();
  5668. if (e)
  5669. e.parentNode.removeChild(e);
  5670. if (b)
  5671. b.parentNode.removeChild(b);
  5672. }
  5673. };
  5674. /* file:jscripts/tiny_mce/classes/TinyMCE_Menu.class.js */
  5675. function TinyMCE_Menu() {
  5676. var id;
  5677. if (typeof(tinyMCE.menuCounter) == "undefined")
  5678. tinyMCE.menuCounter = 0;
  5679. id = "mc_menu_" + tinyMCE.menuCounter++;
  5680. TinyMCE_Layer.call(this, id, true);
  5681. this.id = id;
  5682. this.items = new Array();
  5683. this.needsUpdate = true;
  5684. };
  5685. TinyMCE_Menu.prototype = tinyMCE.extend(TinyMCE_Layer.prototype, {
  5686. init : function(s) {
  5687. var n;
  5688. // Default params
  5689. this.settings = {
  5690. separator_class : 'mceMenuSeparator',
  5691. title_class : 'mceMenuTitle',
  5692. disabled_class : 'mceMenuDisabled',
  5693. menu_class : 'mceMenu',
  5694. drop_menu : true
  5695. };
  5696. for (n in s)
  5697. this.settings[n] = s[n];
  5698. this.create('div', this.settings.menu_class);
  5699. },
  5700. clear : function() {
  5701. this.items = new Array();
  5702. },
  5703. addTitle : function(t) {
  5704. this.add({type : 'title', text : t});
  5705. },
  5706. addDisabled : function(t) {
  5707. this.add({type : 'disabled', text : t});
  5708. },
  5709. addSeparator : function() {
  5710. this.add({type : 'separator'});
  5711. },
  5712. addItem : function(t, js) {
  5713. this.add({text : t, js : js});
  5714. },
  5715. add : function(mi) {
  5716. this.items[this.items.length] = mi;
  5717. this.needsUpdate = true;
  5718. },
  5719. update : function() {
  5720. var e = this.getElement(), h = '', i, t, m = this.items, s = this.settings;
  5721. if (this.settings.drop_menu)
  5722. h += '<span class="mceMenuLine"></span>';
  5723. h += '<table border="0" cellpadding="0" cellspacing="0">';
  5724. for (i=0; i<m.length; i++) {
  5725. t = tinyMCE.xmlEncode(m[i].text);
  5726. c = m[i].class_name ? ' class="' + m[i].class_name + '"' : '';
  5727. switch (m[i].type) {
  5728. case 'separator':
  5729. h += '<tr class="' + s.separator_class + '"><td>';
  5730. break;
  5731. case 'title':
  5732. h += '<tr class="' + s.title_class + '"><td><span' + c +'>' + t + '</span>';
  5733. break;
  5734. case 'disabled':
  5735. h += '<tr class="' + s.disabled_class + '"><td><span' + c +'>' + t + '</span>';
  5736. break;
  5737. default:
  5738. h += '<tr><td><a href="' + tinyMCE.xmlEncode(m[i].js) + '" onmousedown="' + tinyMCE.xmlEncode(m[i].js) + ';return tinyMCE.cancelEvent(event);" onclick="return tinyMCE.cancelEvent(event);" onmouseup="return tinyMCE.cancelEvent(event);"><span' + c +'>' + t + '</span></a>';
  5739. }
  5740. h += '</td></tr>';
  5741. }
  5742. h += '</table>';
  5743. e.innerHTML = h;
  5744. this.needsUpdate = false;
  5745. this.updateBlocker();
  5746. },
  5747. show : function() {
  5748. var nl, i;
  5749. if (tinyMCE.lastMenu == this)
  5750. return;
  5751. if (this.needsUpdate)
  5752. this.update();
  5753. if (tinyMCE.lastMenu && tinyMCE.lastMenu != this)
  5754. tinyMCE.lastMenu.hide();
  5755. TinyMCE_Layer.prototype.show.call(this);
  5756. if (!tinyMCE.isOpera) {
  5757. // Accessibility stuff
  5758. /* nl = this.getElement().getElementsByTagName("a");
  5759. if (nl.length > 0)
  5760. nl[0].focus();*/
  5761. }
  5762. tinyMCE.lastMenu = this;
  5763. }
  5764. });
  5765. /* file:jscripts/tiny_mce/classes/TinyMCE_Compatibility.class.js */
  5766. if (!Function.prototype.call) {
  5767. Function.prototype.call = function() {
  5768. var a = arguments, s = a[0], i, as = '', r, o;
  5769. for (i=1; i<a.length; i++)
  5770. as += (i > 1 ? ',' : '') + 'a[' + i + ']';
  5771. o = s._fu;
  5772. s._fu = this;
  5773. r = eval('s._fu(' + as + ')');
  5774. s._fu = o;
  5775. return r;
  5776. };
  5777. };
  5778. /* file:jscripts/tiny_mce/classes/TinyMCE_Debug.class.js */
  5779. TinyMCE_Engine.prototype.debug = function() {
  5780. var m = "", a, i, l = tinyMCE.log.length;
  5781. for (i=0, a = this.debug.arguments; i<a.length; i++) {
  5782. m += a[i];
  5783. if (i<a.length-1)
  5784. m += ', ';
  5785. }
  5786. if (l < 1000)
  5787. tinyMCE.log[l] = "[debug] " + m;
  5788. };